Android自定义View直线比例图

nsih8320 8年前
   <p>项目中用到下面的效果:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/fdedc0f77b95bde128e9c646018e561c.png"></p>    <p>总共有四种状态,分四种颜色,根据传入的每种状态的比例值在直线上显示各自的长度。</p>    <p>这种效果最终用两种方法完成。</p>    <h3><strong>第一种</strong></h3>    <p>第一种方法是首先想到的一种方法,自定义一个FrameLayout,在里面有四个互相重叠的Imageview或者textview。背景使用shpe绘制四个圆角矩形。然后根据传入的值动态改变imageview或者textview的宽度</p>    <p>shape:</p>    <pre>  <code class="language-java"><?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></code></pre>    <p>view:</p>    <pre>  <code class="language-java">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);          }      }  }</code></pre>    <h3><strong>第二种</strong></h3>    <p>第一种还是有点麻烦,得写四种shape 创建textview对象。其实想一想这个效果直接在view上绘制小圆角矩形不就行了,于是有了第二种:</p>    <pre>  <code class="language-java">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();      }  }</code></pre>    <p>绘制流程:</p>    <p>先绘制灰色、红色,黄色、蓝色。一层一层的覆盖。</p>    <p>最主要的方法就是setScales() 方法。因为绘制的流程是先绘制最后一个颜色(灰色)其实灰色永远都是绘制百分之百的宽度。红色的宽度就是总宽度乘以(1-灰色比例),黄色宽度是 总宽度乘以(1-灰色比例-红色宽度),蓝色宽度是总宽度乘以它自己的比例或者乘以(1-灰色比例-红色比例-黄色比例)。</p>    <p> </p>    <p> </p>    <p> </p>