1. 程式人生 > >android-做一個簡單的左滑刪除控制元件

android-做一個簡單的左滑刪除控制元件


import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.PointF;
import android.support.v4.view.ViewConfigurationCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;

public class SwipeLayout extends ViewGroup{
    public static String TAG = "SwipeLayout";

    //可以滾動的距離
    int mSwipeWidth;


    PointF firstPoint;
    PointF lastPoint;

    float mTouchSlop;

    ValueAnimator openAnimator;
    ValueAnimator closeAnimator;

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

    public SwipeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(ViewConfiguration.get(getContext()));
    }



    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int left=0;
        int childCount = getChildCount();

        for (int i=0;i<childCount;++i){
            View child = getChildAt(i);

            //按順序從左往右排
//            if (i==0){
//                child.layout(0,0,child.getMeasuredWidth(),child.getMeasuredHeight());
//            }else {
                child.layout(left,0,left+child.getMeasuredWidth(),child.getMeasuredHeight());
//            }
            left += child.getMeasuredWidth();
        }


    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int childCount = getChildCount();
        View mainChild = getChildAt(0);
        int width=0;
        int height=0;
        mSwipeWidth = 0;
//        measureChild(mainChild,widthMeasureSpec,heightMeasureSpec);
        measure(widthMeasureSpec,heightMeasureSpec);

        //滑動距離是 從index開始 所有控制元件的寬度之和
        if (childCount>1) {
            for (int i = 1; i < childCount; ++i) {
                mSwipeWidth += getChildAt(i).getMeasuredWidth();
            }
        }


        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthValue = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightValue = MeasureSpec.getSize(heightMeasureSpec);

        switch (heightMode){
            case MeasureSpec.AT_MOST:
            case MeasureSpec.UNSPECIFIED:
                //沒有指定大小 按照第一個子控制元件的大小來設定
                height = mainChild.getMeasuredHeight();
                break;
            case MeasureSpec.EXACTLY:
                height = heightValue;
                break;
        }
        switch (widthMode){
            case MeasureSpec.AT_MOST:
            case MeasureSpec.UNSPECIFIED:
                //沒有指定大小 按照第一個子控制元件的大小來設定
                width = mainChild.getMeasuredWidth();
                break;
            case MeasureSpec.EXACTLY:
                width = widthValue;
                break;
        }

//        for (int i=1;i<childCount;++i){
//            measureChild(getChildAt(i),widthMeasureSpec,MeasureSpec.makeMeasureSpec(height,MeasureSpec.EXACTLY));
//        }
        setMeasuredDimension(width,height);
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
               switch (ev.getAction()){
           case MotionEvent.ACTION_DOWN:
               firstPoint = new PointF(ev.getX(),ev.getY());
               lastPoint = new PointF(ev.getX(),ev.getY());
               break;
           case MotionEvent.ACTION_MOVE:
               float moveDistance = ev.getX()-firstPoint.x;

               //移動距離大於制定值   認為進入控制元件的滑動模式
                if (Math.abs(moveDistance) > mTouchSlop ){
                    //讓父控制元件不攔截我們的事件
                    getParent().requestDisallowInterceptTouchEvent(true);
                    //攔截事件
                    return true;
                }

       }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()){
            case MotionEvent.ACTION_MOVE:
                float moveDistance = ev.getX()-lastPoint.x;
                lastPoint = new PointF(ev.getX(),ev.getY());

                // 這裡要注意   x大於0的時候 往左滑動  小於0往右滑動
                scrollBy((int) -moveDistance ,0);

                //邊界判定 超過了邊界  直接設定為邊界值
                if (getScrollX()> mSwipeWidth){
                    scrollTo(mSwipeWidth,0);
                }else if (getScrollX()<0){
                    scrollTo(0,0);
                }
                break;
            case MotionEvent.ACTION_UP:
                //沒動 不理他
                if (getScrollX()== mSwipeWidth ||getScrollX()==0){
                    return false;
                }
                    float distance = ev.getX()-firstPoint.x;
                //滑動距離超過 可滑動距離指定值 繼續完成滑動
                    if (Math.abs(distance) > mSwipeWidth *0.3 ){
                        if (distance>0){
                            smoothClose();
                        }else if (distance<0){
                            smoothOpen();
                        }
                    }else  {
                        if (distance>0){
                            smoothOpen();

                        }else if (distance<0){
                            smoothClose();
                        }
                    }
                    return true;
        }

        return super.onTouchEvent(ev);
    }

    public void smoothOpen(){

        clearAnimator();
        openAnimator = ValueAnimator.ofInt(getScrollX(), mSwipeWidth);
        openAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer integer = (Integer) animation.getAnimatedValue();
                scrollTo(integer,0);
            }
        });
        openAnimator.start();
    }
    public void smoothClose(){
        clearAnimator();
        closeAnimator = ValueAnimator.ofInt(getScrollX(),0);
        closeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Integer integer = (Integer) animation.getAnimatedValue();
                scrollTo(integer,0);
            }
        });
        closeAnimator.start();

    }

    public void open(){
        scrollTo(mSwipeWidth,0);
    }
    public void close(){
        scrollTo(0,0);

    }
//執行滑動動畫必須先清除動畫  不然會鬼畜
    private void clearAnimator(){
        if (closeAnimator!=null && closeAnimator.isRunning()){
            closeAnimator.cancel();
            closeAnimator = null;
        }
        if (openAnimator!=null && openAnimator.isRunning()) {
            openAnimator.cancel();
            openAnimator = null;
        }
    }

    public void toggle(){
        if (getScrollX()==0){
            open();
        }else {
            close();
        }
    }

}

使用

            <com.example.chenweiqi.simplerefreshview.widget.SwipeLayout
                android:id="@+id/swipeLayout"
                android:layout_width="200dp"
                android:layout_height="wrap_content"
                android:background="#F3F3F3"
                >
                <Button
                    android:id="@+id/btn"
                    android:text="123"
                    android:layout_width="match_parent"
                    android:layout_height="50dp" />

                <Button
                    android:background="#FF0000"
                    android:text="shanchu"
                    android:layout_width="80dp"
                    android:layout_height="match_parent" />
                <TextView
                    android:gravity="center"
                    android:textAlignment="center"
                    android:background="#0F0"
                    android:text="123"
                    android:layout_width="30dp"
                    android:layout_height="match_parent" />
            </com.example.chenweiqi.simplerefreshview.widget.SwipeLayout>

效果