使用几个月的IOS之后,发现IOS中侧滑删除俺就
大家好,自己开始学习Android已经差不多半年了吧,前前后后看了不少的博客获益匪浅。渐渐的随着技术的提升,慢慢感觉网上其它的一些功能的实现又不是那么完美,今天就给大家带来一篇在Android中完全仿照IOS侧滑删除的效果。
首先我们来看一下实现的效果如何:
第一张图片是展示删除的效果,删除时会有上缩动画效果
第二张图片是展示滑出删除按钮时的事件抢占,有删除按钮存在时需要抢占掉ListView的滑动事件,而且保证至多有1个删除按钮显示
所以说实现完美的侧滑删除效果需要了解Android中的事件分发机制,如果有不明白的同学可以去
郭神:
鸿前辈:
这两位前辈的博客里看事件分发章节的内容。
好了我们废话不多说,进入主题。
本例的侧滑删除用的是HorizontalScrollView来实现的。
首先我们先创建我们的activity_main.xml,主布局文件
xmlns:tools=""
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.horizontalslidelistview.MainActivity" >
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
是不是很简单,仅仅是只有一个自定义的ListView,不过我们先放过这个自定义的ListVIew,再来看看ListView中item的布局文件
item_horizontal_slide_listview.xml
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none" >
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
android:id="@+id/item_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:background="#EEEEEE"
android:paddingLeft="20dp"
android:textColor="#FF0000"
android:textSize="20sp" />
android:id="@+id/item_delete"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#FF0000"
android:text="删除" />
如果需要复杂一点儿的item样式,那就把item_text换成自己想要的布局就好了~
然后看我们的重头戏,adapter
public class HorizontalSlideAdapter extends ArrayAdapter {
/** 屏幕宽度 */
private int mScreenWidth;
/** 删除按钮事件 */
private DeleteButtonOnclickImpl mDelOnclickImpl;
/** HorizontalScrollView左右滑动事件 */
private ScrollViewScrollImpl mScrollImpl;
/** 布局参数,动态让HorizontalScrollView中的TextView宽度包裹父容器 */
private LinearLayout.LayoutParams mParams;
/** 记录滑动出删除按钮的itemView */
public HorizontalScrollView mScrollView;
/** touch事件锁定,如果已经有滑动出删除按钮的itemView,就屏蔽下一整次(down,move,up)的onTouch操作 */
public boolean mLockOnTouch = false;
public HorizontalSlideAdapter(Context context, List objects) {
super(context, 0, objects);
// 搞到屏幕宽度
Display defaultDisplay = ((Activity) context).getWindowManager()
.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
defaultDisplay.getMetrics(metrics);
mScreenWidth = metrics.widthPixels;
mParams = new LinearLayout.LayoutParams(mScreenWidth,
LinearLayout.LayoutParams.MATCH_PARENT);
// 初始化删除按钮事件与item滑动事件
mDelOnclickImpl = new DeleteButtonOnclickImpl();
mScrollImpl = new ScrollViewScrollImpl();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = View.inflate(getContext(),
R.layout.item_horizontal_slide_listview, null);
holder.scrollView = (HorizontalScrollView) convertView;
holder.scrollView.setOnTouchListener(mScrollImpl);
holder.infoTextView = (TextView) convertView
.findViewById(R.id.item_text);
// 设置item内容为fill_parent的
holder.infoTextView.setLayoutParams(mParams);
holder.deleteButton = (Button) convertView
.findViewById(R.id.item_delete);
holder.deleteButton.setOnClickListener(mDelOnclickImpl);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.position = position;
holder.deleteButton.setTag(holder);
holder.infoTextView.setText(getItem(position));
holder.scrollView.scrollTo(0, 0);
return convertView;
}
static class ViewHolder {
private HorizontalScrollView scrollView;
private TextView infoTextView;
private Button deleteButton;
private int position;
}
/** HorizontalScrollView的滑动事件 */
private class ScrollViewScrollImpl implements OnTouchListener {
/** 记录开始时的坐标 */
private float startX = 0;
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 如果有划出删除按钮的itemView,就让他滑回去并且锁定本次touch操作,解锁会在父组件的dispatchTouchEvent中进行
if (mScrollView != null) {
scrollView(mScrollView, HorizontalScrollView.FOCUS_LEFT);
mScrollView = null;
mLockOnTouch = true;
return true;
}
startX = event.getX();
break;
case MotionEvent.ACTION_UP:
HorizontalScrollView view = (HorizontalScrollView) v;
// 如果滑动了>50个像素,就显示出删除按钮
if (startX > event.getX() + 50) {
startX = 0;// 因为公用一个事件处理对象,防止错乱,还原startX值
scrollView(view, HorizontalScrollView.FOCUS_RIGHT);
mScrollView = view;
} else {
scrollView(view, HorizontalScrollView.FOCUS_LEFT);
}
break;
}
return false;
}
}
/** HorizontalScrollView左右滑动 */
public void scrollView(final HorizontalScrollView view, final int parameter) {
view.post(new Runnable() {
@Override
public void run() {
view.pageScroll(parameter);
}
});
}
/** 删除事件 */
private class DeleteButtonOnclickImpl implements OnClickListener {
@Override
public void onClick(View v) {
final ViewHolder holder = (ViewHolder) v.getTag();
Toast.makeText(getContext(), "删除第" + holder.position + "项",
Toast.LENGTH_SHORT).show();
Animation animation = AnimationUtils.loadAnimation(getContext(),
R.anim.anim_item_delete);
holder.scrollView.startAnimation(animation);
animation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
remove(getItem(holder.position));
}
});
}
}
}有点儿长,首先是获取当前屏幕宽度,态的给每一个ItemView让他填充父容器(因为宽度是屏幕宽度)。
再之后就是对onTouch事件的处理,这一点注释里面写的比较详细就不再赘述了。
看到这儿也许就会有点儿纳闷了,唉 既然吧事件锁上了,,怎么没见打开啊?
嗯,这也是我当时在编写这个侧滑时遇到的问题,我们不仅仅是只让删除按钮只出现一个就行了,我们还需要在出现删除按钮时也让ListView的滑动失效!