【转】Android 实现ListView的滑动删除效果

http://www.cnblogs.com/weixiao870428/p/3524055.html

http://download.csdn.net/download/love_javc_you/8533495

首先,这是转载过来的,里面对于手势以及事件分发部分写的还比较可以

用过微信的都知道,微信对话列表滑动删除效果是很不错的,这个效果我们也可以有。思路其实很简单,弄个ListView,然后里面的每个item做成一个可以滑动的自定义控件即可。由于ListView是上下滑动而item是左右滑动,因此会有滑动冲突,也许你需要了解下android中点击事件的派发流程,请参考Android源码分析-点击事件派发机制。我的解决思路是这样的:重写ListView的onInterceptTouchEvent方法,在move的时候做判断,如果是左右滑动就返回false,否则返回true;重写SlideView(即自定义item控件)的onTouchEvent方法来处理滑动。整个思路没有问题,滑动冲突也解决了,可是ListView无法得到焦点了,也就是ListView无法处理点击事件了。让我们回想下问题出在哪里:我的理解是这样的,上述处理滑动本身没有问题,但是有一个副作用,就是会让外层View失去焦点且无法处理点击事件。常见的滑动冲突场景,比如launcher内部嵌入ListView却是没有问题的,因为这个时候launcher不需要获得焦点,需要获得焦点的是内部的ListView。因此,上述处理方式对于外部需要获得焦点的情况(比如外部是ListView)就不太适合了。于是我就和ttdevs探讨,发现他采用了另外一种思路,我从来没有想过还可以这样玩。下面介绍他的思路。

新的思路

不考虑那么复杂,不采用主流玩法,所有的事件均由外层的ListView做拦截,同时把事件传递给SlideView做滑动,这种实现的确可以达到效果,而且代码很简单,根本不需要处理什么复杂的滑动冲突。

效果

下面分别为微信和高仿效果

代码分析

先看SlideView是如何实现的

看layout xml:

 

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <merge xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent" >
  5. <LinearLayout
  6. android:id="@+id/view_content"
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent"
  9. android:orientation="horizontal" >
  10. </LinearLayout>
  11. <RelativeLayout
  12. android:id="@+id/holder"
  13. android:layout_width="120dp"
  14. android:layout_height="match_parent"
  15. android:clickable="true"
  16. android:background="@drawable/holder_bg">
  17. <TextView
  18. android:id="@+id/delete"
  19. android:layout_width="wrap_content"
  20. android:layout_height="wrap_content"
  21. android:drawableLeft="@drawable/del_icon_normal"
  22. android:layout_centerInParent="true"
  23. android:gravity="center"
  24. android:textColor="@color/floralwhite"
  25. android:text="删除" />
  26. </RelativeLayout>
  27. </merge>
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <merge xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.   
  6.     <LinearLayout  
  7.         android:id="@+id/view_content"  
  8.         android:layout_width="match_parent"  
  9.         android:layout_height="match_parent"  
  10.         android:orientation="horizontal" >  
  11.     </LinearLayout>  
  12.   
  13.     <RelativeLayout  
  14.         android:id="@+id/holder"  
  15.         android:layout_width="120dp"  
  16.         android:layout_height="match_parent"  
  17.         android:clickable="true"  
  18.         android:background="@drawable/holder_bg">  
  19.   
  20.         <TextView  
  21.             android:id="@+id/delete"  
  22.             android:layout_width="wrap_content"  
  23.             android:layout_height="wrap_content"  
  24.             android:drawableLeft="@drawable/del_icon_normal"  
  25.             android:layout_centerInParent="true"  
  26.             android:gravity="center"  
  27.             android:textColor="@color/floralwhite"  
  28.             android:text="删除" />  
  29.     </RelativeLayout>  
  30.   
  31. </merge>  

上述xml文件中,所有的view都会被放在view_content中,而holder是放置诸如删除按钮之类的东西,我们的SlideView会加载这个布局。

 

再看SlideView.java:

 

  1. /**
  2. * SlideView 继承自LinearLayout
  3. */
  4. public class SlideView extends LinearLayout {
  5. private static final String TAG = "SlideView";
  6. private Context mContext;
  7. // 用来放置所有view的容器
  8. private LinearLayout mViewContent;
  9. // 用来放置内置view的容器,比如删除 按钮
  10. private RelativeLayout mHolder;
  11. // 弹性滑动对象,提供弹性滑动效果
  12. private Scroller mScroller;
  13. // 滑动回调接口,用来向上层通知滑动事件
  14. private OnSlideListener mOnSlideListener;
  15. // 内置容器的宽度 单位:dp
  16. private int mHolderWidth = 120;
  17. // 分别记录上次滑动的坐标
  18. private int mLastX = 0;
  19. private int mLastY = 0;
  20. // 用来控制滑动角度,仅当角度a满足如下条件才进行滑动:tan a = deltaX / deltaY > 2
  21. private static final int TAN = 2;
  22. public interface OnSlideListener {
  23. // SlideView的三种状态:开始滑动,打开,关闭
  24. public static final int SLIDE_STATUS_OFF = 0;
  25. public static final int SLIDE_STATUS_START_SCROLL = 1;
  26. public static final int SLIDE_STATUS_ON = 2;
  27. /**
  28. * @param view
  29. * current SlideView
  30. * @param status
  31. * SLIDE_STATUS_ON, SLIDE_STATUS_OFF or
  32. * SLIDE_STATUS_START_SCROLL
  33. */
  34. public void onSlide(View view, int status);
  35. }
  36. public SlideView(Context context) {
  37. super(context);
  38. initView();
  39. }
  40. public SlideView(Context context, AttributeSet attrs) {
  41. super(context, attrs);
  42. initView();
  43. }
  44. private void initView() {
  45. mContext = getContext();
  46. // 初始化弹性滑动对象
  47. mScroller = new Scroller(mContext);
  48. // 设置其方向为横向
  49. setOrientation(LinearLayout.HORIZONTAL);
  50. // 将slide_view_merge加载进来
  51. View.inflate(mContext, R.layout.slide_view_merge, this);
  52. mViewContent = (LinearLayout) findViewById(R.id.view_content);
  53. mHolderWidth = Math.round(TypedValue.applyDimension(
  54. TypedValue.COMPLEX_UNIT_DIP, mHolderWidth, getResources()
  55. .getDisplayMetrics()));
  56. }
  57. // 设置按钮的内容,也可以设置图标啥的,我没写
  58. public void setButtonText(CharSequence text) {
  59. ((TextView) findViewById(R.id.delete)).setText(text);
  60. }
  61. // 将view加入到ViewContent中
  62. public void setContentView(View view) {
  63. mViewContent.addView(view);
  64. }
  65. // 设置滑动回调
  66. public void setOnSlideListener(OnSlideListener onSlideListener) {
  67. mOnSlideListener = onSlideListener;
  68. }
  69. // 将当前状态置为关闭
  70. public void shrink() {
  71. if (getScrollX() != 0) {
  72. this.smoothScrollTo(0, 0);
  73. }
  74. }
  75. // 根据MotionEvent来进行滑动,这个方法的作用相当于onTouchEvent
  76. // 如果你不需要处理滑动冲突,可以直接重命名,照样能正常工作
  77. public void onRequireTouchEvent(MotionEvent event) {
  78. int x = (int) event.getX();
  79. int y = (int) event.getY();
  80. int scrollX = getScrollX();
  81. Log.d(TAG, "x=" + x + " y=" + y);
  82. switch (event.getAction()) {
  83. case MotionEvent.ACTION_DOWN: {
  84. if (!mScroller.isFinished()) {
  85. mScroller.abortAnimation();
  86. }
  87. if (mOnSlideListener != null) {
  88. mOnSlideListener.onSlide(this,
  89. OnSlideListener.SLIDE_STATUS_START_SCROLL);
  90. }
  91. break;
  92. }
  93. case MotionEvent.ACTION_MOVE: {
  94. int deltaX = x - mLastX;
  95. int deltaY = y - mLastY;
  96. if (Math.abs(deltaX) < Math.abs(deltaY) * TAN) {
  97. // 滑动不满足条件,不做横向滑动
  98. break;
  99. }
  100. // 计算滑动终点是否合法,防止滑动越界
  101. int newScrollX = scrollX - deltaX;
  102. if (deltaX != 0) {
  103. if (newScrollX < 0) {
  104. newScrollX = 0;
  105. else if (newScrollX > mHolderWidth) {
  106. newScrollX = mHolderWidth;
  107. }
  108. this.scrollTo(newScrollX, 0);
  109. }
  110. break;
  111. }
  112. case MotionEvent.ACTION_UP: {
  113. int newScrollX = 0;
  114. // 这里做了下判断,当松开手的时候,会自动向两边滑动,具体向哪边滑,要看当前所处的位置
  115. if (scrollX - mHolderWidth * 0.75 > 0) {
  116. newScrollX = mHolderWidth;
  117. }
  118. // 慢慢滑向终点
  119. this.smoothScrollTo(newScrollX, 0);
  120. // 通知上层滑动事件
  121. if (mOnSlideListener != null) {
  122. mOnSlideListener.onSlide(this,
  123. newScrollX == 0 ? OnSlideListener.SLIDE_STATUS_OFF
  124. : OnSlideListener.SLIDE_STATUS_ON);
  125. }
  126. break;
  127. }
  128. default:
  129. break;
  130. }
  131. mLastX = x;
  132. mLastY = y;
  133. }
  134. private void smoothScrollTo(int destX, int destY) {
  135. // 缓慢滚动到指定位置
  136. int scrollX = getScrollX();
  137. int delta = destX - scrollX;
  138. // 以三倍时长滑向destX,效果就是慢慢滑动
  139. mScroller.startScroll(scrollX, 0, delta, 0, Math.abs(delta) * 3);
  140. invalidate();
  141. }
  142. @Override
  143. public void computeScroll() {
  144. if (mScroller.computeScrollOffset()) {
  145. scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
  146. postInvalidate();
  147. }
  148. }
  149. }
  1. /** 
  2.  * SlideView 继承自LinearLayout 
  3.  */  
  4. public class SlideView extends LinearLayout {  
  5.   
  6.     private static final String TAG = "SlideView";  
  7.   
  8.     private Context mContext;  
  9.   
  10.     // 用来放置所有view的容器  
  11.     private LinearLayout mViewContent;  
  12.   
  13.     // 用来放置内置view的容器,比如删除 按钮  
  14.     private RelativeLayout mHolder;  
  15.   
  16.     // 弹性滑动对象,提供弹性滑动效果  
  17.     private Scroller mScroller;  
  18.   
  19.     // 滑动回调接口,用来向上层通知滑动事件  
  20.     private OnSlideListener mOnSlideListener;  
  21.   
  22.     // 内置容器的宽度 单位:dp  
  23.     private int mHolderWidth = 120;  
  24.   
  25.     // 分别记录上次滑动的坐标  
  26.     private int mLastX = 0;  
  27.     private int mLastY = 0;  
  28.   
  29.     // 用来控制滑动角度,仅当角度a满足如下条件才进行滑动:tan a = deltaX / deltaY > 2  
  30.     private static final int TAN = 2;  
  31.   
  32.     public interface OnSlideListener {  
  33.         // SlideView的三种状态:开始滑动,打开,关闭  
  34.         public static final int SLIDE_STATUS_OFF = 0;  
  35.         public static final int SLIDE_STATUS_START_SCROLL = 1;  
  36.         public static final int SLIDE_STATUS_ON = 2;  
  37.   
  38.         /** 
  39.          * @param view 
  40.          *            current SlideView 
  41.          * @param status 
  42.          *            SLIDE_STATUS_ON, SLIDE_STATUS_OFF or 
  43.          *            SLIDE_STATUS_START_SCROLL 
  44.          */  
  45.         public void onSlide(View view, int status);  
  46.     }  
  47.   
  48.     public SlideView(Context context) {  
  49.         super(context);  
  50.         initView();  
  51.     }  
  52.   
  53.     public SlideView(Context context, AttributeSet attrs) {  
  54.         super(context, attrs);  
  55.         initView();  
  56.     }  
  57.   
  58.     private void initView() {  
  59.         mContext = getContext();  
  60.         // 初始化弹性滑动对象  
  61.         mScroller = new Scroller(mContext);  
  62.         // 设置其方向为横向  
  63.         setOrientation(LinearLayout.HORIZONTAL);  
  64.         // 将slide_view_merge加载进来  
  65.         View.inflate(mContext, R.layout.slide_view_merge, this);  
  66.         mViewContent = (LinearLayout) findViewById(R.id.view_content);  
  67.         mHolderWidth = Math.round(TypedValue.applyDimension(  
  68.                 TypedValue.COMPLEX_UNIT_DIP, mHolderWidth, getResources()  
  69.                         .getDisplayMetrics()));  
  70.     }  
  71.   
  72.     // 设置按钮的内容,也可以设置图标啥的,我没写  
  73.     public void setButtonText(CharSequence text) {  
  74.         ((TextView) findViewById(R.id.delete)).setText(text);  
  75.     }  
  76.   
  77.     // 将view加入到ViewContent中  
  78.     public void setContentView(View view) {  
  79.         mViewContent.addView(view);  
  80.     }  
  81.   
  82.     // 设置滑动回调  
  83.     public void setOnSlideListener(OnSlideListener onSlideListener) {  
  84.         mOnSlideListener = onSlideListener;  
  85.     }  
  86.   
  87.     // 将当前状态置为关闭  
  88.     public void shrink() {  
  89.         if (getScrollX() != 0) {  
  90.             this.smoothScrollTo(0, 0);  
  91.         }  
  92.     }  
  93.   
  94.     // 根据MotionEvent来进行滑动,这个方法的作用相当于onTouchEvent  
  95.     // 如果你不需要处理滑动冲突,可以直接重命名,照样能正常工作  
  96.     public void onRequireTouchEvent(MotionEvent event) {  
  97.         int x = (int) event.getX();  
  98.         int y = (int) event.getY();  
  99.         int scrollX = getScrollX();  
  100.         Log.d(TAG, "x=" + x + "  y=" + y);  
  101.   
  102.         switch (event.getAction()) {  
  103.         case MotionEvent.ACTION_DOWN: {  
  104.             if (!mScroller.isFinished()) {  
  105.                 mScroller.abortAnimation();  
  106.             }  
  107.             if (mOnSlideListener != null) {  
  108.                 mOnSlideListener.onSlide(this,  
  109.                         OnSlideListener.SLIDE_STATUS_START_SCROLL);  
  110.             }  
  111.             break;  
  112.         }  
  113.         case MotionEvent.ACTION_MOVE: {  
  114.             int deltaX = x - mLastX;  
  115.             int deltaY = y - mLastY;  
  116.             if (Math.abs(deltaX) < Math.abs(deltaY) * TAN) {  
  117.                 // 滑动不满足条件,不做横向滑动  
  118.                 break;  
  119.             }  
  120.   
  121.             // 计算滑动终点是否合法,防止滑动越界  
  122.             int newScrollX = scrollX - deltaX;  
  123.             if (deltaX != 0) {  
  124.                 if (newScrollX < 0) {  
  125.                     newScrollX = 0;  
  126.                 } else if (newScrollX > mHolderWidth) {  
  127.                     newScrollX = mHolderWidth;  
  128.                 }  
  129.                 this.scrollTo(newScrollX, 0);  
  130.             }  
  131.             break;  
  132.         }  
  133.         case MotionEvent.ACTION_UP: {  
  134.             int newScrollX = 0;  
  135.             // 这里做了下判断,当松开手的时候,会自动向两边滑动,具体向哪边滑,要看当前所处的位置  
  136.             if (scrollX - mHolderWidth * 0.75 > 0) {  
  137.                 newScrollX = mHolderWidth;  
  138.             }  
  139.             // 慢慢滑向终点  
  140.             this.smoothScrollTo(newScrollX, 0);  
  141.             // 通知上层滑动事件  
  142.             if (mOnSlideListener != null) {  
  143.                 mOnSlideListener.onSlide(this,  
  144.                         newScrollX == 0 ? OnSlideListener.SLIDE_STATUS_OFF  
  145.                                 : OnSlideListener.SLIDE_STATUS_ON);  
  146.             }  
  147.             break;  
  148.         }  
  149.         default:  
  150.             break;  
  151.         }  
  152.   
  153.         mLastX = x;  
  154.         mLastY = y;  
  155.     }  
  156.   
  157.     private void smoothScrollTo(int destX, int destY) {  
  158.         // 缓慢滚动到指定位置  
  159.         int scrollX = getScrollX();  
  160.         int delta = destX - scrollX;  
  161.         // 以三倍时长滑向destX,效果就是慢慢滑动  
  162.         mScroller.startScroll(scrollX, 0, delta, 0, Math.abs(delta) * 3);  
  163.         invalidate();  
  164.     }  
  165.   
  166.     @Override  
  167.     public void computeScroll() {  
  168.         if (mScroller.computeScrollOffset()) {  
  169.             scrollTo(mScroller.getCurrX(), mScroller.getCurrY());  
  170.             postInvalidate();  
  171.         }  
  172.     }  
  173.   
  174. }  

上述代码做了很详细的说明,这就是滑动控件的完整代码,大家要明白的是:你所添加的view都是加在SlideView的子View : view_content中的,而不是直接加在SlideView中,只有这样我们才方便做滑动效果。

 

接着看ListView的代码:核心就是下面这一个方法,将点击事件发送给SlideView处理。

 

  1. @Override
  2. public boolean onTouchEvent(MotionEvent event) {
  3. switch (event.getAction()) {
  4. case MotionEvent.ACTION_DOWN: {
  5. int x = (int) event.getX();
  6. int y = (int) event.getY();
  7. //我们想知道当前点击了哪一行
  8. int position = pointToPosition(x, y);
  9. Log.e(TAG, "postion=" + position);
  10. if (position != INVALID_POSITION) {
  11. //得到当前点击行的数据从而取出当前行的item。
  12. //可能有人怀疑,为什么要这么干?为什么不用getChildAt(position)?
  13. //因为ListView会进行缓存,如果你不这么干,有些行的view你是得不到的。
  14. MessageItem data = (MessageItem) getItemAtPosition(position);
  15. mFocusedItemView = data.slideView;
  16. Log.e(TAG, "FocusedItemView=" + mFocusedItemView);
  17. }
  18. }
  19. default:
  20. break;
  21. }
  22. //向当前点击的view发送滑动事件请求,其实就是向SlideView发请求
  23. if (mFocusedItemView != null) {
  24. mFocusedItemView.onRequireTouchEvent(event);
  25. }
  26. return super.onTouchEvent(event);
  27. }
  1. @Override  
  2. public boolean onTouchEvent(MotionEvent event) {  
  3.     switch (event.getAction()) {  
  4.     case MotionEvent.ACTION_DOWN: {  
  5.         int x = (int) event.getX();  
  6.         int y = (int) event.getY();  
  7.         //我们想知道当前点击了哪一行  
  8.         int position = pointToPosition(x, y);  
  9.         Log.e(TAG, "postion=" + position);  
  10.         if (position != INVALID_POSITION) {  
  11.             //得到当前点击行的数据从而取出当前行的item。  
  12.             //可能有人怀疑,为什么要这么干?为什么不用getChildAt(position)?  
  13.             //因为ListView会进行缓存,如果你不这么干,有些行的view你是得不到的。  
  14.             MessageItem data = (MessageItem) getItemAtPosition(position);  
  15.             mFocusedItemView = data.slideView;  
  16.             Log.e(TAG, "FocusedItemView=" + mFocusedItemView);  
  17.         }  
  18.     }  
  19.     default:  
  20.         break;  
  21.     }  
  22.   
  23.     //向当前点击的view发送滑动事件请求,其实就是向SlideView发请求  
  24.     if (mFocusedItemView != null) {  
  25.         mFocusedItemView.onRequireTouchEvent(event);  
  26.     }  
  27.   
  28.     return super.onTouchEvent(event);  
  29. }  

最后看Activity的代码:

  1. public class MainActivity extends Activity implements OnItemClickListener,
  2. OnClickListener, OnSlideListener {
  3. private static final String TAG = "MainActivity";
  4. private ListViewCompat mListView;
  5. private List<MessageItem> mMessageItems = new ArrayList<MainActivity.MessageItem>();
  6. private SlideAdapter mSlideAdapter;
  7. // 上次处于打开状态的SlideView
  8. private SlideView mLastSlideViewWithStatusOn;
  9. @Override
  10. protected void onCreate(Bundle savedInstanceState) {
  11. super.onCreate(savedInstanceState);
  12. setContentView(R.layout.activity_main);
  13. initView();
  14. }
  15. private void initView() {
  16. mListView = (ListViewCompat) findViewById(R.id.list);
  17. for (int i = 0; i < 20; i++) {
  18. MessageItem item = new MessageItem();
  19. if (i % 3 == 0) {
  20. item.iconRes = R.drawable.default_qq_avatar;
  21. item.title = "腾讯新闻";
  22. item.msg = "青岛爆炸满月:大量鱼虾死亡";
  23. item.time = "晚上18:18";
  24. else {
  25. item.iconRes = R.drawable.wechat_icon;
  26. item.title = "微信团队";
  27. item.msg = "欢迎你使用微信";
  28. item.time = "12月18日";
  29. }
  30. mMessageItems.add(item);
  31. }
  32. mSlideAdapter = new SlideAdapter();
  33. mListView.setAdapter(mSlideAdapter);
  34. mListView.setOnItemClickListener(this);
  35. }
  36. private class SlideAdapter extends BaseAdapter {
  37. private LayoutInflater mInflater;
  38. SlideAdapter() {
  39. super();
  40. mInflater = getLayoutInflater();
  41. }
  42. @Override
  43. public int getCount() {
  44. return mMessageItems.size();
  45. }
  46. @Override
  47. public Object getItem(int position) {
  48. return mMessageItems.get(position);
  49. }
  50. @Override
  51. public long getItemId(int position) {
  52. return position;
  53. }
  54. @Override
  55. public View getView(int position, View convertView, ViewGroup parent) {
  56. ViewHolder holder;
  57. SlideView slideView = (SlideView) convertView;
  58. if (slideView == null) {
  59. // 这里是我们的item
  60. View itemView = mInflater.inflate(R.layout.list_item, null);
  61. slideView = new SlideView(MainActivity.this);
  62. // 这里把item加入到slideView
  63. slideView.setContentView(itemView);
  64. // 下面是做一些数据缓存
  65. holder = new ViewHolder(slideView);
  66. slideView.setOnSlideListener(MainActivity.this);
  67. slideView.setTag(holder);
  68. else {
  69. holder = (ViewHolder) slideView.getTag();
  70. }
  71. MessageItem item = mMessageItems.get(position);
  72. item.slideView = slideView;
  73. item.slideView.shrink();
  74. holder.icon.setImageResource(item.iconRes);
  75. holder.title.setText(item.title);
  76. holder.msg.setText(item.msg);
  77. holder.time.setText(item.time);
  78. holder.deleteHolder.setOnClickListener(MainActivity.this);
  79. return slideView;
  80. }
  81. }
  82. public class MessageItem {
  83. public int iconRes;
  84. public String title;
  85. public String msg;
  86. public String time;
  87. public SlideView slideView;
  88. }
  89. private static class ViewHolder {
  90. public ImageView icon;
  91. public TextView title;
  92. public TextView msg;
  93. public TextView time;
  94. public ViewGroup deleteHolder;
  95. ViewHolder(View view) {
  96. icon = (ImageView) view.findViewById(R.id.icon);
  97. title = (TextView) view.findViewById(R.id.title);
  98. msg = (TextView) view.findViewById(R.id.msg);
  99. time = (TextView) view.findViewById(R.id.time);
  100. deleteHolder = (ViewGroup) view.findViewById(R.id.holder);
  101. }
  102. }
  103. @Override
  104. public void onItemClick(AdapterView<?> parent, View view, int position,
  105. long id) {
  106. // 这里处理ListItem的点击事件
  107. Log.e(TAG, "onItemClick position=" + position);
  108. }
  109. @Override
  110. public void onSlide(View view, int status) {
  111. // 如果当前存在已经打开的SlideView,那么将其关闭
  112. if (mLastSlideViewWithStatusOn != null
  113. && mLastSlideViewWithStatusOn != view) {
  114. mLastSlideViewWithStatusOn.shrink();
  115. }
  116. // 记录本次处于打开状态的view
  117. if (status == SLIDE_STATUS_ON) {
  118. mLastSlideViewWithStatusOn = (SlideView) view;
  119. }
  120. }
  121. @Override
  122. public void onClick(View v) {
  123. // 这里处理删除按钮的点击事件,可以删除对话
  124. if (v.getId() == R.id.holder) {
  125. int position = mListView.getPositionForView(v);
  126. if (position != ListView.INVALID_POSITION) {
  127. mMessageItems.remove(position);
  128. mSlideAdapter.notifyDataSetChanged();
  129. }
  130. Log.e(TAG, "onClick v=" + v);
  131. }
  132. }
  133. }
  1. public class MainActivity extends Activity implements OnItemClickListener,  
  2.         OnClickListener, OnSlideListener {  
  3.   
  4.     private static final String TAG = "MainActivity";  
  5.   
  6.     private ListViewCompat mListView;  
  7.   
  8.     private List<MessageItem> mMessageItems = new ArrayList<MainActivity.MessageItem>();  
  9.   
  10.     private SlideAdapter mSlideAdapter;  
  11.   
  12.     // 上次处于打开状态的SlideView  
  13.     private SlideView mLastSlideViewWithStatusOn;  
  14.   
  15.     @Override  
  16.     protected void onCreate(Bundle savedInstanceState) {  
  17.         super.onCreate(savedInstanceState);  
  18.         setContentView(R.layout.activity_main);  
  19.         initView();  
  20.     }  
  21.   
  22.     private void initView() {  
  23.         mListView = (ListViewCompat) findViewById(R.id.list);  
  24.   
  25.         for (int i = 0; i < 20; i++) {  
  26.             MessageItem item = new MessageItem();  
  27.             if (i % 3 == 0) {  
  28.                 item.iconRes = R.drawable.default_qq_avatar;  
  29.                 item.title = "腾讯新闻";  
  30.                 item.msg = "青岛爆炸满月:大量鱼虾死亡";  
  31.                 item.time = "晚上18:18";  
  32.             } else {  
  33.                 item.iconRes = R.drawable.wechat_icon;  
  34.                 item.title = "微信团队";  
  35.                 item.msg = "欢迎你使用微信";  
  36.                 item.time = "12月18日";  
  37.             }  
  38.             mMessageItems.add(item);  
  39.         }  
  40.         mSlideAdapter = new SlideAdapter();  
  41.         mListView.setAdapter(mSlideAdapter);  
  42.         mListView.setOnItemClickListener(this);  
  43.     }  
  44.   
  45.     private class SlideAdapter extends BaseAdapter {  
  46.   
  47.         private LayoutInflater mInflater;  
  48.   
  49.         SlideAdapter() {  
  50.             super();  
  51.             mInflater = getLayoutInflater();  
  52.         }  
  53.   
  54.         @Override  
  55.         public int getCount() {  
  56.             return mMessageItems.size();  
  57.         }  
  58.   
  59.         @Override  
  60.         public Object getItem(int position) {  
  61.             return mMessageItems.get(position);  
  62.         }  
  63.   
  64.         @Override  
  65.         public long getItemId(int position) {  
  66.             return position;  
  67.         }  
  68.   
  69.         @Override  
  70.         public View getView(int position, View convertView, ViewGroup parent) {  
  71.             ViewHolder holder;  
  72.             SlideView slideView = (SlideView) convertView;  
  73.             if (slideView == null) {  
  74.                 // 这里是我们的item  
  75.                 View itemView = mInflater.inflate(R.layout.list_item, null);  
  76.   
  77.                 slideView = new SlideView(MainActivity.this);  
  78.                 // 这里把item加入到slideView  
  79.                 slideView.setContentView(itemView);  
  80.                 // 下面是做一些数据缓存  
  81.                 holder = new ViewHolder(slideView);  
  82.                 slideView.setOnSlideListener(MainActivity.this);  
  83.                 slideView.setTag(holder);  
  84.             } else {  
  85.                 holder = (ViewHolder) slideView.getTag();  
  86.             }  
  87.             MessageItem item = mMessageItems.get(position);  
  88.             item.slideView = slideView;  
  89.             item.slideView.shrink();  
  90.   
  91.             holder.icon.setImageResource(item.iconRes);  
  92.             holder.title.setText(item.title);  
  93.             holder.msg.setText(item.msg);  
  94.             holder.time.setText(item.time);  
  95.             holder.deleteHolder.setOnClickListener(MainActivity.this);  
  96.   
  97.             return slideView;  
  98.         }  
  99.   
  100.     }  
  101.   
  102.     public class MessageItem {  
  103.         public int iconRes;  
  104.         public String title;  
  105.         public String msg;  
  106.         public String time;  
  107.         public SlideView slideView;  
  108.     }  
  109.   
  110.     private static class ViewHolder {  
  111.         public ImageView icon;  
  112.         public TextView title;  
  113.         public TextView msg;  
  114.         public TextView time;  
  115.         public ViewGroup deleteHolder;  
  116.   
  117.         ViewHolder(View view) {  
  118.             icon = (ImageView) view.findViewById(R.id.icon);  
  119.             title = (TextView) view.findViewById(R.id.title);  
  120.             msg = (TextView) view.findViewById(R.id.msg);  
  121.             time = (TextView) view.findViewById(R.id.time);  
  122.             deleteHolder = (ViewGroup) view.findViewById(R.id.holder);  
  123.         }  
  124.     }  
  125.   
  126.     @Override  
  127.     public void onItemClick(AdapterView<?> parent, View view, int position,  
  128.             long id) {  
  129.         // 这里处理ListItem的点击事件  
  130.         Log.e(TAG, "onItemClick position=" + position);  
  131.     }  
  132.   
  133.     @Override  
  134.     public void onSlide(View view, int status) {  
  135.         // 如果当前存在已经打开的SlideView,那么将其关闭  
  136.         if (mLastSlideViewWithStatusOn != null  
  137.                 && mLastSlideViewWithStatusOn != view) {  
  138.             mLastSlideViewWithStatusOn.shrink();  
  139.         }  
  140.         // 记录本次处于打开状态的view  
  141.         if (status == SLIDE_STATUS_ON) {  
  142.             mLastSlideViewWithStatusOn = (SlideView) view;  
  143.         }  
  144.     }  
  145.   
  146.     @Override  
  147.     public void onClick(View v) {  
  148.         // 这里处理删除按钮的点击事件,可以删除对话  
  149.         if (v.getId() == R.id.holder) {  
  150.             int position = mListView.getPositionForView(v);  
  151.             if (position != ListView.INVALID_POSITION) {  
  152.                 mMessageItems.remove(position);  
  153.                 mSlideAdapter.notifyDataSetChanged();  
  154.             }  
  155.             Log.e(TAG, "onClick v=" + v);  
  156.         }  
  157.     }  
  158. }  

代码我都特意写了注释,就不多说了。

posted @ 2016-04-13 09:41  牧之丨  阅读(860)  评论(0编辑  收藏  举报