Android_自定义控件之两圆点之间来回移动加载进度

欢迎加入技术谈论群:714476794

 

一、前言

最近喜欢上自定义控件,喜欢实现一些简约有趣的控件,也好巩固下以前学得知识和不断的学习新知识,程序员嘛,活到老学到老。
这篇文章接着上一篇文章: Android_自定义控件之水平圆点加载进度条,类似的实现方式,都是些比较简单的view绘制。
 

二、实现

先看下实现的效果吧:
 
说下实现思路:圆点x轴会有个位移变化量,当位移达到圆点直径+圆点间距之和就回改变方向(改变方向就是通过变化量值不断增加和不断减少来实现),可能写的有点模糊,接下来看代码:
package com.kincai.testcustomview_dotalternatelyprogress;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

/**
 * Copyright (C) 2015 The KINCAI Open Source Project
 * .
 * Create By KINCAI
 * .
 * Time 2017-06-16 21:44
 * .
 * Desc 两个源点来回移动
 */

public class DotAlternatelyView extends View {
    private final String TAG = this.getClass().getSimpleName();
    private Paint mPaint = new Paint();
    /**
     * 可视为左边圆点颜色值
     */
    private int mLeftColor;
    /**
     * 可视为右边圆点颜色值
     */
    private int mRightColor;
    /**
     * 圆点半径
     */
    private int mDotRadius;
    /**
     * 圆点间距
     */
    private int mDotSpacing;
    /**
     * 圆点位移量
     */
    private float mMoveDistance;
    /**
     * 圆点移动率
     */
    private float mMoveRate;
    /**
     * 以刚开始左边圆点为准 向右移
     */
    private final int DOT_STATUS_RIGHT = 0X101;
    /**
     * 以刚开始左边圆点为准 圆点移动方向-向左移
     */
    private final int DOT_STATUS_LEFT = 0X102;
    /**
     * 以刚开始左边圆点为准,圆点移动方向
     */
    private int mDotChangeStatus = DOT_STATUS_RIGHT;
    /**
     * 圆点透明度变化最大(也就是透明度在255-mAlphaChangeTotal到255之间)
     */
    private int mAlphaChangeTotal = 130;
    /**
     * 透明度变化率
     */
    private float mAlphaChangeRate;
    /**
     * 透明度改变量
     */
    private float mAlphaChange;

    public DotAlternatelyView(Context context) {
        this(context, null);
    }

    public DotAlternatelyView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DotAlternatelyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DotAlternatelyView, defStyleAttr, 0);
        initAttributes(typedArray);
        typedArray.recycle();
        init();
    }

    private void initAttributes(TypedArray Attributes) {
        mLeftColor = Attributes.getColor(R.styleable.DotAlternatelyView_dot_dark_color, ContextCompat.getColor(getContext(), R.color.colorPrimary));
        mRightColor = Attributes.getColor(R.styleable.DotAlternatelyView_dot_light_color, ContextCompat.getColor(getContext(), R.color.colorAccent));
        mDotRadius = Attributes.getDimensionPixelSize(R.styleable.DotAlternatelyView_dot_radius, DensityUtils.dp2px(getContext(), 3));
        mDotSpacing = Attributes.getDimensionPixelSize(R.styleable.DotAlternatelyView_dot_spacing, DensityUtils.dp2px(getContext(), 6));
        mMoveRate = Attributes.getFloat(R.styleable.DotAlternatelyView_dot_move_rate, 1.2f);
    }

    /**
     * 初始化
     */
    private void init() {
        //移动总距离/移动率 = alpha总变化/x
        //x = 移动率 * alpha总变化 / 移动总距离
        mAlphaChangeRate = mMoveRate * mAlphaChangeTotal / (mDotRadius * 2 + mDotSpacing);
        mPaint.setColor(mLeftColor);
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        Log.e(TAG, " aaaa " + mAlphaChangeRate);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //测量宽高
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int width;
        int height;

        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
            Log.e(TAG, "onMeasure MeasureSpec.EXACTLY widthSize=" + widthSize);
        } else {
            //指定最小宽度所有圆点加上间距的宽度, 以最小半径加上间距算总和再加上最左边和最右边变大后的距离
            width = (mDotRadius * 2) * 2 + mDotSpacing;
            Log.e(TAG, "onMeasure no MeasureSpec.EXACTLY widthSize=" + widthSize + " width=" + width);
            if (widthMode == MeasureSpec.AT_MOST) {
                width = Math.min(width, widthSize);
                Log.e(TAG, "onMeasure MeasureSpec.AT_MOST width=" + width);
            }

        }

        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
            Log.e(TAG, "onMeasure MeasureSpec.EXACTLY heightSize=" + heightSize);
        } else {
            height = mDotRadius * 2;
            Log.e(TAG, "onMeasure no MeasureSpec.EXACTLY heightSize=" + heightSize + " height=" + height);
            if (heightMode == MeasureSpec.AT_MOST) {
                height = Math.min(height, heightSize);
                Log.e(TAG, "onMeasure MeasureSpec.AT_MOST height=" + height);
            }

        }
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //左边圆点起点x轴
        int startPointX = getWidth() / 2 - (2 * mDotRadius * 2 + mDotSpacing) / 2 + mDotRadius;
        //左边圆点起点y轴
        int startPointY = getHeight() / 2;
        //向右移 位移要增加对应透明度变化量也需要增加 反之都需要减小
        if (mDotChangeStatus == DOT_STATUS_RIGHT) {
            mMoveDistance += mMoveRate;
            mAlphaChange += mAlphaChangeRate;
        } else {
            mAlphaChange -= mAlphaChangeRate;
            mMoveDistance -= mMoveRate;
        }
        Log.e(TAG, "mAlphaChange " + mAlphaChange);
        //当移动到最右 那么需要改变方向 反过来
        if (mMoveDistance >= mDotRadius * 2 + mDotSpacing && mDotChangeStatus == DOT_STATUS_RIGHT) {
            mDotChangeStatus = DOT_STATUS_LEFT;
            mMoveDistance = mDotRadius * 2 + mDotSpacing;
            mAlphaChange = mAlphaChangeTotal;
        } else if (mMoveDistance <= 0 && mDotChangeStatus == DOT_STATUS_LEFT) { //当移动到最座 那么需要改变方向 反过来
            mDotChangeStatus = DOT_STATUS_RIGHT;
            mMoveDistance = 0f;
            mAlphaChange = 0f;
        }

        //因为两个圆点可能会给定不同的颜色来显示 所以提供两种颜色设置mLeftColor和mRightColor
        mPaint.setColor(mLeftColor);
        mPaint.setAlpha((int) (255 - mAlphaChange));
        canvas.drawCircle(startPointX + mMoveDistance, startPointY, mDotRadius, mPaint);
        mPaint.setColor(mRightColor);
        mPaint.setAlpha((int) (255 - mAlphaChange));
        canvas.drawCircle(startPointX + mDotRadius * 2 - mMoveDistance + mDotSpacing, startPointY, mDotRadius, mPaint);

        invalidate();
    }
}
 
要是不容易理解的话,下载源码运行再对着源码看会容易理解
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值