slideview 側滑時上下滾動 onitemclick和滑動的衝突 解決方法
阿新 • • 發佈:2018-12-11
初學android不久 第一次寫部落格 記錄下。如果有錯誤 請提醒,萬分感謝
slideview原文地址:http://blog.csdn.net/singwhatiwanna/article/details/17515543
自定義LinearLayout ,作為listview裡的item 在onslidelistner中增加個正在滑動的狀態 ,憑這個狀態可以讓側滑的時候 讓listview不滾動
public class SlideView extends LinearLayout { private static final String TAG = "SlideView"; private Context mContext; private LinearLayout mViewContent; private RelativeLayout mHolder; private Scroller mScroller; private OnSlideListener mOnSlideListener; private int mHolderWidth = 120; private int mLastX = 0; private int mLastY = 0; // 用來控制滑動角度,僅當角度a滿足如下條件才進行滑動:tan a = deltaX / deltaY > 2 private static final int TAN = 2; //自定義監聽 監聽滑動過程中的各個狀態 public interface OnSlideListener { //滑動結束,側滑刪除未展開 public static final int SLIDE_STATUS_OFF = 0; //開始滑動 public static final int SLIDE_STATUS_START_SCROLL = 1; //滑動結束,側滑刪除展開 public static final int SLIDE_STATUS_ON = 2; //滑動中 public static final int SLIDEING = 4; /** * @param view current SlideView * @param status SLIDE_STATUS_ON or SLIDE_STATUS_OFF */ public void onSlide(View view, int status); } public SlideView(Context context) { super(context); initView(); } public SlideView(Context context, AttributeSet attrs) { super(context, attrs); initView(); } private void initView() { mContext = getContext(); mScroller = new Scroller(mContext); //因為用了merge標籤 指定下orientation setOrientation(LinearLayout.HORIZONTAL); View.inflate(mContext, R.layout.privatelisting_delete_merge, this); mViewContent = (LinearLayout) findViewById(R.id.view_content); //根據解析度 計算側滑刪除 具體寬度 mHolderWidth = Math.round(TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, mHolderWidth, getResources() .getDisplayMetrics())); Log.d("mHolderWidth", String.valueOf(mHolderWidth)); } public void setButtonText(CharSequence text) { ((TextView)findViewById(R.id.delete)).setText(text); } public void setContentView(View view) { mViewContent.addView(view); } public void setOnSlideListener(OnSlideListener onSlideListener) { mOnSlideListener = onSlideListener; } //復位 public void shrink() { if (getScrollX() != 0) { this.smoothScrollTo(0, 0); } } //關鍵判斷 public boolean onRequireTouchEvent(MotionEvent event) { boolean result=false; //當前點選的位置 和X滾動的距離 int x = (int) event.getX(); int y = (int) event.getY(); int scrollX = getScrollX(); Log.d(TAG, "x=" + x + " y=" + y +"scrollX="+scrollX); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { if (!mScroller.isFinished()) { mScroller.abortAnimation(); } if (mOnSlideListener != null) { mOnSlideListener.onSlide(this, OnSlideListener.SLIDE_STATUS_START_SCROLL); } break; } //手指移動 滾動過程中 超過mHolderWidth 就不再滾動 case MotionEvent.ACTION_MOVE: { //滾動過程中 當前位置 和上個位置 deltaX,如果向左滾為負值 向右滾為正值 int deltaX = x - mLastX; int deltaY = y - mLastY; Log.d("test11","mLastX:"+mLastX+"x:"+x+"scrollX:"+scrollX); //手指縱向移動 不做橫向滑動 if (Math.abs(deltaX) < Math.abs(deltaY) * TAN) { break; } // 計算滑動終點是否合法,防止滑動越界 int newScrollX = scrollX - deltaX; if (deltaX != 0) { if (newScrollX < 0) { newScrollX = 0; } else if (newScrollX > mHolderWidth) { newScrollX = mHolderWidth; } Log.d("newScrollX:MOVE", String.valueOf(newScrollX)); this.scrollTo(newScrollX, 0); } if (mOnSlideListener != null) { mOnSlideListener.onSlide(this, OnSlideListener.SLIDEING); } break; } case MotionEvent.ACTION_UP: { //擡起手指時 大於mHolderWidth * 0.75就展開 否則回到初始位置 int newScrollX = 0; if (scrollX - mHolderWidth * 0.75 > 0) { newScrollX = mHolderWidth; } Log.d("test123", x+","+getScrollX()+","+mLastX); Log.d("newScrollX:UP", String.valueOf(newScrollX)); this.smoothScrollTo(newScrollX, 0); //通知adapter 這個item最終展開了沒有 if (mOnSlideListener != null) { mOnSlideListener.onSlide(this, newScrollX == 0 ? OnSlideListener.SLIDE_STATUS_OFF : OnSlideListener.SLIDE_STATUS_ON); } if(getScrollX()<=mHolderWidth&&getScrollX()>0){ result =true; } break; } } Log.d("hjk", String.valueOf(mLastX)); Log.d("hjk", String.valueOf(mLastY)); mLastX = x; mLastY = y; return result; } private void smoothScrollTo(int destX, int destY) { // 緩慢滾動到指定位置 int scrollX = getScrollX(); int delta = destX - scrollX; mScroller.startScroll(scrollX, 0, delta, 0, Math.abs(delta) * 3); invalidate(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { Log.d("test11","123"); scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } } }
自定義listview 其中的item 為slideview 重寫ontouchevent 方法 由iscroll判斷是否將事件傳遞給子view 如果是發生了側滑 就消費這個事件不繼續往下傳,也就執行不了onitemclick 不過對於判斷是否側滑事件 判斷可能存在問題。
public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { //按下 case MotionEvent.ACTION_DOWN: { int x = (int) event.getX(); int y = (int) event.getY(); int position = pointToPosition(x, y); Log.e(TAG, "postion=" + position); //如果是有效觸點 即點選了list,得到item if (position != INVALID_POSITION) { MessageBean data = (MessageBean) getItemAtPosition(position); mFocusedItemView = data.slideView; Log.e(TAG, "FocusedItemView=" + mFocusedItemView); } } default: break; } //事件交給item,即slideview處理 if (mFocusedItemView != null) { boolean isScroll=mFocusedItemView.onRequireTouchEvent(event); //判斷是否滾動 攔截掉事件不往下傳遞 if (isScroll) { Log.d("test123", String.valueOf(isScroll)); return true; } } return super.onTouchEvent(event); }
個人覺得 其中需要掌握的 知識點 merge標籤 :初始化xml時 消除了多餘的根佈局
scrollto 絕對位移 scrollby 相對位移 getscrollx getsrcolly 在viewgroup中是 內部view相對於父佈局左上角的位置
ontouchevent 和onintercepttouchevent 推薦個作者部落格 寫的很詳細 http://blog.csdn.net/yanzi1225627/article/details/22592831