您的位置:首页 > 移动开发 > Android开发

[开源学习]SwipeMenuListView源码实现过程解析

2015-12-13 22:16 656 查看

SwipeMenuListView源码实现过程解析

  QQ消息窗口一个功能,拖动消息以后在Item中显示出两个按钮,感觉体验不错,虽然这个功能早就有了,但一直没有去思考过实现,于是决定去学习相同功能的开源控件源码-SwipeMenuListView。另外发现网上很多人写了它的使用方法,却没有人解析过它的实现过程,于是希望我文笔拙劣的这一篇,能让阅读之人有所收获。

首先我们先看看官方Demo效果:



再看看项目类:



重要的信息类、接口

  首先先简单地了解这个开源项目中的几个信息类、和几个接口,把”好戏”留在后头。

SwipeMenu:

public class SwipeMenu {
private Context mContext;
private List<SwipeMenuItem> mItems;
private int mViewType;
public SwipeMenu(Context context) {
mContext = context;
mItems = new ArrayList<SwipeMenuItem>();
}
public Context getContext() {
return mContext;
}
public void addMenuItem(SwipeMenuItem item) {
mItems.add(item);
}
public void removeMenuItem(SwipeMenuItem item) {
mItems.remove(item);
}
...//此处省去部分操作SwipeMenuItem方法~
}


SwipeMenuItem:

public class SwipeMenuItem {

private int id;
private Context mContext;
private String title;
private Drawable icon;
private Drawable background;
private int titleColor;
private int titleSize;
private int width;
public SwipeMenuItem(Context context) {
mContext = context;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
...//此处省去很多get和set方法~
}


  明显,SwipeMenuItem就是拖动菜单的信息元素,它封装好方法来对拖动菜单子项进行设置的,SwipeMenu是一个装载这些信息容器List,可以对SwipeMenuItem添加和移除等等操作。

SwipeMenuCreator:

public interface SwipeMenuCreator {
void create(SwipeMenu menu);
}


  这个接口用于设置回调SwipeMenu的信息,在SwipeMenuListView中(setMenuCreator)要用这个接口来将拖动菜单的信息传入,然后生成对应的拖动菜单,具体后面分析SwipeMenuListView类的时候会细讲,这里只需要大概知道就好。

另外还有下面这三个接口:

public static interface OnMenuItemClickListener {
boolean onMenuItemClick(int position, SwipeMenu menu, int index);
}
public static interface OnSwipeListener {
void onSwipeStart(int position);

void onSwipeEnd(int position);
}
public static interface OnMenuStateChangeListener {
void onMenuOpen(int position);

void onMenuClose(int position);
}


  分别用于实现拖动菜单的点击事件、拖动时的坐标更新、拖动菜单状态改变。

  另外还设置了系统的动画补间器接口,用于修饰打开和移除时的动画效果:

private Interpolator mCloseInterpolator;
private Interpolator mOpenInterpolator;


核心的部分

SwipeMenuView

代码:

public class SwipeMenuView extends LinearLayout implements OnClickListener {

private SwipeMenuListView mListView;
private SwipeMenuLayout mLayout;
private SwipeMenu mMenu;
private OnSwipeItemClickListener onItemClickListener;
private int position;

public int getPosition() {
return position;
}

public void setPosition(int position) {
this.position = position;
}

public SwipeMenuView(SwipeMenu menu, SwipeMenuListView listView) {
super(menu.getContext());
mListView = listView;
mMenu = menu;
List<SwipeMenuItem> items = menu.getMenuItems();
int id = 0;
for (SwipeMenuItem item : items) {
addItem(item, id++);
}
}

private void addItem(SwipeMenuItem item, int id) {
LayoutParams params = new LayoutParams(item.getWidth(),
LayoutParams.MATCH_PARENT);
LinearLayout parent = new LinearLayout(getContext());
parent.setId(id);
parent.setGravity(Gravity.CENTER);
parent.setOrientation(LinearLayout.VERTICAL);
parent.setLayoutParams(params);
parent.setBackgroundDrawable(item.getBackground());
parent.setOnClickListener(this);
addView(parent);

if (item.getIcon() != null) {
parent.addView(createIcon(item));
}
if (!TextUtils.isEmpty(item.getTitle())) {
parent.addView(createTitle(item));
}

}

private ImageView createIcon(SwipeMenuItem item) {
ImageView iv = new ImageView(getContext());
iv.setImageDrawable(item.getIcon());
return iv;
}

private TextView createTitle(SwipeMenuItem item) {
TextView tv = new TextView(getContext());
tv.setText(item.getTitle());
tv.setGravity(Gravity.CENTER);
tv.setTextSize(item.getTitleSize());
tv.setTextColor(item.getTitleColor());
return tv;
}
//此处省略部分方法。
public static interface OnSwipeItemClickListener {
void onItemClick(SwipeMenuView view, SwipeMenu menu, int index);
}
}


  这个SwipeMenuView就是侧滑后所看到的菜单,通过它的构造方法将SwipeMenu传进来,for循环遍历List中的元素,通过createIcon、createTitle新建ImageView和TextView对象,实例化一个LinearLayout对象装载ImageView和TextView,将这个LinearLayout添加到自身。点击事件触发时通过接口回调(OnSwipeItemClickListener)将自己及Menu信息传出去。

SwipeMenuLayout:

  因为整个SwipeMenuLayout(继承自FrameLayout)的代码稍微多,所以这里分开的挑出几个核心的方法进行解析。

其构造方法:

public SwipeMenuLayout(View contentView, SwipeMenuView menuView,
Interpolator closeInterpolator, Interpolator openInterpolator) {
super(contentView.getContext());
mCloseInterpolator = closeInterpolator;
mOpenInterpolator = openInterpolator;
mContentView = contentView;
mMenuView = menuView;
mMenuView.setLayout(this);
init();
}


  通过构造方法传入SwipeMenuView,及传入动画补间器(加速、减速…),再调用init方法初始化:

private void init() {
setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
mGestureListener = new SimpleOnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
isFling = false;
return true;
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2,
float velocityX, float velocityY) {
// TODO
if (Math.abs(e1.getX() - e2.getX()) > MIN_FLING
&& velocityX < MAX_VELOCITYX) {
isFling = true;
}
return super.onFling(e1, e2, velocityX, velocityY);
}
};
mGestureDetector = new GestureDetectorCompat(getContext(),
mGestureListener);
if (mCloseInterpolator != null) {
mCloseScroller = ScrollerCompat.create(getContext(),
mCloseInterpolator);
} else {
mCloseScroller = ScrollerCompat.create(getContext());
}
if (mOpenInterpolator != null) {
mOpenScroller = ScrollerCompat.create(getContext(),
mOpenInterpolator);
} else {
mOpenScroller = ScrollerCompat.create(getContext());
}

LayoutParams contentParams = new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
mContentView.setLayoutParams(contentParams);
if (mContentView.getId() < 1) {
mContentView.setId(CONTENT_VIEW_ID);
}
mMenuView.setId(MENU_VIEW_ID);
mMenuView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
addView(mContentView);
addView(mMenuView);
}


  监听手势动作,onFling设置最小滑动动作,设置添加移除的动画效果的补间器Interpolator,及关键在最后添加mContentView及mMenuView,前者是ListView的本身的Item,后者是SwipeMenuView即拖动后显示的菜单。

onSwipe:

public boolean onSwipe(MotionEvent event) {
mGestureDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = (int) event.getX();
isFling = false;
break;
case MotionEvent.ACTION_MOVE:
// Log.i("byz", "downX = " + mDownX + ", moveX = " + event.getX());
int dis = (int) (mDownX - event.getX());
if (state == STATE_OPEN) {
dis += mMenuView.getWidth()*mSwipeDirection;;
}
swipe(dis);
break;
case MotionEvent.ACTION_UP:
if ((isFling || Math.abs(mDownX - event.getX()) > (mMenuView.getWidth() / 2)) &&
Math.signum(mDownX - event.getX()) == mSwipeDirection) {
// open
smoothOpenMenu();
} else {
// close
smoothCloseMenu();
return false;
}
break;
}
return true;
}


里面ACTION_MOVE调用的swipe(dis)方法:

private void swipe(int dis) {
if (Math.signum(dis) != mSwipeDirection) {
dis = 0;
} else if (Math.abs(dis) > mMenuView.getWidth()) {
dis = mMenuView.getWidth()*mSwipeDirection;
}

mContentView.layout(-dis, mContentView.getTop(),
mContentView.getWidth() -dis, getMeasuredHeight());

if (mSwipeDirection == SwipeMenuListView.DIRECTION_LEFT) {

mMenuView.layout(mContentView.getWidth() - dis, mMenuView.getTop(),
mContentView.getWidth() + mMenuView.getWidth() - dis,
mMenuView.getBottom());
} else {
mMenuView.layout(-mMenuView.getWidth() - dis, mMenuView.getTop(),
- dis, mMenuView.getBottom());
}
}


  里面ACTION_UP时调用的方法smoothCloseMenu、smoothOpenMenu:

public void smoothCloseMenu() {
state = STATE_CLOSE;
if (mSwipeDirection == SwipeMenuListView.DIRECTION_LEFT) {
mBaseX = -mContentView.getLeft();
mCloseScroller.startScroll(0, 0, mMenuView.getWidth(), 0, 350);
} else {
mBaseX = mMenuView.getRight();
mCloseScroller.startScroll(0, 0, mMenuView.getWidth(), 0, 350);
}
postInvalidate();
}

public void smoothOpenMenu() {
state = STATE_OPEN;
if (mSwipeDirection == SwipeMenuListView.DIRECTION_LEFT) {
mOpenScroller.startScroll(-mContentView.getLeft(), 0, mMenuView.getWidth(), 0, 350);
} else {
mOpenScroller.startScroll(mContentView.getLeft(), 0, mMenuView.getWidth(), 0, 350);
}
postInvalidate();
}


  这个onSwipe方法是在外部将SwipeMenuListView的触摸事件传入给SwipeMenuLayout时进行调用的。里面的mSwipeDirection是用于设置拖动菜单的出现位置(左边或右边)。将dis(指的是偏移量)传入到swipe方法中,swipe方法中得到偏移量再对mMenuView进行位置的操作,也就是拖动菜单动作。

  ACTION_UP中判断坐标偏移量足够大则调用smoothOpenMenu()开启拖动菜单,否则关闭调用smoothCloseMenu()关闭拖动菜单。

  在解析SwipeMenuListView之前,我们先解析SwipeMenuAdapter这个类,它是实现这个ListView拖动菜单功能十分关键的部分。

  先看看它的核心部分的代码:

public class SwipeMenuAdapter implements WrapperListAdapter,
OnSwipeItemClickListener {

private ListAdapter mAdapter;
private Context mContext;
private SwipeMenuListView.OnMenuItemClickListener onMenuItemClickListener;

public SwipeMenuAdapter(Context context, ListAdapter adapter) {
mAdapter = adapter;
mContext = context;
}

@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(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);
}
if (mAdapter instanceof BaseSwipListAdapter) {
boolean swipEnable = (((BaseSwipListAdapter) mAdapter).getSwipEnableByPosition(position));
layout.setSwipEnable(swipEnable);
}
return layout;
}

public void createMenu(SwipeMenu menu) {
// Test Code
SwipeMenuItem item = new SwipeMenuItem(mContext);
item.setTitle("Item 1");
item.setBackground(new ColorDrawable(Color.GRAY));
item.setWidth(300);
menu.addMenuItem(item);

item = new SwipeMenuItem(mContext);
item.setTitle("Item 2");
item.setBackground(new ColorDrawable(Color.RED));
item.setWidth(300);
menu.addMenuItem(item);
}

//此处省略掉很多实现Adapter方法及一些简单操作方法
}


  看看它的构造方法,传进来了一个Adapter,它自身不就是adapter吗,为什么会传进一个Adapter?事实上是SwipeMenuListView在重写setAdapter的地方,将外部传入的Adapter赋给了它,SwipeMenuListView重写的这个我后面再讲。两个Adapter是相互衔接的,或者应该这样说,SwipeMenuAdapter是构造在SwipeMenuListView的Adapter里面的。

  我们继续看,SwipeMenuAdapter中的getView方法里面通过以下代码获得一个contentView,可以看到,它的数据来源都是从构造方法传进来的Adapter中get的。

View contentView = mAdapter.getView(position, convertView, parent);


SwipeMenuListView listView = (SwipeMenuListView) parent;
layout = new SwipeMenuLayout(contentView, menuView,listView.getCloseInterpolator(),listView.getOpenInterpolator());


  然后将得到的这个contentView作为参数去新建一个SwipeMenuLayout,这不就是文章前面解析过的源码吗!传进去的contentView(View)和menuView(SwipeMenuView)就生成了一个新的SwipeMenuLayout并返回!这里耦合的特别好,无论原本ListView的item子项目是构件,都将作为SwipeMenuLayout的一部分,和拖动菜单是分开的,二者完全独立,只有在这个getView方法中才将二者合并。

SwipeMenuListView

  终于到这个 最核心的类了,它继承自FrameLayout,首先依然从构造方法开始看起:

public SwipeMenuListView(Context context) {
super(context);
init();
}
public SwipeMenuListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public SwipeMenuListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
MAX_X = dp2px(MAX_X);
MAX_Y = dp2px(MAX_Y);
mTouchState = TOUCH_STATE_NONE;
}


  构造方法中init()设置了一下最大滑动距离,这个距离用于onInterceptTouchEvent判定是否要拦截点击事件,具体我在下面的onInterceptTouchEvent方法解析中一起讲。

@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 (mTouchView == null && view instanceof SwipeMenuLayout) {
mTouchView = (SwipeMenuLayout) view;
}
//如果摸在
if(mTouchView != null && mTouchView.isOpen() && view != mTouchView){
handled =  true;
}

if (mTouchView != null) {
mTouchView.onSwipe(ev);
}
return handled;
case MotionEvent.ACTION_MOVE:
float dy = Math.abs((ev.getY() - mDownY));
float dx = Math.abs((ev.getX() - mDownX));
if (Math.abs(dy) > MAX_Y || Math.abs(dx) > MAX_X) {
return true;
}
}
return super.onInterceptTouchEvent(ev);
}


  onInterceptTouchEvent是用于Touch事件的拦截,当返回true的时候,事件会在当前这个ViewGroud被拦截,不继续往下传,并在这一级的View开始消费事件。可以在ACTION_MOVE中看到它时这样操作的:判断当Math.abs(dy) > MAX_Y || Math.abs(dx) > MAX_X,即Y坐标的偏移大雨MAX_Y或X坐标的偏移大于MAX_X时,返回true,拦截事件。

  作者真的很细心,这个是为了当我们打开拖动菜单后,能够在拖动菜单的范围内触摸移动来拖动某个Item。因为只要我们移动超过这个偏移的判定值,不把事件传递到Item项中,直接能够拖动Item,佩服作者考虑的如此周全。

  接着继续往下看其TouchEvent事件处理,因为代码比较多,我们将Event事件分两部分的case看。 

  

- case:MotionEvent.ACTION_DOWN

@Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() != MotionEvent.ACTION_DOWN && mTouchView == null)
return super.onTouchEvent(ev);
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
int oldPos = mTouchPosition;
mDownX = ev.getX();
mDownY = ev.getY();
mTouchState = TOUCH_STATE_NONE;

mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());

if (mTouchPosition == oldPos && mTouchView != null
&& mTouchView.isOpen()) {
mTouchState = TOUCH_STATE_X;
mTouchView.onSwipe(ev);
return true;
}

View view = getChildAt(mTouchPosition - getFirstVisiblePosition());

if (mTouchView != null && mTouchView.isOpen()) {
mTouchView.smoothCloseMenu();
mTouchView = null;
// return super.onTouchEvent(ev);
// try to cancel the touch event
MotionEvent cancelEvent = MotionEvent.obtain(ev);
cancelEvent.setAction(MotionEvent.ACTION_CANCEL);
onTouchEvent(cancelEvent);
if (mOnMenuStateChangeListener != null) {
mOnMenuStateChangeListener.onMenuClose(oldPos);
}
return true;
}
if (view instanceof SwipeMenuLayout) {
mTouchView = (SwipeMenuLayout) view;
mTouchView.setSwipeDirection(mDirection);
}
if (mTouchView != null) {
mTouchView.onSwipe(ev);
}
break;


  这儿关键的代码在于:

mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());


View view = getChildAt(mTouchPosition - getFirstVisiblePosition());


  因为ListView是没有ItemOntouch的监听API,所以我们只能自己通过上面的方法来计算当前拖动的item是第几个Item,然后对其进行操作。pointToPosition可以获得点击位置坐标上的Item是第几个,然后再通过getChildAt计算出当前这个item所在的位置(层级),mTouchPosition - getFirstVisiblePosition()就是计算点击的Itemp在当前显示的ListView的Child中的位置(层级)。

case ACTION_MOVE and ACTION_UP:

case MotionEvent.ACTION_MOVE:
//有些可能有header,要减去header再判断
mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY()) - getHeaderViewsCount();
//如果滑动了一下没完全展现,就收回去,这时候mTouchView已经赋值,再滑动另外一个不可以swip的view
//会导致mTouchView swip 。 所以要用位置判断是否滑动的是一个view
if (!mTouchView.getSwipEnable() || mTouchPosition != mTouchView.getPosition()) {
break;
}
float dy = Math.abs((ev.getY() - mDownY));
float dx = Math.abs((ev.getX() - mDownX));
if (mTouchState == TOUCH_STATE_X) {
if (mTouchView != null) {
mTouchView.onSwipe(ev);
}
getSelector().setState(new int[]{0});
ev.setAction(MotionEvent.ACTION_CANCEL);
super.onTouchEvent(ev);
return true;
} else if (mTouchState == TOUCH_STATE_NONE) {
if (Math.abs(dy) > MAX_Y) {
mTouchState = TOUCH_STATE_Y;
} else if (dx > MAX_X) {
mTouchState = TOUCH_STATE_X;
if (mOnSwipeListener != null) {
mOnSwipeListener.onSwipeStart(mTouchPosition);
}
}
}
case MotionEvent.ACTION_UP:
if (mTouchState == TOUCH_STATE_X) {
if (mTouchView != null) {
boolean isBeforeOpen = mTouchView.isOpen();
mTouchView.onSwipe(ev);
boolean isAfterOpen = mTouchView.isOpen();
if (isBeforeOpen != isAfterOpen && mOnMenuStateChangeListener != null) {
if (isAfterOpen) {
mOnMenuStateChangeListener.onMenuOpen(mTouchPosition);
} else {
mOnMenuStateChangeListener.onMenuClose(mTouchPosition);
}
}
if (!isAfterOpen) {
mTouchPosition = -1;
mTouchView = null;
}
}
if (mOnSwipeListener != null) {
mOnSwipeListener.onSwipeEnd(mTouchPosition);
}
ev.setAction(MotionEvent.ACTION_CANCEL);
super.onTouchEvent(ev);
return true;
}
break;
}
return super.onTouchEvent(ev);


  作者自己注释了的那部分我就不说了,在Down的时候已经得到了我们需要操作的那个Item,强制转成SwipeMenuLayout类型(当然还是有instanceof判定),然后在MOVE里面进行坐标上的移动,以及一些操作细节处理,一次只有显示一个拖动菜单。

SwipeMenuListView官方DEMO

看完解析完项目实现,就再简单看看DEMO吧。

DEMO中的SimpleActivity,就是上面gif图的效果。

部分定义:

private List<ApplicationInfo> mAppList;
private AppAdapter mAdapter;
private SwipeMenuListView mListView;


  Demo里的Item图片是来自于手机中应用的ICON图标,因而它定义了List mAppList,然后再getView的方法中通过以下得到ICON图标和应用名字:

ApplicationInfo item = getItem(position);
holder.iv_icon.setImageDrawable(item.loadIcon(getPackageManager()));
holder.tv_name.setText(item.loadLabel(getPackageManager()));


  这与源码本身功能无关。接下来我们看AppAdapter的定义及它的父类:

class AppAdapter extends BaseSwipListAdapter {

@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = View.inflate(getApplicationContext(),
R.layout.item_list_app, null);
new ViewHolder(convertView);
}
ViewHolder holder = (ViewHolder) convertView.getTag();
ApplicationInfo item = getItem(position);
holder.iv_icon.setImageDrawable(item.loadIcon(getPackageManager()));
holder.tv_name.setText(item.loadLabel(getPackageManager()));
holder.iv_icon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(SimpleActivity.this, "iv_icon_click", Toast.LENGTH_SHORT).show();
}
});
holder.tv_name.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(SimpleActivity.this,"iv_icon_click",Toast.LENGTH_SHORT).show();
}
});
return convertView;
}
//省略去一堆简单的重写方法、ViewHolder定义即接口。
}


public abstract class BaseSwipListAdapter extends BaseAdapter {
public boolean getSwipEnableByPosition(int position){
return true;
}
}


  AppAdapter的定义代码跟我们自己平时写的没有什么区别,实现BaseAdapter中的抽象方法,设置ViewHolder等等。

AppAdapter的父类只定义了一个接口,这个接口用于设定是否设置拖动菜单。

(这个我觉得已经不需要讲了,使用直接去下载源码用用就好了。)

  具体实现代码:

mAppList = getPackageManager().getInstalledApplications(0);
mListView = (SwipeMenuListView) findViewById(R.id.listView);
mAdapter = new AppAdapter();
mListView.setAdapter(mAdapter);
// step 1. create a MenuCreator
SwipeMenuCreator creator = new SwipeMenuCreator() {
@Override
public void create(SwipeMenu menu) {
// create "open" item
SwipeMenuItem openItem = new SwipeMenuItem(
getApplicationContext());
// set item background
openItem.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9,
0xCE)));
// set item width
openItem.setWidth(dp2px(90));
// set item title
openItem.setTitle("Open");
// set item title fontsize
openItem.setTitleSize(18);
// set item title font color
openItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(openItem);

// create "delete" item
SwipeMenuItem deleteItem = new SwipeMenuItem(
getApplicationContext());
// set item background
deleteItem.setBackground(new ColorDrawable(Color.rgb(0xF9,
0x3F, 0x25)));
// set item width
deleteItem.setWidth(dp2px(90));
// set a icon
deleteItem.setIcon(R.drawable.ic_delete);
// add to menu
menu.addMenuItem(deleteItem);
}
};
// set creator
mListView.setMenuCreator(creator);

// 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 0:
open(item);
break;
case 1:
mAppList.remove(position);
mAdapter.notifyDataSetChanged();
break;
}
return false;
}
});


到此SwipeMenuListView源码解析已完毕,谢谢阅读!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息