高仿微信對話列表滑動刪除效果

目錄(?)[+]

前言

用過微信的都知道,微信對話列表滑動刪除效果是很不錯的,這個效果我們也可以有。思路其實很簡單,弄個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:

[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
  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>
[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
  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:

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  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(00);
  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. }
[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  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(00);  
  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處理。

[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  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. }
[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  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的代碼:
[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  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. }
[java] view plaincopy在CODE上查看代碼片派生到我的代碼片
  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. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章