Android App中ListView仿QQ實現滑動刪除效果的要點解析_Android

來源:互聯網
上載者:User

本來準備在ListView的每個Item的布局上設定一個隱藏的Button,當滑動的時候顯示。但是因為每次只要存在一個Button,發現每個Item上的Button相互間不好控制。所以決定繼承ListView然後結合PopupWindow。
首先是布局檔案:
delete_btn.xml:這裡只需要一個Button

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:orientation="vertical" >    <Button      android:id="@+id/id_item_btn"     android:layout_width="60dp"     android:singleLine="true"     android:layout_height="wrap_content"     android:text="刪除"     android:background="@drawable/d_delete_btn"     android:textColor="#ffffff"     android:paddingLeft="15dp"     android:paddingRight="15dp"     android:layout_alignParentRight="true"     android:layout_centerVertical="true"     android:layout_marginRight="15dp"     /> </LinearLayout> 

主布局檔案:activity_main.xml,ListView的每個Item的樣式直接使用了系統的android.R.layout.simple_list_item_1

<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.example.listviewitemslidedeletebtnshow.QQListView     android:id="@+id/id_listview"     android:layout_width="fill_parent"     android:layout_height="wrap_content" >   </com.example.listviewitemslidedeletebtnshow.QQListView>  </RelativeLayout> 

接下來看看QQListView的實現:

package com.example.listviewitemslidedeletebtnshow;  import android.content.Context; import android.util.AttributeSet; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.widget.Button; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.PopupWindow;  public class QQListView extends ListView {    private static final String TAG = "QQlistView";    // private static final int VELOCITY_SANP = 200;   // private VelocityTracker mVelocityTracker;   /**    * 使用者滑動的最小距離    */   private int touchSlop;    /**    * 是否響應滑動    */   private boolean isSliding;    /**    * 手指按下時的x座標    */   private int xDown;   /**    * 手指按下時的y座標    */   private int yDown;   /**    * 手指移動時的x座標    */   private int xMove;   /**    * 手指移動時的y座標    */   private int yMove;    private LayoutInflater mInflater;    private PopupWindow mPopupWindow;   private int mPopupWindowHeight;   private int mPopupWindowWidth;    private Button mDelBtn;   /**    * 為刪除按鈕提供一個回調介面    */   private DelButtonClickListener mListener;    /**    * 當前手指觸摸的View    */   private View mCurrentView;    /**    * 當前手指觸摸的位置    */   private int mCurrentViewPos;    /**    * 必要的一些初始化    *    * @param context    * @param attrs    */   public QQListView(Context context, AttributeSet attrs)   {     super(context, attrs);      mInflater = LayoutInflater.from(context);     touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();      View view = mInflater.inflate(R.layout.delete_btn, null);     mDelBtn = (Button) view.findViewById(R.id.id_item_btn);     mPopupWindow = new PopupWindow(view, LinearLayout.LayoutParams.WRAP_CONTENT,         LinearLayout.LayoutParams.WRAP_CONTENT);     /**      * 先調用下measure,否則拿不到寬和高      */     mPopupWindow.getContentView().measure(0, 0);     mPopupWindowHeight = mPopupWindow.getContentView().getMeasuredHeight();     mPopupWindowWidth = mPopupWindow.getContentView().getMeasuredWidth();   }    @Override   public boolean dispatchTouchEvent(MotionEvent ev)   {     int action = ev.getAction();     int x = (int) ev.getX();     int y = (int) ev.getY();     switch (action)     {      case MotionEvent.ACTION_DOWN:       xDown = x;       yDown = y;       /**        * 如果當前popupWindow顯示,則直接隱藏,然後屏蔽ListView的touch事件的下傳        */       if (mPopupWindow.isShowing())       {         dismissPopWindow();         return false;       }       // 獲得當前手指按下時的item的位置       mCurrentViewPos = pointToPosition(xDown, yDown);       // 獲得當前手指按下時的item       View view = getChildAt(mCurrentViewPos - getFirstVisiblePosition());       mCurrentView = view;       break;     case MotionEvent.ACTION_MOVE:       xMove = x;       yMove = y;       int dx = xMove - xDown;       int dy = yMove - yDown;       /**        * 判斷是否是從右至左的滑動        */       if (xMove < xDown && Math.abs(dx) > touchSlop && Math.abs(dy) < touchSlop)       {         // Log.e(TAG, "touchslop = " + touchSlop + " , dx = " + dx +         // " , dy = " + dy);         isSliding = true;       }       break;     }     return super.dispatchTouchEvent(ev);   }    @Override   public boolean onTouchEvent(MotionEvent ev)   {     int action = ev.getAction();     /**      * 如果是從右至左的滑動才相應      */     if (isSliding)     {       switch (action)       {       case MotionEvent.ACTION_MOVE:          int[] location = new int[2];         // 獲得當前item的位置x與y         mCurrentView.getLocationOnScreen(location);         // 設定popupWindow的動畫         mPopupWindow.setAnimationStyle(R.style.popwindow_delete_btn_anim_style);         mPopupWindow.update();         mPopupWindow.showAtLocation(mCurrentView, Gravity.LEFT | Gravity.TOP,             location[0] + mCurrentView.getWidth(), location[1] + mCurrentView.getHeight() / 2                 - mPopupWindowHeight / 2);         // 設定刪除按鈕的回調         mDelBtn.setOnClickListener(new OnClickListener()         {           @Override           public void onClick(View v)           {             if (mListener != null)             {               mListener.clickHappend(mCurrentViewPos);               mPopupWindow.dismiss();             }           }         });         // Log.e(TAG, "mPopupWindow.getHeight()=" + mPopupWindowHeight);          break;       case MotionEvent.ACTION_UP:         isSliding = false;        }       // 相應滑動期間螢幕itemClick事件,避免發生衝突       return true;     }      return super.onTouchEvent(ev);   }    /**    * 隱藏popupWindow    */   private void dismissPopWindow()   {     if (mPopupWindow != null && mPopupWindow.isShowing())     {       mPopupWindow.dismiss();     }   }    public void setDelButtonClickListener(DelButtonClickListener listener)   {     mListener = listener;   }    interface DelButtonClickListener   {     public void clickHappend(int position);   }  } 

代碼注釋寫得很詳細,簡單說一下,在dispatchTouchEvent中設定當前是否響應使用者滑動,然後在onTouchEvent中判斷是否響應,如果響應則popupWindow以動畫的形式展示出來。當然螢幕上如果存在PopupWindow則螢幕ListView的滾動與Item的點擊,以及從右至左滑動時螢幕Item的click事件。
接下來是MainActivity.java,這裡代碼很簡單不做介紹了。

package com.example.listviewitemslidedeletebtnshow;  import java.util.ArrayList; import java.util.Arrays; import java.util.List;  import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Toast;  import com.example.listviewitemslidedeletebtnshow.QQListView.DelButtonClickListener;  public class MainActivity extends Activity {   private QQListView mListView;   private ArrayAdapter<String> mAdapter;   private List<String> mDatas;    @Override   protected void onCreate(Bundle savedInstanceState)   {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_main);      mListView = (QQListView) findViewById(R.id.id_listview);     // 不要直接Arrays.asList     mDatas = new ArrayList<String>(Arrays.asList("HelloWorld", "Welcome", "Java", "Android", "Servlet", "Struts",         "Hibernate", "Spring", "HTML5", "Javascript", "Lucene"));     mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mDatas);     mListView.setAdapter(mAdapter);      mListView.setDelButtonClickListener(new DelButtonClickListener()     {       @Override       public void clickHappend(final int position)       {         Toast.makeText(MainActivity.this, position + " : " + mAdapter.getItem(position), 1).show();         mAdapter.remove(mAdapter.getItem(position));       }     });      mListView.setOnItemClickListener(new OnItemClickListener()     {       @Override       public void onItemClick(AdapterView<?> parent, View view, int position, long id)       {         Toast.makeText(MainActivity.this, position + " : " + mAdapter.getItem(position), 1).show();       }     });   } } 

效果圖如下:樓主使用asm.jar以及gifcamera截的gif,由於button的動畫很短感覺截圖效果很卡不流暢,大家有什麼好的截圖,還望推薦。有興趣的還是下載源碼看看效果i。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.