1. 程式人生 > >slideview 側滑時上下滾動 onitemclick和滑動的衝突 解決方法

slideview 側滑時上下滾動 onitemclick和滑動的衝突 解決方法

初學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