做过的自定义 View

做过的自定义 View

 

 

音频条状图


需求



音频图
  1. 最终效果类似于音频图中的条状图

  2. 只是效果模拟,并不监听真实的音频

  3. 条的宽度相同,高度随机;条的颜色是红到黄的线性渐变

  4. 随着时间的变化,条的高度发生变化

详细设计


  1. 自定义属性

    1. 条的宽度(默认 3dp

    2. 条的颜色变化范围(两个颜色——默认红色、橙色)

    3. 条之间的间距

    4. 整个 View 的背景颜色

    5. 变化的频率,单位是毫秒

  2. 处理起始绘制的坐标,并结合条间距计算 View 能显示多少个条。计算方法:条的总数 = (View 的宽度 - 条间距 * 2) / (条的宽度 + 条间距)

  3. 随机生成条的高度,高度的范围:[1, 控件的高度]

  4. 条的颜色在两个颜色之间,随时间呈线性梯度变化

具体实现


  1. 定义自定义属性(res/values/attrs.xml):

    <declare-styleable name="AudioBarChart">
        <attr name="barWidth" format="reference|dimension" /><!-- 条的宽度,默认 3dp -->
        <attr name="barStartColor" format="reference|color" /><!-- 条颜色的起始值,默认红色 -->
        <attr name="barEndColor" format="reference|color" /><!-- 条颜色的结束值,默认橙色 -->
        <attr name="barSpace" format="reference|dimension" /><!-- 条间距,默认 1dp -->
        <attr name="wholeBgColor" format="reference|color" /><!-- 整个的背影颜色,默认白色 -->
        <attr name="changeFrenquency" format="integer" /><!-- 条变化的频率,单位毫秒,默认 300 -->
    </declare-styleable>
    
  2. 获取自定义属性并指定默认值:

    public AudioBarChart(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AudioBarChart);
    
            mBarWidth = (int) typedArray.getDimension(R.styleable.AudioBarChart_barWidth, 20);
            mBarStartColor = typedArray.getColor(R.styleable.AudioBarChart_barStartColor, getResources().getColor(R.color.audio_bar_chart_red));
            mBarEndColor = typedArray.getColor(R.styleable.AudioBarChart_barEndColor, getResources().getColor(R.color.audio_bar_chart_orange));
            mBarSpace = (int) typedArray.getDimension(R.styleable.AudioBarChart_barSpace, 5);
            mWholeBgColor = typedArray.getColor(R.styleable.AudioBarChart_wholeBgColor, getResources().getColor(android.R.color.white));
            mChangeFrequency = typedArray.getInt(R.styleable.AudioBarChart_changeFrenquency, 300);
    
            typedArray.recycle();
    }
    
  3. 测量并初始化变量值:

    @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
                mWidth = MeasureSpec.getSize(widthMeasureSpec);
                mHeight = MeasureSpec.getSize(heightMeasureSpec);
    
                setMeasuredDimension(mWidth, mHeight);
    
                mBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
                mBarPaint.setStyle(Paint.Style.FILL);
    
                mBarCount = (mWidth - mBarSpace * 2) / (mBarWidth + mBarSpace);
        }
    
  4. 绘制:

    @Override
    protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
            setBackgroundColor(mWholeBgColor);
            for (int i = 0; i < mBarCount; i++) {
                int height = mHeight - new Random().nextInt(mHeight * 3 / 4);
                int x = (i + 1) * mBarSpace + i * mBarWidth;
                Rect rect = new Rect(x, height, x + mBarWidth, mHeight);
                mLinearGradient = new LinearGradient(x, mHeight, x + mBarWidth, height, mBarStartColor, mBarEndColor, Shader.TileMode.CLAMP);
                mBarPaint.setShader(mLinearGradient);
                canvas.drawRect(rect, mBarPaint);
            }
            postInvalidateDelayed(mChangeFrequency);
    }
    
  5. 最终效果:


最终效果
原文地址:https://www.cnblogs.com/wchhuangya/p/5861452.html