剑客
关注科技互联网

[原]Android自定义View直线比例图

项目中用到下面的效果:

[原]Android自定义View直线比例图

总共有四种状态,分四种颜色,根据传入的每种状态的比例值在直线上显示各自的长度。

这种效果最终用两种方法完成。

第一种

第一种方法是首先想到的一种方法,自定义一个FrameLayout,在里面有四个互相重叠的Imageview或者textview。背景使用shpe绘制四个圆角矩形。然后根据传入的值动态改变imageview或者textview的宽度

shape:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <!-- 圆角 -->
    <corners
        android:radius="10dp"
        />
    <solid android:color="@color/patrol_no_start_gray"/>
</shape>

view:

package com.chs.listtext;

import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;

/**
 * 作者:chs on 2016/9/27 14:02
 * 邮箱:657083984@qq.com
 */

public class ProgressScaleView extends FrameLayout {
    private int[] resId = new int[]{R.drawable.shape_patrol_corners_gray, R.drawable.shape_patrol_corners_red,
            R.drawable.shape_patrol_corners_yellow,
            R.drawable.shape_patrol_corners_blue};
    private double [] scales = new double[4];
    private int mWidth;
    public ProgressScaleView(Context context) {
        super(context);
        init(context);
    }

    public ProgressScaleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ProgressScaleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    public void setScales(double[] scales) {
        this.scales = scales;
        invalidate();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        int count = getChildCount();
        //依次改变textview的宽度
        for (int i = 0; i < count; i++) {
            TextView view = (TextView) getChildAt(i);
            float scale = 0;
            for(int j = 0;j<scales.length-i;j++){
                scale+=scales[j];
            }
                view.getLayoutParams().width = (int) (mWidth*scale);
        }
    }

    private void init(Context context) {
        mWidth = context.getResources().getDisplayMetrics().widthPixels-DensityUtil.dip2px(context, 40);
        //创建四个textview 宽度都为ViewGroup.LayoutParams.MATCH_PARENT 依次覆盖
        for (int i = 0; i < 4; i++) {
            TextView textView = new TextView(context);
            textView.setHeight(DensityUtil.dip2px(context, 20));
            textView.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
            textView.setBackgroundResource(resId[i]);
            addView(textView);
        }
    }
}

第二种

第一种还是有点麻烦,得写四种shape 创建textview对象。其实想一想这个效果直接在view上绘制小圆角矩形不就行了,于是有了第二种:

package com.hsm.bxt.widgets;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import com.hsm.bxt.utils.DensityUtil;

/**
 * 作者:chs on 2016/9/28 10:03
 * 邮箱:657083984@qq.com
 */

public class ScaleView extends View {
    private int mWidth;
    private RectF mRect1;
    private RectF mRect2;
    private RectF mRect3;
    private RectF mRect4;
    private Paint mPaint;
    private int [] mColors = new int[]{Color.parseColor("#C4D4E8"),Color.parseColor("#FF727A"),Color.parseColor("#FFC636"),Color.parseColor("#44B2FE")};
    private static final int BG_COLOR = Color.parseColor("#FFFFFF");
    public ScaleView(Context context) {
        super(context);
        init(context);
    }

    public ScaleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ScaleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }
    private void init(Context context) {
        setWillNotDraw(false);
        int height = DensityUtil.dip2px(context, 10);
        mWidth = context.getResources().getDisplayMetrics().widthPixels-DensityUtil.dip2px(context, 40);
        mRect1 = new RectF(0,0,0, height);
        mRect2 = new RectF(0,0,0, height);
        mRect3 = new RectF(0,0,0, height);
        mRect4 = new RectF(0,0,0, height);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        mWidth = w;
        super.onSizeChanged(w, h, oldw, oldh);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(BG_COLOR);
        mPaint.setColor(mColors[0]);
        canvas.drawRoundRect(mRect1,15,15,mPaint);
        mPaint.setColor(mColors[1]);
        canvas.drawRoundRect(mRect2,15,15,mPaint);
        mPaint.setColor(mColors[2]);
        canvas.drawRoundRect(mRect3,15,15,mPaint);
        mPaint.setColor(mColors[3]);
        canvas.drawRoundRect(mRect4,15,15,mPaint);
    }

    /**
     * 给数据赋值
     * @param scales
     */
    public void setScales(double[] scales){
        float scale1 = 0;
        for (int j = 0; j < scales.length - 0; j++) {
            scale1 += scales[j];
        }
        mRect1.right = (int) (mWidth*scale1);
        float scale2 = 0;
        for (int j = 0; j < scales.length - 1; j++) {
            scale2 += scales[j];
        }
        mRect2.right = (int) (mWidth*scale2);
        float scale3 = 0;
        for (int j = 0; j < scales.length - 2; j++) {
            scale3 += scales[j];
        }
        mRect3.right = (int) (mWidth*scale3);
        float scale4 = 0;
        for (int j = 0; j < scales.length - 3; j++) {
            scale4 += scales[j];
        }
        mRect4.right = (int) (mWidth*scale4);
        invalidate();
    }
}

绘制流程:

先绘制灰色、红色,黄色、蓝色。一层一层的覆盖。

最主要的方法就是setScales() 方法。因为绘制的流程是先绘制最后一个颜色(灰色)其实灰色永远都是绘制百分之百的宽度。红色的宽度就是总宽度乘以(1-灰色比例),黄色宽度是 总宽度乘以(1-灰色比例-红色宽度),蓝色宽度是总宽度乘以它自己的比例或者乘以(1-灰色比例-红色比例-黄色比例)。

OK完事。源码在 图表库 中的ScaleView。

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址