以前项目中用到了一个放qq的侧滑删除的效果,结果github上一搜就copy了一个,不得不说大神们写的真心牛逼,那个时候呢看到一个东西能用就可以了,也不管怎么实现的,现在反过来一看,原来自定义还可以这么玩,当然,前面项目中也因此出现了一个bug,就是我使用的是PulltorefreshScrollView,因此也出现了ScrollView跟ListView的事件冲突,呵呵,不怕笑话,当是体验不好,直接变成了长按删除了,嘻嘻!!自从前面研究了一下事件分发,因此解决了困扰了我很久的问题。
看一下侧滑删除效果图:
copy github上的pulltorefresh下拉刷新效果图:
不同的侧滑效果:
我们简单看一下大神的SwipeMenu实现方式:
1、SwipeMenuListView继承ListView。
public class SwipeMenuListView extends ListView {
2、重写setAdapter方法,然后创建一个SwipeMenuLayout包含我们自己adapter中getView返回的View跟我们的侧滑菜单。
@Override
public void setAdapter(ListAdapter adapter) {
super.setAdapter(new SwipeMenuAdapter(getContext(), adapter) {
@Override
public void createMenu(SwipeMenu menu) {
if (mMenuCreator != null) {
mMenuCreator.create(menu);
Log.e("TAG", "---createMenu--");
}
}
@Override
public void onItemClick(SwipeMenuView view, SwipeMenu menu,
int index) {
if (mOnMenuItemClickListener != null) {
mOnMenuItemClickListener.onMenuItemClick(
view.getPosition(), menu, index);
}
if (mTouchView != null) {
mTouchView.smoothCloseMenu();
}
}
});
}
SwipeMenuAdapter的方法可以看到,new了一个SwipeMenuLayout(FrameLayout)然后把我们的contentView跟swipeMenu放在一起了,
@Override
public View getView(int position, View convertView, ViewGroup parent) {
SwipeMenuLayout layout = null;
if (convertView == null) {
View contentView = mAdapter.getView(position, convertView, parent);
SwipeMenu menu = new SwipeMenu(mContext);
menu.setViewType(mAdapter.getItemViewType(position));
createMenu(menu);
SwipeMenuView menuView = new SwipeMenuView(menu,
(SwipeMenuListView) parent);
menuView.setOnSwipeItemClickListener(this);
SwipeMenuListView listView = (SwipeMenuListView) parent;
layout = new SwipeMenuLayout(contentView, menuView,
listView.getCloseInterpolator(),
listView.getOpenInterpolator());
layout.setPosition(position);
} else {
layout = (SwipeMenuLayout) convertView;
layout.closeMenu();
layout.setPosition(position);
View view = mAdapter.getView(position, layout.getContentView(),
parent);
}
return layout;
}
3、也是最重要的一步:就是监听ListView的事件,处理SwipeMenuLayout的子控件(contentView+menu)的摆放位置,从而显示menu跟隐藏menu
大致实现思路就是这样了的,代码太多我就不一一列出了,下面我会给出demo的下载地址,我相信大家自己是能够看懂的。因为我用的是PullToRefreshScrollView,也就是把侧滑删除ListView放在了ScrollView中,解决事件冲突:
思路:重写dispatchTouchEvent方法,通过判断滑动的距离来定义是否需要拦截掉和不拦截事件,从而解决事件冲突。一般都是放在父类中的onintecerpterTouchEvent方法中去实现,今天我们用另外一种方式,通过父类的requestDisallowInterceptTouchEvent(boolean flag);方法决定父类是否需要拦截子控件事件。
/**
* 处理ScrollerView嵌套ListView引发的事件冲突
*/
private int mLastY;
private int mLastX;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int action=ev.getAction();
switch(action){
case MotionEvent.ACTION_DOWN:
mLastX=(int) ev.getX();
mLastY=(int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
int duraX=Math.abs((int) (ev.getX()-mLastX));
int duraY=Math.abs((int) (ev.getY()-mLastY));
if((duraX>10&&duraY<40)||(mTouchState == TOUCH_STATE_X)){
/**
* 当x轴距离为>10并且y轴滑动距离<40的时候,认为是侧滑删除操作,父控件不拦截子控件的事件
*/
this.getParent().requestDisallowInterceptTouchEvent(true);
}else{
/**
* 拦截子控件的事件,交给父控件处理
*/
this.getParent().requestDisallowInterceptTouchEvent(false);
}
mLastX=(int) ev.getX();
mLastY=(int) ev.getY();
break;
}
return super.dispatchTouchEvent(ev);
}
对事件传递不是很熟悉的童鞋,也可以看看我前面写的两篇博客Android事件传递
是不是很简单哦,反正我是照着demo自己敲了很多遍,至少我觉得我收获挺多的。嘻嘻嘻~!!
最后附上我demo的链接地址:
https://github.com/913453448/SwipeMenuDemo.git