基于Adapter的侧滑自定义控件(Java)

作者: Wocus | 来源:发表于2017-08-29 10:07 被阅读122次

    基于listview中的adapter侧滑,监听adapter中的view的触摸实现滑动,先看效果图

    image.png

    使用步骤

    1.提供自定义View
    package com.sunnet.shipcargo.view;
    
    import android.content.Context;
    import android.support.v4.view.ViewCompat;
    import android.support.v4.widget.ViewDragHelper;
    import android.support.v4.widget.ViewDragHelper.Callback;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.FrameLayout;
    
    /**
     * 侧滑Layout
     */
    public class SwipeListLayout extends FrameLayout {
    
        private View hiddenView;
        private View itemView;
        private int hiddenViewWidth;
        private ViewDragHelper mDragHelper;
        private int hiddenViewHeight;
        private int itemWidth;
        private int itemHeight;
        private OnSwipeStatusListener listener;
        private Status status = Status.Close;
        private boolean smooth = true;
    
        public static final String TAG = "SlipListLayout";
    
        // 状态
        public enum Status {
            Open, Close
        }
    
        /**
         * 设置侧滑状态
         * 
         * @param status
         *            状态 Open or Close
         * @param smooth
         *            若为true则有过渡动画,否则没有
         */
        public void setStatus(Status status, boolean smooth) {
            this.status = status;
            if (status == Status.Open) {
                open(smooth);
            } else {
                close(smooth);
            }
        }
    
        public void setOnSwipeStatusListener(OnSwipeStatusListener listener) {
            this.listener = listener;
        }
    
        /**
         * 是否设置过渡动画
         * 
         * @param smooth
         */
        public void setSmooth(boolean smooth) {
            this.smooth = smooth;
        }
    
        public interface OnSwipeStatusListener {
    
            /**
             * 当状态改变时回调
             * 
             * @param status
             */
            void onStatusChanged(Status status);
    
            /**
             * 开始执行Open动画
             */
            void onStartCloseAnimation();
    
            /**
             * 开始执行Close动画
             */
            void onStartOpenAnimation();
    
        }
    
        public SwipeListLayout(Context context) {
            this(context, null);
        }
    
        public SwipeListLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
            mDragHelper = ViewDragHelper.create(this, callback);
        }
    
        // ViewDragHelper的回调
        Callback callback = new Callback() {
    
            @Override
            public boolean tryCaptureView(View view, int arg1) {
                return view == itemView;
            }
    
            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                if (child == itemView) {
                    if (left > 0) {
                        return 0;
                    } else {
                        left = Math.max(left, -hiddenViewWidth);
                        return left;
                    }
                }
                return 0;
            }
    
            @Override
            public int getViewHorizontalDragRange(View child) {
                return hiddenViewWidth;
            }
    
            @Override
            public void onViewPositionChanged(View changedView, int left, int top,
                    int dx, int dy) {
                if (itemView == changedView) {
                    hiddenView.offsetLeftAndRight(dx);
                }
                // 有时候滑动很快的话 会出现隐藏按钮的linearlayout没有绘制的问题
                // 为了确保绘制成功 调用 invalidate
                invalidate();
            }
    
            @Override
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                // 向右滑xvel为正 向左滑xvel为负
                if (releasedChild == itemView) {
                    if (xvel == 0
                            && Math.abs(itemView.getLeft()) > hiddenViewWidth / 2.0f) {
                        open(smooth);
                    } else if (xvel < 0) {
                        open(smooth);
                    } else {
                        close(smooth);
                    }
                }
            }
    
        };
        private Status preStatus = Status.Close;
    
        /**
         * 侧滑关闭
         * 
         * @param smooth
         *            为true则有平滑的过渡动画
         */
        private void close(boolean smooth) {
            preStatus = status;
            status = Status.Close;
            if (smooth) {
                if (mDragHelper.smoothSlideViewTo(itemView, 0, 0)) {
                    if (listener != null) {
                        Log.i(TAG, "start close animation");
                        listener.onStartCloseAnimation();
                    }
                    ViewCompat.postInvalidateOnAnimation(this);
                }
            } else {
                layout(status);
            }
            if (listener != null && preStatus == Status.Open) {
                Log.i(TAG, "close");
                listener.onStatusChanged(status);
            }
        }
    
        /**
         * 
         * @param status
         */
        private void layout(Status status) {
            if (status == Status.Close) {
                hiddenView.layout(itemWidth, 0, itemWidth + hiddenViewWidth,
                        itemHeight);
                itemView.layout(0, 0, itemWidth, itemHeight);
            } else {
                hiddenView.layout(itemWidth - hiddenViewWidth, 0, itemWidth,
                        itemHeight);
                itemView.layout(-hiddenViewWidth, 0, itemWidth - hiddenViewWidth,
                        itemHeight);
            }
        }
    
        /**
         * 侧滑打开
         * 
         * @param smooth
         *            为true则有平滑的过渡动画
         */
        private void open(boolean smooth) {
            preStatus = status;
            status = Status.Open;
            if (smooth) {
                if (mDragHelper.smoothSlideViewTo(itemView, -hiddenViewWidth, 0)) {
                    if (listener != null) {
                        Log.i(TAG, "start open animation");
                        listener.onStartOpenAnimation();
                    }
                    ViewCompat.postInvalidateOnAnimation(this);
                }
            } else {
                layout(status);
            }
            if (listener != null && preStatus == Status.Close) {
                Log.i(TAG, "open");
                listener.onStatusChanged(status);
            }
        }
    
        @Override
        public void computeScroll() {
            super.computeScroll();
            // 开始执行动画
            if (mDragHelper.continueSettling(true)) {
                ViewCompat.postInvalidateOnAnimation(this);
            }
        }
    
        // 让ViewDragHelper来处理触摸事件
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            final int action = ev.getAction();
            if (action == MotionEvent.ACTION_CANCEL) {
                mDragHelper.cancel();
                return false;
            }
            return mDragHelper.shouldInterceptTouchEvent(ev);
        }
    
        // 让ViewDragHelper来处理触摸事件
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            mDragHelper.processTouchEvent(event);
            return true;
        };
    
        @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
            hiddenView = getChildAt(0); // 得到隐藏按钮的linearlayout
            itemView = getChildAt(1); // 得到最上层的linearlayout
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            // 测量子View的长和宽
            itemWidth = itemView.getMeasuredWidth();
            itemHeight = itemView.getMeasuredHeight();
            hiddenViewWidth = hiddenView.getMeasuredWidth();
            hiddenViewHeight = hiddenView.getMeasuredHeight();
        }
    
        @Override
        protected void onLayout(boolean changed, int left, int top, int right,
                int bottom) {
            layout(Status.Close);
        }
    
    }
    
    2.adapter中的布局
    <?xml version="1.0" encoding="utf-8"?>
    <com.sunnet.shipcargo.view.SwipeListLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/sll_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#efefef" >
        //此处放侧滑显示的内容
        <LinearLayout
            android:id="@+id/layout_wharfschedule_rightchange"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="center_vertical"
            android:orientation="horizontal" >
    
            <TextView
                android:id="@+id/tv_off"
                android:layout_width="90dp"
                android:layout_height="match_parent"
                android:background="#D8584B"
                android:gravity="center"
                android:text="删除"
                android:textColor="#ffffff"
                android:textSize="14dp" />
        </LinearLayout>
        //此处放显示内容
         <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="#efefef"
            android:gravity="center_vertical"
            android:paddingLeft="10dp"
            android:orientation="horizontal" >
    
        <TextView
            android:id="@+id/txt_adapter_shipfile_one"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/portd_on"
            android:gravity="center"
            android:text="1" />
    
        <TextView
            android:id="@+id/txt_adapter_shipfile_two"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            android:textStyle="bold"
            android:text="模板号 338" />
    
        <TextView
            android:id="@+id/txt_adapter_shipfile_three"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:textSize="12dp"
            android:text="已认证" />
        </LinearLayout>
    
    </com.sunnet.shipcargo.view.SwipeListLayout>
    
    3.使用
    1.定义侧滑
    private Set<SwipeListLayout> sets = new HashSet<SwipeListLayout>();//全局变量
    2.绑定侧滑布局
    SwipeListLayout sll_main=(SwipeListLayout) contentView.findViewById(R.id.sll_main);//Adapter中的getView绑定
    3.事件注册
    sll_main.setOnSwipeStatusListener(new MyOnSlipStatusListener(viewHolder.sll_main));
    4.事件处理
        /**
         * 侧滑
         * @author 75242
         *
         */
        class MyOnSlipStatusListener implements
                SwipeListLayout.OnSwipeStatusListener {
    
            private SwipeListLayout slipListLayout;
    
            public MyOnSlipStatusListener(SwipeListLayout slipListLayout) {
                this.slipListLayout = slipListLayout;
            }
    
            @Override
            public void onStatusChanged(SwipeListLayout.Status status) {
                if (status == SwipeListLayout.Status.Open) {
                    // 若有其他的item的状态为Open,则Close,然后移除
                    if (sets.size() > 0) {
                        for (SwipeListLayout s : sets) {
                            s.setStatus(SwipeListLayout.Status.Close, true);
                            sets.remove(s);
                        }
                    }
                    sets.add(slipListLayout);
                } else {
                    if (sets.contains(slipListLayout))
                        sets.remove(slipListLayout);
                }
            }
    
            @Override
            public void onStartCloseAnimation() {
    
            }
    
            @Override
            public void onStartOpenAnimation() {
    
            }
    
        }
    

    有任何疑问,请联系我QQ752422962

    相关文章

      网友评论

        本文标题:基于Adapter的侧滑自定义控件(Java)

        本文链接:https://www.haomeiwen.com/subject/jsxodxtx.html