最近在https://github.com/中使用一个SwipeMenuListView(左滑出菜单)的控件,先上效果图:
感觉还挺好用,这里记录一下使用方法:
public class SwipeMenuListView extends ListView {
//源码省略,请自行到github下载
}
可以看出直接使用这个控件即可,在xml中使用(记得把源码导入):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.baoyz.swipemenulistview.SwipeMenuListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
接下来是在主函数中的使用方法,这里就是在每一条listview中去添加右边的菜单:
mListView = (SwipeMenuListView) findViewById(R.id.listView);
mListView.setAdapter(mAdapter);
initSwipeMenu();
initListener();
重要的方法就是
initSwipeMenu()
和
initLisener()
,如下:
public void initSwipeMenu(){
// step 1. create a MenuCreator
SwipeMenuCreator creator = new SwipeMenuCreator() {
@Override
public void create(SwipeMenu menu) {
// create "share" item
SwipeMenuItem shareItem = new SwipeMenuItem(getApplicationContext());
// set item background
shareItem.setBackground(getResources().getDrawable(R.color.blue_color));
// set item width
shareItem.setWidth(dp2px(80)); //这里设定宽度为80,可以改
// set item title
shareItem.setTitle("share");
// set item title fontsize
shareItem.setTitleSize(18);
//set icon
shareItem.setIcon(R.drawable.ic_action_share);
// set item title font color
shareItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(shareItem);
// create "delete" item
SwipeMenuItem openItem = new SwipeMenuItem(getApplicationContext());
// set item background
openItem.setBackground(getResources().getDrawable(R.color.red_color));
// set item width
openItem.setWidth(dp2px(80));//这里设定宽度为80,可以改
// set item title
openItem.setTitle("delete");
// set item title fontsize
openItem.setTitleSize(18);
//set icon
openItem.setIcon(R.drawable.ic_action_discard);
// set item title font color
openItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(openItem);
}
};
// set creator
mListView.setMenuCreator(creator);
int count = mAppList.size();
mListView.setTotalItemNum(count);
}
private void initListener(){
// step 2. listener item click event
mListView.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
ApplicationInfo item = mAppList.get(position);
switch (index) {
case 1:
// open
// open(item);
mAppList.remove(position);
mAdapter.notifyDataSetChanged();
break;
}
return false;
}
});
// set SwipeListener
mListView.setOnSwipeListener(new SwipeMenuListView.OnSwipeListener() {
@Override
public void onSwipeStart(int position) {
// swipe start
}
@Override
public void onSwipeEnd(int position) {
// swipe end
}
});
// set MenuStateChangeListener
mListView.setOnMenuStateChangeListener(new SwipeMenuListView.OnMenuStateChangeListener() {
@Override
public void onMenuOpen(int position) {
}
@Override
public void onMenuClose(int position) {
}
});
// other setting
// listView.setCloseInterpolator(new BounceInterpolator());
// test item long click
mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getApplicationContext(), position + " long click", Toast.LENGTH_SHORT).show();
return false;
}
});
}
以上就是使用方法,注意一点,你的item的高度要控制好,因为如果高度不够的话左滑显示的菜单会有显示不全的问题。最后说源码中的一个小bug,当你左滑出菜单后,如果此时竖向滑动其他条目到顶端或底端的时候会这样:
看了源码发现是如果滑动其他条目的时候,在SwipeMenuListView中的onTouchEvent方法中
MotionEvent.ACTION_MOVE
这了设置了break:
if (!mTouchView.getSwipEnable() || mTouchPosition != mTouchView.getPosition()) { break; }那我们可以最简单的方法就是把这段代码注释掉就不会有这种划出界的现象了,如果说怕有问题,也可以自己加个标志位去判断,如下方法:
boolean letViewDispear //用这个标志位
boolean letViewDispear = false; //此标志用于有菜单的时候
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//在拦截处处理,在滑动设置了点击事件的地方也能swip,点击时又不能影响原来的点击事件
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mDownX = ev.getX();
mDownY = ev.getY();
boolean handled = super.onInterceptTouchEvent(ev);
mTouchState = TOUCH_STATE_NONE;
mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
View view = getChildAt(mTouchPosition - getFirstVisiblePosition());
//只在空的时候赋值 以免每次触摸都赋值,会有多个open状态
if (view instanceof SwipeMenuLayout) {
//如果有打开了 就拦截.
if (mTouchView != null && mTouchView.isOpen()) {
if(!inRangeOfView(mTouchView.getMenuView(), ev)){ //false 表示不在,true表示在
letViewDispear = true; //有菜单时设为true
return true; //true表示不往下执行了,false表示抛给父类去处理
}
}
mTouchView = (SwipeMenuLayout) view;
mTouchView.setSwipeDirection(mDirection);
}
//如果摸在另外个view
if (mTouchView != null && mTouchView.isOpen() && view != mTouchView) {
handled = true; //触摸在别的view就handle
}
if (mTouchView != null) {
mTouchView.onSwipe(ev);
}
return handled;
case MotionEvent.ACTION_MOVE:
//略,可以直接把这里的上述代码注释,也可以使用我们自己定义的标志位
case MotionEvent.ACTION_UP:
//略
}
return super.onInterceptTouchEvent(ev);
}
然后在OnTouchEvent方法MotionEvent.ACTION_MOVE中根据这个改上面的代码:
if (!mTouchView.getSwipEnable() || mTouchPosition != mTouchView.getPosition()) {
//TODO 这个判断不能break,原因是break会导致ActionMove不往下执行,影响ActionUp的操作,最终导致滑动到顶端或底端出现超界现象
if(!letViewDispear){
break;
}else {
letViewDispear = false;
}
}
好了,这样就不会因为break而影响到接下来MotionEvent.ACTION_UPd的处理了,以上就是对这个控件的学习心得,关于如何导入含源代码的第三方库类,可以参考文章: