仿荷包投资的滑块

来源:互联网 发布:欧元符号 mac 编辑:程序博客网 时间:2024/04/28 20:32

遇到个需要仿荷包这个滑块的需求

第一想法使用seekbar来实现,结果android:tickMark属性需要API24以上,瞬间无语了,API24的用户目前又有几个呢?

然后想自定义seekbar,结果做出来后拖动的时候一闪一闪的,没有中间过程。

突然想起鸿神的一篇文章里有个拖动控件的ViewDragHelper,http://blog.csdn.net/lmj623565791/article/details/46858663;

稍微修改一下不就是我所需要的吗,我把它里面的多余的去掉,就留了一个回弹的view,然后修改了下回弹的位置,并且用canvas画出几个圆点,大功告成。

先贴上我的布局文件,中间那条线是单独的一个view

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:padding="10dp">    <View        android:layout_width="match_parent"        android:layout_height="3dp"        android:layout_centerVertical="true"        android:background="@color/colorAccent" />    <com.tshouyi.vdhdemo.VDHLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_centerVertical="true"        android:orientation="vertical">        <TextView            android:layout_width="40dp"            android:layout_height="40dp"            android:layout_gravity="left"            android:background="@mipmap/bg"            android:clickable="true"            android:gravity="center"            android:text="back" />    </com.tshouyi.vdhdemo.VDHLayout></RelativeLayout>

代码注释也很详细了,没注释的地方我也不知道

package com.tshouyi.vdhdemo;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Point;import android.support.v4.widget.ViewDragHelper;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.widget.LinearLayout;/** * Created by zxy on 2016/11/11. */public class VDHLayout extends LinearLayout {    private ViewDragHelper mDragger;    private View mAutoBackView;    private Point[] mAutoBackOriginPos =            {                    new Point(0, 0),                    new Point(0, 0),                    new Point(0, 0),                    new Point(0, 0),                    new Point(0, 0),            };//5个原点坐标数组初始值    public VDHLayout(Context context, AttributeSet attrs) {        super(context, attrs);        setWillNotDraw(false);//没这个方法就不执行onDraw,我也不知道为什么        //1、创建实例        mDragger = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback()//3、实现ViewDragHelper.CallCack相关方法        {            /**             * 如果子View不消耗事件(clickable=false),那么整个手势(DOWN-MOVE*-UP)都是直接进入onTouchEvent,在onTouchEvent的DOWN的时候就确定了captureView。             * 如果消耗事件,那么就会先走onInterceptTouchEvent方法,判断是否可以捕获,而在判断的过程中会去判断另外两个回调的方法:             * getViewHorizontalDragRange和getViewVerticalDragRange,只有这两个方法返回大于0的值才能正常的捕获。             */            @Override            public boolean tryCaptureView(View child, int pointerId) {//tryCaptureView如果返回ture则表示可以捕获该view                //mEdgeTrackerView禁止直接移动                return child == mAutoBackView;            }            /**             * clampViewPositionHorizontal,clampViewPositionVertical可以在该方法中对child移动的边界进行控制,             * left , top 分别为即将移动到的位置,以下代码表示内部移动效果             */            @Override            public int clampViewPositionHorizontal(View child, int left, int dx) {                final int leftBound = getPaddingLeft();                final int rightBound = getWidth() - mAutoBackView.getWidth() - leftBound;                final int newLeft = Math.min(Math.max(left, leftBound), rightBound);                return newLeft;            }            @Override            public int clampViewPositionVertical(View child, int top, int dy) {                return mAutoBackOriginPos[0].y;//水平滑动,y是固定的            }            //手指释放的时候回调            @Override            public void onViewReleased(View releasedChild, float xvel, float yvel) {                //mAutoBackView手指释放时可以自动回去                if (releasedChild == mAutoBackView) {                    //判断不同范围回到最近的圆点                    if (mAutoBackView.getLeft() < mAutoBackOriginPos[1].x / 2) {                        mDragger.settleCapturedViewAt(mAutoBackOriginPos[0].x, mAutoBackOriginPos[0].y);                    } else if (mAutoBackView.getLeft() < 3 * mAutoBackOriginPos[1].x / 2) {                        mDragger.settleCapturedViewAt(mAutoBackOriginPos[1].x, mAutoBackOriginPos[0].y);                    } else if (mAutoBackView.getLeft() < 5 * mAutoBackOriginPos[1].x / 2) {                        mDragger.settleCapturedViewAt(mAutoBackOriginPos[2].x, mAutoBackOriginPos[0].y);                    } else if (mAutoBackView.getLeft() < 7 * mAutoBackOriginPos[1].x / 2) {                        mDragger.settleCapturedViewAt(mAutoBackOriginPos[3].x, mAutoBackOriginPos[0].y);                    } else {                        mDragger.settleCapturedViewAt(mAutoBackOriginPos[4].x, mAutoBackOriginPos[0].y);                    }                    invalidate();                }            }            @Override            public int getViewHorizontalDragRange(View child) {                return getMeasuredWidth() - child.getMeasuredWidth();            }            @Override            public int getViewVerticalDragRange(View child) {                return getMeasuredHeight() - child.getMeasuredHeight();            }        });    }    //    2、触摸相关方法    @Override    public boolean onInterceptTouchEvent(MotionEvent event) {        return mDragger.shouldInterceptTouchEvent(event);//决定我们是否应该拦截当前的事件    }    int position;    @Override    public boolean onTouchEvent(MotionEvent event) {        if (event.getX() > mAutoBackView.getLeft() && event.getX() < mAutoBackView.getRight()) {//按下时在滑块范围内说明要拖动            mDragger.processTouchEvent(event);//处理触摸事件        } else {//else滑动滑块到触摸位置最近的圆点            if (event.getX() - 60 < mAutoBackOriginPos[1].x / 2) {                //点击该范围移动到第一个点,60是什么我也不知道,不要这个就点不准                position = 0;            } else if (event.getX() - 60 < 3 * mAutoBackOriginPos[1].x / 2) {                position = mAutoBackOriginPos[1].x;            } else if (event.getX() - 60 < 5 * mAutoBackOriginPos[1].x / 2) {                position = 2 * mAutoBackOriginPos[1].x;            } else if (event.getX() - 60 < 7 * mAutoBackOriginPos[1].x / 2) {                position = 3 * mAutoBackOriginPos[1].x;            } else {                position = 4 * mAutoBackOriginPos[1].x;            }            //1.调用ofInt(int...values)方法创建ValueAnimator对象            int pNow = mAutoBackView.getLeft();            ValueAnimator mAnimator = ValueAnimator.ofInt(pNow, position);            //2.为目标对象的属性变化设置监听器            mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {                @Override                public void onAnimationUpdate(ValueAnimator animation) {                    // 3.为目标对象的属性设置计算好的属性值                    int animatorValue = (int) animation.getAnimatedValue();                    MarginLayoutParams marginLayoutParams = (MarginLayoutParams) mAutoBackView.getLayoutParams();                    marginLayoutParams.leftMargin = animatorValue;                    mAutoBackView.setLayoutParams(marginLayoutParams);                }            });            //4.设置动画的持续时间、是否重复及重复次数等属性            mAnimator.setDuration(Math.abs(pNow - position) * 2);            mAnimator.setRepeatCount(0);            mAnimator.setRepeatMode(ValueAnimator.REVERSE);            //5.为ValueAnimator设置目标对象并开始执行动画            mAnimator.setTarget(mAutoBackView);            mAnimator.start();            invalidate();        }        return true;    }    @Override    public void computeScroll() {        if (mDragger.continueSettling(true)) {            invalidate();        }    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        super.onLayout(changed, l, t, r, b);        //保存5个原点的位置信息(左边缘坐标),不懂的参考图片        for (int i = 0; i < 5; i++) {            mAutoBackOriginPos[i].x = i * ((r - l) - (mAutoBackView.getRight() - mAutoBackView.getLeft())) / 4;            mAutoBackOriginPos[i].y = mAutoBackView.getTop();        }    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        mAutoBackView = getChildAt(0);//加载view    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        Paint paint = new Paint();        paint.setColor(Color.BLUE);        paint.setAntiAlias(true);        //画圆点        for (int i = 0; i < 5; i++) {            canvas.drawCircle(mAutoBackOriginPos[i].x + (mAutoBackView.getRight() - mAutoBackView.getLeft()) / 2,                    mAutoBackOriginPos[i].y + (mAutoBackView.getBottom() - mAutoBackView.getTop()) / 2, 15, paint);        }    }}


不懂的再看一下这张图吧

好了,就这样吧。

顺便把另外一种自定义seek利用seek的进度的方式贴上,原理就是通过改变seekbar的进度来滑动到指定位置。

先看xml文件,两个seekbar重合,上面seekbar个仅仅是为了得到圆点,也就是将Base.Widget.AppCompat.SeekBar.Discrete重新定义了一下,第二个的最大值设置为200

 <RelativeLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="50dp"        android:layout_alignParentTop="true"        android:layout_alignParentLeft="true"        android:layout_alignParentStart="true">        <SeekBar            android:id="@+id/seekBar2"            style="@style/Base.Widget.AppCompat.SeekBar.Seek"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_centerVertical="true"            android:max="4"            android:thumb="@null" />        <SeekBar            android:id="@+id/seekBar"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_alignParentTop="true"            android:layout_centerVertical="true"            android:max="200"            android:progress="0"            android:thumb="@mipmap/ic_launcher" />    </RelativeLayout>

接下来是自定义的样式
    <style name="Base.Widget.AppCompat.SeekBar.Seek">        <item name="tickMark">@drawable/seekbar</item>    </style>
引用的shape文件
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"    android:shape="oval">    <size        android:width="12dp"        android:height="12dp" />    <solid android:color="@android:color/holo_red_dark" /></shape>
activity也很简单,自己看吧
public class MainActivity extends AppCompatActivity {    private SeekBar seekBar;    boolean check = false;    int pro;//用来控制滑动时触发的onProgressChanged不进行滑动    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        seekBar = (SeekBar) findViewById(R.id.seekBar);        SeekBar seekBar2 = (SeekBar) findViewById(R.id.seekBar2);        seekBar2.setEnabled(false);//去除重叠的后面个seekbar的影响        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {            @Override            public void onProgressChanged(final SeekBar seekBar, int i, boolean b) {                if (pro==0||pro == seekBar.getProgress() || pro - 1  == seekBar.getProgress()|| pro+ 1 == seekBar.getProgress() ) {                 //变化值为1的一般不是滑动触发的                    final int progress = seekBar.getProgress();                    pro = progress;                    if (progress < 25) {                        new Handler().postDelayed(new Runnable() {                            @Override                            public void run() {                                if (progress != 0)                                    seekBar.setProgress(progress - 1);                            }                        }, 10);                    } else if (progress < 50) {                        new Handler().postDelayed(new Runnable() {                            @Override                            public void run() {                                seekBar.setProgress(progress + 1);                            }                        }, 10);                    } else if (progress < 75) {                        new Handler().postDelayed(new Runnable() {                            @Override                            public void run() {                                if (progress != 50)                                    seekBar.setProgress(progress - 1);                            }                        }, 10);                    } else if (progress < 100) {                        new Handler().postDelayed(new Runnable() {                            @Override                            public void run() {                                seekBar.setProgress(progress + 1);                            }                        }, 10);                    } else if (progress < 125) {                        new Handler().postDelayed(new Runnable() {                            @Override                            public void run() {                                if (progress != 100)                                    seekBar.setProgress(progress - 1);                            }                        }, 10);                    } else if (progress < 150) {                        new Handler().postDelayed(new Runnable() {                            @Override                            public void run() {                                seekBar.setProgress(progress + 1);                            }                        }, 10);                    } else if (progress < 175) {                        new Handler().postDelayed(new Runnable() {                            @Override                            public void run() {                                if (progress != 150)                                    seekBar.setProgress(progress - 1);                            }                        }, 10);                    } else if (progress < 200) {                        new Handler().postDelayed(new Runnable() {                            @Override                            public void run() {                                seekBar.setProgress(progress + 1);                            }                        }, 10);                    }                }            }            @Override            public void onStartTrackingTouch(SeekBar seekBar) {            }            @Override            public void onStopTrackingTouch(final SeekBar seekBar) {                pro=seekBar.getProgress();                seekBar.setProgress(seekBar.getProgress() - 1);            }        });    }}

最后效果

没怎么写博客,里面问题很多,欢迎指正



0 0
原创粉丝点击