• D2-Android自定义拉绳小控件


    零、前言

    [1].今天忙了大半天重构LogicCanvas库结果还是很令我满意的,LogicCanvas已经升级到V0.02了
    [2].以前想过,以后我变厉害了,一定要写个小拉环,一个晚上总算捣哧出来了
    [3].本控件绘图部分使用我的LogicCanvas绘图库,喜欢的话可以到github上看看,顺便给个star
    [4].动画使用我的NumGo库,由于绘图经常用,所以已经集成到LogicCanvas中了,单独NumGo的github地址
    [5].本文主要讲的是绘制以及事件处理,回调处理,自定义属性就不演示了,可以根据前一篇自己写一下
    [6].注释写得应该很清楚了,我就不废话了。准备瓜子花生米,往下看吧。

    先看看效果:
    9414344-e5737e571a9b0b29.gif
    拉环控件.gif

    一、准备工作:

    1.新建SwitchRopView继承自View:初始化NumGo
    public class SwitchRopView extends View {
    
        public SwitchRopView(Context context) {
            this(context, null, 0);
        }
    
        public SwitchRopView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public SwitchRopView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        public void init() {
            mRunNum = new NumGo(false, -1, 2000).setOnUpdate(new NumGo.OnUpdate() {
                @Override
                public void onUpdate(float rate) {
                    mRotateRate = rate;
                    invalidate();
                }
            });
        }
    }
    
    2.dip2px方法
    public float dip2px(Float dp) {
        if (dp != null) {
            final Float scale = getContext().getResources().getDisplayMetrics().density;
            return dp * scale + 0.5f;
        }
        return dp;
    }
    

    二、成员属性一览

    大注释的都可以做成自定义属性,看你们的需要吧

    //线的属性---------------------------------
    /**
     * 线宽
     */
    private float mRopWidth = dip2px(8f);
    /**
     * 线高
     */
    private float mRopHeight = dip2px(60f);
    /**
     * 线的颜色
     */
    private int mRopColor = 0xff76C5F5;
    //斜线的属性---------------------------------
    /**
     * 斜线宽
     */
    private float mPieceWidth = dip2px(8.5f);
    /**
     * 斜线高
     */
    private float mPieceHeight = dip2px(5f);
    /**
     * 斜线的个数
     */
    private float mPieceCount = 5;
    /**
     * 斜线的颜色
     */
    private int mPieceColor = 0xffFBF579;
    //圆圈的属性---------------------------------
    /**
     * 圆圈半径
     */
    private float mRingR = dip2px(10f);
    /**
     * 圆圈厚度
     */
    private float mRingB = dip2px(6f);
    /**
     * 圆圈颜色
     */
    private int mRingColor = 0xffC4C4BA;
    //小圈的属性---------------------------------
    /**
     * 小圆圈半径
     */
    private float mDorR = dip2px(7f);
    /**
     * 小圆圈厚度
     */
    private float mDotB = dip2px(2f);
    /**
     * 小圆圈颜色
     */
    private int mDotColor = 0xffffffff;
    private NumGo mRunNum;
    private float mRotateRate;//旋转的分度值
    Pos lastPos = new Pos(0, 0);//最后一次坐标点
    long lastTimestamp = 0L;//最后一次的时间戳
    float downHeight = 0;//下拉总量
    boolean isMove = false;//是否移动
    boolean isDown = false;//是否按下
    

    三、绘制方法:onDraw

    @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
          Painter painter = PainterEnum.INSTANCE.getInstance(canvas);
            //绘制线
            Shape rop = new ShapeLine().ps(
                    new Pos(0, 0),
                    new Pos(0, -mRopHeight),
                    new Pos(0 + mRopWidth, -mRopHeight),
                    new Pos(0 + mRopWidth, 0),
                    new Pos(0, 0))
                    .fs(mRopColor).p((2 * mRingR - mRopWidth) / 2, 0f);
            painter.draw(rop);
            //绘制斜线
            ShapeLine piece = new ShapeLine();
            piece.fs(mPieceColor);
            Pos p0 = new Pos(0, 0);
            Pos p1 = new Pos(0, -mPieceHeight);
            Pos p2 = new Pos(mPieceWidth, -mPieceWidth - mPieceHeight);
            Pos p3 = new Pos(mPieceWidth, -mPieceWidth);
            for (int i = 0; i < mPieceCount; i++) {
                piece.ps(p0, p1, p2, p3).p((2 * mRingR - mRopWidth) / 2, -mRopHeight / 5 * i);
                painter.draw(piece);
            }
            //绘制圆圈和点
            ShapeArc ring = new ShapeArc();
            ring.r(mRingR).ang(360f).b(mRingB).ss(mRingColor);
            ShapeArc rot = new ShapeArc();
            rot.r(mDorR).ang(45f).b(mDotB).rot(360 * mRotateRate).ss(mDotColor);
            painter.groupMove(mRingR, -mRopHeight - mRingR + 3, ring, rot);
            painter.draw(ring);
            painter.draw(rot);
        }
    

    四、测量

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            //测量
            setMeasuredDimension((int) (2 * mRingR), (int) dip2px(600f));
        }
    

    五、事件监听

        /////////////////////////////////////////////拉绳拉下监听
    
        /**
         * 拉绳拉下监听
         */
        public interface OnRopDownListener {
            /**
             * 拉绳拉下回调函数
             * @param dataY 下移量
             */
            void ropDown(float dataY);
        }
    
        private OnRopDownListener mOnRopDownListener;
    
        public void setOnRopDownListener(OnRopDownListener onRopDownListener) {
            mOnRopDownListener = onRopDownListener;
        }
    
        /////////////////////////////////////////////拉绳松开监听
    
        /**
         * 拉绳松开监听
         */
        public interface OnRopUPListener {
            /**
             * 拉绳松开回调函数
             */
            void ropUp();
        }
    
        private OnRopUPListener mOnRopUPListener;
    
        public void setOnRopUPListener(OnRopUPListener onRopUPListener) {
            mOnRopUPListener = onRopUPListener;
        }
    

    六、事件处理

        @Override
        public boolean onTouchEvent(MotionEvent event) {
    
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN://按下
                    mRunNum.go();//按下触发RunNum,使得小点旋转
                    lastPos.x = event.getX();
                    lastPos.y = event.getY();
                    lastTimestamp = System.currentTimeMillis();
                    mRingColor = ColUtils.randomRGB();//环设随机色
                    isDown = true;
                    break;
                case MotionEvent.ACTION_UP://抬起
                    mRopHeight = dip2px(60f);//回复到原始高度
                    mRunNum.end();//结束动画
                    if (mOnRopUPListener != null && isMove) {//设置抬起监听
                        mOnRopUPListener.ropUp();//回调抬起函数
                        isMove = false;
                    }
                    downHeight = 0;
                    isDown = false;
                    invalidate();
                    break;
                case MotionEvent.ACTION_MOVE://2
    
                    float x = event.getX();
                    float y = event.getY();
                    Pos curPos = new Pos(x, y);//最后一次坐标点
    
                    long curTimestamp = new Date().getTime();
                    long t = curTimestamp - lastTimestamp;
                    float dataY = curPos.y - lastPos.y;
                    mRopHeight += dataY;
                    downHeight += dataY;
                    if (downHeight > 50) {//下拉高度大于50才算移动
                        isMove = true;
                        if (t > 50) {//时间大于50ms才切换颜色
                            mRopColor = ColUtils.randomRGB();
                        }
                    }
    
                    if (mOnRopDownListener != null) {//下拉过程中的监听
                        mOnRopDownListener.ropDown(downHeight);
                    }
                    lastPos = curPos;//更新位置
                    lastTimestamp = curTimestamp;//更新时间
                    break;
            }
            return true;
        }
    

    七、Activity使用

    public class RopActivity extends AppCompatActivity {
        @BindView(R.id.rop)
        SwitchRopView mRop;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_rop);
            ButterKnife.bind(this);
    
            mRop.setOnRopUPListener(new SwitchRopView.OnRopUPListener() {
                @Override
                public void ropUp() {
                    ToastUtil.show(RopActivity.this, "已松开手");
                }
            });
    
        }
    }
    

    附录、布局文件:.xml
    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.toly1994.d.view.SwitchRopView
            android:id="@+id/rop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>
    
    </android.support.constraint.ConstraintLayout>
    

    后记、

    1.声明:

    [1]本文由张风捷特烈原创,转载请注明
    [2]欢迎广大编程爱好者共同交流
    [3]个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
    [4]你的喜欢与支持将是我最大的动力

    2.连接传送门:

    更多安卓技术欢迎访问:安卓技术栈
    我的github地址:欢迎star
    简书首发,腾讯云+社区同步更新
    张风捷特烈个人网站,编程笔记请访问:http://www.toly1994.com

    3.联系我

    QQ:1981462002
    邮箱:1981462002@qq.com
    微信:zdl1994328

    4.欢迎关注我的微信公众号,最新精彩文章,及时送达:
    9414344-c474349cd3bd4b82.jpg
    公众号.jpg
  • 相关阅读:
    Dockerfile-ADD命令-转载
    华为云上上传镜像到在线镜像仓库
    什么是4D(DRG、DLG、DOM、DEM)数据
    视频对接资料
    OpenLayer改变切片地图的样式-滤镜效果
    Docker-挂载宿主机目录到容器
    RTSP在线视频环境搭建2-海康摄像头
    配置自己风格的Clang-Format-Xcode
    GCDAsyncUdpSocket的使用
    react-native component function
  • 原文地址:https://www.cnblogs.com/toly-top/p/9781902.html
Copyright © 2020-2023  润新知