Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android仿微信對話列表滑動刪除效果

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

編輯:關於Android編程

微信對話列表滑動刪除效果很不錯的,借鑒了github上SwipeListView(項目地址:https://github.com/likebamboo/SwipeListView),在其上進行了一些重構,最終實現了微信對話列表滑動刪除效果。

實現原理
 1.通過ListView的pointToPosition(int x, int y)來獲取按下的position,然後通過android.view.ViewGroup.getChildAt(position)來得到滑動對象swipeView
 2.在onTouchEvent中計算要滑動的距離,調用swipeView.scrollTo即可。

運行效果如下

下面是最核心的部分SwipeListView代碼: 

package com.fxsky.swipelist.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView;

import com.fxsky.swipelist.R;

public class SwipeListView extends ListView {
 private Boolean mIsHorizontal;

 private View mPreItemView;

 private View mCurrentItemView;

 private float mFirstX;

 private float mFirstY;

 private int mRightViewWidth;

 // private boolean mIsInAnimation = false;
 private final int mDuration = 100;

 private final int mDurationStep = 10;

 private boolean mIsShown;

 public SwipeListView(Context context) {
 this(context,null);
 }

 public SwipeListView(Context context, AttributeSet attrs) {
 this(context, attrs,0);
 }

 public SwipeListView(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 
 TypedArray mTypedArray = context.obtainStyledAttributes(attrs, 
 R.styleable.swipelistviewstyle); 
 
 //獲取自定義屬性和默認值 
 mRightViewWidth = (int) mTypedArray.getDimension(R.styleable.swipelistviewstyle_right_width, 200); 
 
 mTypedArray.recycle(); 
 }

 /**
 * return true, deliver to listView. return false, deliver to child. if
 * move, return true
 */
 @Override
 public boolean onInterceptTouchEvent(MotionEvent ev) {
 float lastX = ev.getX();
 float lastY = ev.getY();
 switch (ev.getAction()) {
 case MotionEvent.ACTION_DOWN:
 mIsHorizontal = null;
 System.out.println("onInterceptTouchEvent----->ACTION_DOWN");
 mFirstX = lastX;
 mFirstY = lastY;
 int motionPosition = pointToPosition((int)mFirstX, (int)mFirstY);

 if (motionPosition >= 0) {
  View currentItemView = getChildAt(motionPosition - getFirstVisiblePosition());
  mPreItemView = mCurrentItemView;
  mCurrentItemView = currentItemView;
 }
 break;

 case MotionEvent.ACTION_MOVE:
 float dx = lastX - mFirstX;
 float dy = lastY - mFirstY;

 if (Math.abs(dx) >= 5 && Math.abs(dy) >= 5) {
  return true;
 }
 break;

 case MotionEvent.ACTION_UP:
 case MotionEvent.ACTION_CANCEL:
 System.out.println("onInterceptTouchEvent----->ACTION_UP");
 if (mIsShown && (mPreItemView != mCurrentItemView || isHitCurItemLeft(lastX))) {
  System.out.println("1---> hiddenRight");
  /**
  * 情況一:
  * <p>
  * 一個Item的右邊布局已經顯示,
  * <p>
  * 這時候點擊任意一個item, 那麼那個右邊布局顯示的item隱藏其右邊布局
  */
  hiddenRight(mPreItemView);
 }
 break;
 }

 return super.onInterceptTouchEvent(ev);
 }

 private boolean isHitCurItemLeft(float x) {
 return x < getWidth() - mRightViewWidth;
 }

 /**
 * @param dx
 * @param dy
 * @return judge if can judge scroll direction
 */
 private boolean judgeScrollDirection(float dx, float dy) {
 boolean canJudge = true;

 if (Math.abs(dx) > 30 && Math.abs(dx) > 2 * Math.abs(dy)) {
 mIsHorizontal = true;
 System.out.println("mIsHorizontal---->" + mIsHorizontal);
 } else if (Math.abs(dy) > 30 && Math.abs(dy) > 2 * Math.abs(dx)) {
 mIsHorizontal = false;
 System.out.println("mIsHorizontal---->" + mIsHorizontal);
 } else {
 canJudge = false;
 }

 return canJudge;
 }

 /**
 * return false, can't move any direction. return true, cant't move
 * vertical, can move horizontal. return super.onTouchEvent(ev), can move
 * both.
 */
 @Override
 public boolean onTouchEvent(MotionEvent ev) {
 float lastX = ev.getX();
 float lastY = ev.getY();

 switch (ev.getAction()) {
 case MotionEvent.ACTION_DOWN:
 System.out.println("---->ACTION_DOWN");
 break;

 case MotionEvent.ACTION_MOVE:
 float dx = lastX - mFirstX;
 float dy = lastY - mFirstY;

 // confirm is scroll direction
 if (mIsHorizontal == null) {
  if (!judgeScrollDirection(dx, dy)) {
  break;
  }
 }

 if (mIsHorizontal) {
  if (mIsShown && mPreItemView != mCurrentItemView) {
  System.out.println("2---> hiddenRight");
  /**
  * 情況二:
  * <p>
  * 一個Item的右邊布局已經顯示,
  * <p>
  * 這時候左右滑動另外一個item,那個右邊布局顯示的item隱藏其右邊布局
  * <p>
  * 向左滑動只觸發該情況,向右滑動還會觸發情況五
  */
  hiddenRight(mPreItemView);
  }

  if (mIsShown && mPreItemView == mCurrentItemView) {
  dx = dx - mRightViewWidth;
  System.out.println("======dx " + dx);
  }

  // can't move beyond boundary
  if (dx < 0 && dx > -mRightViewWidth) {
  mCurrentItemView.scrollTo((int)(-dx), 0);
  }

  return true;
 } else {
  if (mIsShown) {
  System.out.println("3---> hiddenRight");
  /**
  * 情況三:
  * <p>
  * 一個Item的右邊布局已經顯示,
  * <p>
  * 這時候上下滾動ListView,那麼那個右邊布局顯示的item隱藏其右邊布局
  */
  hiddenRight(mPreItemView);
  }
 }

 break;

 case MotionEvent.ACTION_UP:
 case MotionEvent.ACTION_CANCEL:
 System.out.println("============ACTION_UP");
 clearPressedState();
 if (mIsShown) {
  System.out.println("4---> hiddenRight");
  /**
  * 情況四:
  * <p>
  * 一個Item的右邊布局已經顯示,
  * <p>
  * 這時候左右滑動當前一個item,那個右邊布局顯示的item隱藏其右邊布局
  */
  hiddenRight(mPreItemView);
 }

 if (mIsHorizontal != null && mIsHorizontal) {
  if (mFirstX - lastX > mRightViewWidth / 2) {
  showRight(mCurrentItemView);
  } else {
  System.out.println("5---> hiddenRight");
  /**
  * 情況五:
  * <p>
  * 向右滑動一個item,且滑動的距離超過了右邊View的寬度的一半,隱藏之。
  */
  hiddenRight(mCurrentItemView);
  }

  return true;
 }

 break;
 }

 return super.onTouchEvent(ev);
 }

 private void clearPressedState() {
 // TODO current item is still has background, issue
 mCurrentItemView.setPressed(false);
 setPressed(false);
 refreshDrawableState();
 // invalidate();
 }

 private void showRight(View view) {
 System.out.println("=========showRight");

 Message msg = new MoveHandler().obtainMessage();
 msg.obj = view;
 msg.arg1 = view.getScrollX();
 msg.arg2 = mRightViewWidth;
 msg.sendToTarget();

 mIsShown = true;
 }

 private void hiddenRight(View view) {
 System.out.println("=========hiddenRight");
 if (mCurrentItemView == null) {
 return;
 }
 Message msg = new MoveHandler().obtainMessage();//
 msg.obj = view;
 msg.arg1 = view.getScrollX();
 msg.arg2 = 0;

 msg.sendToTarget();

 mIsShown = false;
 }

 /**
 * show or hide right layout animation
 */
 @SuppressLint("HandlerLeak")
 class MoveHandler extends Handler {
 int stepX = 0;

 int fromX;

 int toX;

 View view;

 private boolean mIsInAnimation = false;

 private void animatioOver() {
 mIsInAnimation = false;
 stepX = 0;
 }

 @Override
 public void handleMessage(Message msg) {
 super.handleMessage(msg);
 if (stepX == 0) {
 if (mIsInAnimation) {
  return;
 }
 mIsInAnimation = true;
 view = (View)msg.obj;
 fromX = msg.arg1;
 toX = msg.arg2;
 stepX = (int)((toX - fromX) * mDurationStep * 1.0 / mDuration);
 if (stepX < 0 && stepX > -1) {
  stepX = -1;
 } else if (stepX > 0 && stepX < 1) {
  stepX = 1;
 }
 if (Math.abs(toX - fromX) < 10) {
  view.scrollTo(toX, 0);
  animatioOver();
  return;
 }
 }

 fromX += stepX;
 boolean isLastStep = (stepX > 0 && fromX > toX) || (stepX < 0 && fromX < toX);
 if (isLastStep) {
 fromX = toX;
 }

 view.scrollTo(fromX, 0);
 invalidate();

 if (!isLastStep) {
 this.sendEmptyMessageDelayed(0, mDurationStep);
 } else {
 animatioOver();
 }
 }
 }

 public int getRightViewWidth() {
 return mRightViewWidth;
 }

 public void setRightViewWidth(int mRightViewWidth) {
 this.mRightViewWidth = mRightViewWidth;
 }
}

Demo下載地址:http://xiazai.jb51.net/201608/yuanma/SwipeListView(jb51.net).rar

Demo中SwipeAdapter源碼中有一處由於粗心寫錯了,會導致向下滑動時出現數組越界異常,現更正如下:

@Override
 public int getCount() {
// return 100;
 return data.size();
 }

本文已被整理到了《Android微信開發教程匯總》,歡迎大家學習閱讀。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved