zoukankan      html  css  js  c++  java
  • 手把手实现腾讯qq拖拽删去效果(一)

      qq拖拽删除的效果,简单又好用,今天我就叫大家实现吧。

      这个滑动效果,有何难点了,就是响应每行的点击事件了,为了完成这个任务,并且能够实现动画的效果了,我重写了一个slideview这个控件,这个控件是干什么的了,是一个类似于viewflipper带动画的翻页控件了。它又是任何布局,任何控制了。

      首先,我们赏析一下它的布局文件:

    <merge xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <LinearLayout
            android:id="@+id/view_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal" >
        </LinearLayout>
    
        <RelativeLayout
            android:id="@+id/holder"
            android:layout_width="120dp"
            android:layout_height="match_parent"
            android:clickable="true"
            android:background="@drawable/delete_holder_bg">
    
            <TextView
                android:id="@+id/delete"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawableLeft="@drawable/delete_icon_normal"
                android:layout_centerInParent="true"
                android:gravity="center"
                android:textColor="@color/floralwhite"
                android:text="删除" />
        </RelativeLayout>
    
    </merge>

      由布局文件,可得知:

      ①由一对<merge>....</merge>标签包裹了里面的容器,merge标签是什么了,又有什么作用了。可以使用<merge>标签,它将它里面嵌套的view直接include到其父layout中,而没有再加一层view group,因此减小了深度,提高了速度。在这里了,我们就是将一个linearlayout的线性表局文件和relative布局文件嵌套其中了。

      ②relativelayout是显示相应的删除的按钮,而linearlayout主要是显示需要加载数据的值。

      具体的说明,请见下图:

      这里我们首先说明了布局文件,接下来就是控制文件了。

      控制文件的代码如何,我们来瞧一瞧:

    package com.routemap_infomation.utils;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.util.TypedValue;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.LinearLayout;
    import android.widget.RelativeLayout;
    import android.widget.Scroller;
    import android.widget.TextView;
    
    import com.routemap_infomation.myfocus.R;
    
    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 = 100;
    
        private int mLastX = 0;
        private int mLastY = 0;
        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;
    
            /**
             * @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);
    
            setOrientation(LinearLayout.HORIZONTAL);
            View.inflate(mContext, R.layout.delete_button, this);
            mViewContent = (LinearLayout) findViewById(R.id.view_content);
            mHolderWidth = Math.round(TypedValue.applyDimension(
                    TypedValue.COMPLEX_UNIT_DIP, mHolderWidth, getResources()
                            .getDisplayMetrics()));
        }
    
        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) {
            
            int x = (int) event.getX();
            int y = (int) event.getY();
            int scrollX = getScrollX();
            Log.d(TAG, "x=" + x + "  y=" + y);
    
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }
                if (mOnSlideListener != null) {
                    mOnSlideListener.onSlide(this,
                            OnSlideListener.SLIDE_STATUS_START_SCROLL);
                }
                break;
            }
            case MotionEvent.ACTION_MOVE: {
            
                int deltaX = x - mLastX;
                int deltaY = y - mLastY;
                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;
                    }
                    this.scrollTo(newScrollX, 0);
                }
                break;
            }
            case MotionEvent.ACTION_UP: {
            
                int newScrollX = 0;
                if (scrollX - mHolderWidth * 0.75 > 0) {
                    newScrollX = mHolderWidth;
                }
                this.smoothScrollTo(newScrollX, 0);
                if (mOnSlideListener != null) {
                    mOnSlideListener.onSlide(this,
                            newScrollX == 0 ? OnSlideListener.SLIDE_STATUS_OFF
                                    : OnSlideListener.SLIDE_STATUS_ON);
                    return false;
                }
               // break;
            }
            default:
                break;
            }
    
            mLastX = x;
            mLastY = y;
            return true;
        }
    
        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()) {
                scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
                postInvalidate();
            }
        }
    
    }

      由代码我们可以下这样的结论了:

      ①这个控件其实本质是一个线性布局(Linearlayout)控件,因此就具有了linearlayout的属性。

      ②我上文说过这个控件是为了实现一个viewflipper翻页动画效果,因此需要一个动画效果,这里,我没有做自身的动画,而是通过了scroller本身滑动带有的动画效果。

      ③因为是拖拽,所以监听屏幕的触摸事件也是理所当然了,因此需要处理好触摸按下(down),触摸移动(move),抬起(up)的事件,对其相应事件下,scroller(滑动条)移动的距离需要进行监听。

      ④由于要移动控件,移动后,相应的控件需要进行了重回。

      这就是我实现了拖拽效果的一利器,今天就介绍到这里了。下节,来说明吧它如何整合到自定义的下拉列表中去。 

      

  • 相关阅读:
    数论
    2019牛客暑期多校训练营(第七场)
    C++大数模板
    网络流
    2019 Multi-University Training Contest 6
    无聊的数列
    Can you answer on these queries III
    Interval GCD
    2733:判断闰年-poj
    题目1083:特殊乘法-九度oj
  • 原文地址:https://www.cnblogs.com/manuosex/p/3633463.html
Copyright © 2011-2022 走看看