美文网首页android
android 自定义垂直滑动选值

android 自定义垂直滑动选值

作者: android_haihong | 来源:发表于2019-02-24 22:32 被阅读67次

    今天周日 记录一个小demo.

    之前看到某德扑游戏有个(梭哈/all in)下注的操作
    感觉挺好意思的,实现了下
    上效果:


    video2gif_20190224_175958.gif

    大概画个图声明下原理


    image.png

    代码实现也是挺简洁的,很多东西明白原理了就很简单了,其实我当时实现花了很长时间,这个是最后的精华版本:
    布局代码:

    <?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:orientation="vertical">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:layout_marginBottom="10dp"
            android:focusable="false"
            android:orientation="vertical">
    
            <FrameLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_gravity="center"
                android:layout_weight="1"
                android:layout_marginBottom="10dp"
                android:focusable="false">
    
                <LinearLayout
                    android:id="@+id/fl_container"
                    android:layout_width="60dp"
                    android:layout_height="match_parent"
                    android:layout_gravity="center|bottom"
                    android:layout_marginBottom="55dp"
                    android:layout_weight="1"
                    android:gravity="bottom"
                    android:orientation="vertical" />
    
                <ImageView
                    android:layout_width="70dip"
                    android:layout_height="70dip"
                    android:layout_alignParentBottom="true"
                    android:layout_centerHorizontal="true"
                    android:layout_gravity="bottom"
                    android:src="@mipmap/ziyoujiazhu2x" />
    
                <LinearLayout
                    android:id="@+id/ll_container"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_gravity="center|top"
                    android:layout_marginBottom="20dp"
                    android:layout_weight="1"
                    android:gravity="bottom"
                    android:orientation="vertical">
    
                    <ImageView
                        android:id="@+id/iv_move"
                        android:layout_width="25dip"
                        android:layout_height="25dip"
                        android:layout_gravity="center|bottom"
                        android:src="@mipmap/png" />
                </LinearLayout>
            </FrameLayout>
    
            <TextView
                android:id="@+id/num"
                android:layout_width="match_parent"
                android:layout_height="30dp"
                android:focusable="false"
                android:gravity="center"
                android:text="100"
                android:textColor="@color/black"
                android:textSize="15sp" />
        </LinearLayout>
    
    </RelativeLayout>
    

    可以看到显示的数值view和滑动的那个logo,是通过FrameLayout来达到一个层叠的效果
    布局很简单,认真看看就知道原理了

    然后是实现代码:
    注释我也直接写代码里面了

    public class SlideActivity extends Activity {
    
        private LinearLayout ll_container;
        private ImageView ivMove;
    
        private int containerWidth, containerHeight;    //容器宽高
        private float lastX, lastY; //最后一次触摸事件的坐标
        private float actY1;
        private TextView num;
        TextView showText[];
        private int showNum;
        //滑动下注
        private LinearLayout params;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_slide);
    
            addView();
            initXYview();
    
            //咱们让数值默认隐藏状态
            HIDE();
        }
    
        /**
         * 滑动自由下注 (动态生成滑动条)====================================================================
         */
        private void addView() {
            int cost = 5000;
            showNum = 35;
            //这个是获取到的坐标数值
            num = (TextView) findViewById(R.id.num);
    
            //创建一个textview数据作为动态view
            showText = new TextView[showNum];
            for (int i = 0; i < showNum; i++) {
                showText[i] = new TextView(this);
                final TextView showText1 = new TextView(this);
                showText[i].setGravity(Gravity.CENTER | Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
                showText[i].setTag(i); //设置id
                showText[i].setTextColor(Color.WHITE);
    
                // set 文本大小
                showText1.setTextColor(Color.TRANSPARENT);
                showText1.setHeight(4);
                showText1.setWidth(4);
    
                //这个就是动态view的容器
                params = (LinearLayout) findViewById(R.id.fl_container);
                params.setGravity(Gravity.BOTTOM | Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL);
                //添加文本到主布局
                params.addView(showText[i]);
                params.addView(showText1);
                //设置不同点位的样式
                if (i == 0) {
                    showText[i].setBackgroundResource(R.drawable.btn_data2);
                    showText[i].setText(String.valueOf(cost));
                    showText[i].getLayoutParams().width = ((int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_DIP, 52, getResources().getDisplayMetrics()));
                    showText[i].getLayoutParams().height = ((int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_DIP, 22, getResources().getDisplayMetrics()));
                } else if (i == showNum / 2) {
                    showText[i].setBackgroundResource(R.drawable.btn_data2);
                    showText[i].setText(String.valueOf(cost / 2));
                    showText[i].getLayoutParams().width = ((int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_DIP, 52, getResources().getDisplayMetrics()));
                    showText[i].getLayoutParams().height = ((int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_DIP, 22, getResources().getDisplayMetrics()));
                } else if (i == showNum - 1) {
                    showText[i].setBackgroundResource(R.drawable.btn_data2);
                    showText[i].setText("100");
                    showText[i].getLayoutParams().width = ((int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_DIP, 52, getResources().getDisplayMetrics()));
                    showText[i].getLayoutParams().height = ((int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_DIP, 22, getResources().getDisplayMetrics()));
                } else {
                    showText[i].setBackgroundResource(R.drawable.msg_num_shape);
                    showText[i].setText(String.valueOf(cost / showNum * (showNum - i)));
                    showText[i].setTextSize(0);
                    showText[i].getLayoutParams().width = ((int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_DIP, 6, getResources().getDisplayMetrics()));
                    showText[i].getLayoutParams().height = ((int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_DIP, 6, getResources().getDisplayMetrics()));
                }
            }
    
        }
    
        /**
         * 滑动取值
         */
        @SuppressLint("ClickableViewAccessibility")
        /**
         * 关键>>>>>
         * 滑动自由下注 ================================================================================
         */
        private void initXYview() {
            ll_container = (LinearLayout) findViewById(R.id.ll_container);
            ll_container.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    //不能直接在onCreate()方法中得到宽高,会得到0,所以注册视图树的观察者来得到宽高
                    //OnPreDrawListener是当一个视图树将要绘制时,所要调用的回调函数的接口类
                    containerWidth = ll_container.getWidth();
                    containerHeight = ll_container.getHeight();
                    return true;
                }
            });
    
            ivMove = (ImageView) findViewById(R.id.iv_move);     //滑动logo
            ivMove.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
                    ivMove.setVisibility(View.VISIBLE);
                    switch (motionEvent.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            // 记录触摸时的坐标,这里为什么要用getRawX()和getRawY(),
                            // 相信理解getX(),getY()和getRawX(),getRawY()的区别就知道为什么了
                            lastX = motionEvent.getRawX();
                            lastY = motionEvent.getRawY();
    
                            actY1 = ivMove.getY();
                            DIAPLAY(); //显示滑动条
    
                            //return true对事件进行拦截,不继续下发,防止继续响应onClick事件.
                            return true;
                        case MotionEvent.ACTION_MOVE:
                            //每次移动的距离
                            float distanceX = motionEvent.getRawX() - lastX;
                            float distanceY = motionEvent.getRawY() - lastY;
    
                            //控件将要移动到的位置,先计算一下,不在ofFloat()方法中
                            // 再计算是因为要防止控件移动到容器之外.
                            float nextX = ivMove.getX() + distanceX;
                            float nextY = ivMove.getY() + distanceY;
                            //如果将要移动到的 x 轴坐标小于0,则等于0,防止移出容器左边
                            if (nextX < 0)
                                nextX = 0;
                            //防止移出容器右边
                            if (nextX > containerWidth - ivMove.getWidth())
                                nextX = containerWidth - ivMove.getWidth();
                            //防止移出容器顶边
                            if (nextY < 0)
                                nextY = 0;
                            //防止移出容器底边
                            if (nextY > containerHeight - ivMove.getHeight())
                                nextY = containerHeight - ivMove.getHeight();
    
                            if (nextY < showText[0].getY())
                                nextY = showText[0].getY();
                            //利用属性动画改变控件的x,y坐标
                            ObjectAnimator mObjectAnimatorX = ObjectAnimator.ofFloat(ivMove,
                                    "x", ivMove.getX(), nextX);
                            ObjectAnimator mObjectAnimatorY = ObjectAnimator.ofFloat(ivMove,
                                    "y", ivMove.getY(), nextY);
                            AnimatorSet mAnimatorSet = new AnimatorSet();
                            mAnimatorSet.playTogether(mObjectAnimatorX, mObjectAnimatorY);
                            mAnimatorSet.setDuration(0);
                            mAnimatorSet.start();
                            //移动完之后记录当前坐标
                            lastX = motionEvent.getRawX();
                            lastY = motionEvent.getRawY();
    
                            MatchingY(ivMove.getY());
                            break;
                        case MotionEvent.ACTION_UP:
                            HIDE();
    
                            //结束后回到原位
                            //利用属性动画改变控件的x,y坐标
                            ObjectAnimator mObjectAnimatorXX = ObjectAnimator.ofFloat(ivMove,
                                    "x", ivMove.getX(), 0);
                            ObjectAnimator mObjectAnimatorYY = ObjectAnimator.ofFloat(ivMove,
                                    "y", ivMove.getY(), actY1);
                            AnimatorSet mAnimatorSetX = new AnimatorSet();
                            mAnimatorSetX.playTogether(mObjectAnimatorXX, mObjectAnimatorYY);
                            mAnimatorSetX.setDuration(0);
                            mAnimatorSetX.start();
    
                            break;
                    }
                    return false;
                }
            });
        }
    
        //匹配滑动坐标取值
        //这一步就是将滑动位置和数值所在位置坐标匹配,就能拿到准确的数值了
        private void MatchingY(float y) {
            float showy;
            for (int i = 0; i < showNum; i++) {
                showy = showText[i].getY();
                if (showy - 2 < y && y < showy + 2) {   // -2 和 +2 是因为view中存在间隔,为的是更精确的取值
                    num.setText(showText[i].getText().toString());
                } else if (showText[showNum - 1].getY() - 2 < y) {
                    num.setText("100");
                }
            }
        }
    
        //隐藏数值还有滑动view
        private void HIDE() {
            params.setVisibility(View.INVISIBLE);
            ivMove.setBackgroundResource(R.mipmap.png);
        }
    
        //显示数值还有滑动view
        private void DIAPLAY() {
            params.setVisibility(View.VISIBLE);
            ivMove.setBackgroundResource(R.mipmap.my_gold2x);
        }
    
    }
    

    上github 链接:(https://github.com/a824676719/ViewDemo)

    相关文章

      网友评论

        本文标题:android 自定义垂直滑动选值

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