Android自定義View直線比例圖

nsih8320 8年前發布 | 8K 次閱讀 安卓開發 Android開發 移動開發

項目中用到下面的效果:

總共有四種狀態,分四種顏色,根據傳入的每種狀態的比例值在直線上顯示各自的長度。

這種效果最終用兩種方法完成。

第一種

第一種方法是首先想到的一種方法,自定義一個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-灰色比例-紅色比例-黃色比例)。

 

 

 

 本文由用戶 nsih8320 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!