国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android自定義控件實現折線圖

2019-10-21 21:31:53
字體:
來源:轉載
供稿:網友

本文實例實現一個如下圖所示的Android折線圖,供大家參考,具體內容如下

Android,自定義控件,折線圖

Android,自定義控件,折線圖

Android,自定義控件,折線圖

首先是控件繪圖區域的劃分,控件左邊取一小部分(控件總寬度的八分之一)繪制表頭,右邊剩余的部分繪制表格

確定表格的行列數,首先繪制一個三行八列的網格,設置好行列的坐標后開始繪制

/*繪制三條橫線*/for(int i=0;i<3;i++){  canvas.drawLine(textWide, mLineYs[i], totalWidth, mLineYs[i], mPaintLine);}/*繪制八條豎線*/for(int i=0;i<8;i++){  canvas.drawLine(mLineXs[i], 0, mLineXs[i], totalHeight, mPaintLine);}

網格繪制完成后,開始繪制折線圖

根據輸入的節點數據,分別繪制兩條折線

通過canvas的drawLine方法依次連接兩點即可

在每個數據節點處繪制一個小圓,突出顯示

/*繪制第一條折線的路徑*/for (int i = 0; i < mPerformance_1.length - 1; i++) {  /*折線圖的折線的畫筆設置粗一點*/  mPaintLine.setStrokeWidth(5);  /*計算當前節點的坐標值*/  float prePointX =mLineXs[i];  float prePointY =mLineYs[2] - (mLineYs[2] - mLineYs[mPerformance_1[i].type]) * animCurrentValue;  /*計算下一個節點的坐標值*/  float nextPointX=mLineXs[i + 1];  float nextPointY=mLineYs[2] - (mLineYs[2] - mLineYs[mPerformance_1[i + 1].type]) * animCurrentValue;  /*連接當前坐標和下一個坐標,繪制線段*/  canvas.drawLine(prePointX, prePointY, nextPointX, nextPointY, mPaintLine1);  /*當前節點坐標處繪制小圓*/  canvas.drawCircle(prePointX, prePointY, mSmallDotRadius, mPointPaint);}

兩條折線重合的地方,需要特殊考慮,比如希望兩條折線重合的地方折線變為白色

設置下兩條折線的畫筆即可

mPaintLine2.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));mPaintLine1.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));

Android,自定義控件,折線圖

測試代碼及效果;

final Random random=new Random();final LineChartView myView=(LineChartView)findViewById(R.id.custom_view);final LineChartView.Performance[] performances1=new LineChartView.Performance[8];final LineChartView.Performance[] performances2=new LineChartView.Performance[8];myView.setOnClickListener(new View.OnClickListener(){  @Override  public void onClick(View v){    for(int i=0;i<performances1.length;i++){      switch (random.nextInt(2016)%3){        case 0:          performances1[i]= LineChartView.Performance.WIN;          break;        case 1:          performances1[i]= LineChartView.Performance.DRAW;          break;        case 2:          performances1[i]= LineChartView.Performance.LOSE;          break;        default:          performances1[i]= LineChartView.Performance.LOSE;          break;      }      switch (random.nextInt(2016)%3){        case 0:          performances2[i]= LineChartView.Performance.WIN;          break;        case 1:          performances2[i]= LineChartView.Performance.DRAW;          break;        case 2:          performances2[i]= LineChartView.Performance.LOSE;          break;        default:          performances1[i]= LineChartView.Performance.LOSE;          break;      }    }    myView.setPerformances(performances1,performances2);  }});

Android,自定義控件,折線圖

完整代碼如下:

public class LineChartView extends View {  private Context context;  /*動畫插值器*/  DecelerateInterpolator mDecelerateInterpolator = new DecelerateInterpolator();  /*動畫刷新的次數*/  private int mDuration = 10;  /*當前動畫進度值*/  private int mCurrentTime = 0;  private Performance[] mPerformance_1, mPerformance_2;  /*兩條折線的顏色*/  private int mLineColor1, mLineColor2;  /*繪制表頭文字畫筆*/  private Paint mPaintText = new Paint();  /*繪制表格的畫筆*/  private Paint mPaintLine = new Paint();  /*第一條折線的畫筆*/  private Paint mPaintLine1 =new Paint();  /*第二條折線的畫筆*/  private Paint mPaintLine2 =new Paint();  /*坐標點的小圓點畫筆*/  private Paint mPointPaint = new Paint();  private float mSmallDotRadius = 4;  private TypedValue typedValue;  private int mPaintClolor;  /*Handler刷新界面產生動畫效果*/  private Handler mHandler = new Handler();  private Runnable mAnimation = new Runnable() {    @Override    public void run() {      if (mCurrentTime < mDuration) {        mCurrentTime++;        LineChartView.this.invalidate();      }    }  };   public LineChartView(Context context) {    super(context);    this.context=context;    init();  }   public LineChartView(Context context, AttributeSet attrs) {    super(context, attrs);    this.context=context;    init();  }   public LineChartView(Context context, AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);    this.context=context;    init();  }   public enum Performance {    WIN(0),    DRAW(1),    LOSE(2);    public int type;    Performance(int type) {      this.type = type;    }  }   public void setPerformances(Performance[] performance1, Performance[] performance2) {    if (performance1 == null) {      performance1 = new Performance[0];    }    if (performance2 == null) {      performance2 = new Performance[0];    }    mPerformance_1 = Arrays.copyOf(performance1, performance1.length > 8 ? 8 : performance1.length);    mPerformance_2 = Arrays.copyOf(performance2, performance2.length > 8 ? 8 : performance2.length);    if (isShown()) {      mCurrentTime = 0;      this.invalidate();    }  }   /**   * 設置折線1的顏色   *   * @param mLineColor1   */  public void setLineColor1(int mLineColor1) {    this.mLineColor1 = mLineColor1;  }   /**   * 設置折線2的顏色   *   * @param mLineColor2   */  public void setLineColor2(int mLineColor2) {    this.mLineColor2 = mLineColor2;  }   private void init() {    mLineColor1=Color.BLUE;    mLineColor2 = Color.GREEN;    typedValue=new TypedValue();    context.getTheme().resolveAttribute(R.attr.title_bar,typedValue,true);    mPaintClolor =getResources().getColor(typedValue.resourceId);     final LineChartView.Performance[] performances1=new LineChartView.Performance[8];    final LineChartView.Performance[] performances2=new LineChartView.Performance[8];    final Random random=new Random();    for(int i=0;i<performances1.length;i++){      switch (random.nextInt(2016)%3){        case 0:          performances1[i]= LineChartView.Performance.WIN;          break;        case 1:          performances1[i]= LineChartView.Performance.DRAW;          break;        case 2:          performances1[i]= LineChartView.Performance.LOSE;          break;        default:          performances1[i]= LineChartView.Performance.LOSE;          break;      }      switch (random.nextInt(2016)%3){        case 0:          performances2[i]= LineChartView.Performance.WIN;          break;        case 1:          performances2[i]= LineChartView.Performance.DRAW;          break;        case 2:          performances2[i]= LineChartView.Performance.LOSE;          break;        default:          performances1[i]= LineChartView.Performance.LOSE;          break;      }    }    setPerformances(performances1,performances2);  }    /**   * @param canvas   */  @Override  protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    /*獲取控件總寬高*/    float totalWidth = getWidth();    float totalHeight = getHeight();    /*左邊取總寬度的八分之一繪制表格頭部*/    float textWide = totalWidth / 8;    /*左邊留一點空白*/    float left_offset = 10;    /*折線圖的總寬度等于控件的總寬度減去表頭和留白*/    float chartWide = totalWidth - textWide - left_offset;    /*一共三行,設置每一行的垂直坐標*/    float[] mLineYs = new float[]{totalHeight / 8, totalHeight / 2, totalHeight * 7 / 8};    /*一共八列,設置每一列的水平坐標*/    float[] mLineXs = new float[]{        textWide + left_offset + chartWide * 0 / 8,        textWide + left_offset + chartWide * 1 / 8,        textWide + left_offset + chartWide * 2 / 8,        textWide + left_offset + chartWide * 3 / 8,        textWide + left_offset + chartWide * 4 / 8,        textWide + left_offset + chartWide * 5 / 8,        textWide + left_offset + chartWide * 6 / 8,        textWide + left_offset + chartWide * 7 / 8,    };     /*繪制表頭文字*/    mPaintText.setStyle(Paint.Style.FILL);    mPaintText.setColor(mPaintClolor);    mPaintText.setAlpha(226);    mPaintText.setTextSize(28);    /*從中間開始繪制*/    mPaintText.setTextAlign(Paint.Align.CENTER);    /*測量文字大小,并計算偏移量*/    Paint.FontMetrics fontMetrics = mPaintText.getFontMetrics();    float textBaseLineOffset = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;    canvas.drawText("勝場", textWide / 2, mLineYs[0] + textBaseLineOffset, mPaintText);    canvas.drawText("平局", textWide / 2, mLineYs[1] + textBaseLineOffset, mPaintText);    canvas.drawText("負場", textWide / 2, mLineYs[2] + textBaseLineOffset, mPaintText);     /*繪制表格畫筆設置*/    mPaintLine.setStyle(Paint.Style.STROKE);    mPaintLine.setAntiAlias(true);    mPaintLine.setColor(mPaintClolor);    mPaintLine.setAlpha(80);    mPaintLine.setStrokeWidth(1);    /*開始繪制表格*/    /*繪制三條橫線*/    for(int i=0;i<3;i++){      canvas.drawLine(textWide, mLineYs[i], totalWidth, mLineYs[i], mPaintLine);    }    /*繪制八條豎線*/    for(int i=0;i<8;i++){      canvas.drawLine(mLineXs[i], 0, mLineXs[i], totalHeight, mPaintLine);    }    /*折線圖畫筆設置*/    mPaintLine1.setStyle(Paint.Style.STROKE);    /*設置透明度,取值范圍為0~255,數值越小越透明,0表示完全透明*/    mPaintLine1.setAlpha(0);    mPaintLine1.setAntiAlias(true);    mPaintLine1.setColor(mLineColor1);    mPaintLine1.setStrokeWidth(5);    mPaintLine2.setStyle(Paint.Style.STROKE);    /*設置透明度,取值范圍為0~255,數值越小越透明,0表示完全透明*/    mPaintLine2.setAlpha(0);    mPaintLine2.setAntiAlias(true);    mPaintLine2.setColor(mLineColor2);    mPaintLine2.setStrokeWidth(5);    if (typedValue.resourceId==R.color.white){      /*PorterDuff.Mode.SCREEN 上下層都顯示。*/      mPaintLine2.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));      mPaintLine1.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));    }else {      /*PorterDuff.Mode.DARKEN 上下層都顯示。變暗*/      mPaintLine2.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN));      mPaintLine1.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN));    }    /*畫節點處的小圓點的畫筆設置*/    mPointPaint.setStyle(Paint.Style.STROKE);    mPointPaint.setAntiAlias(true);    mPointPaint.setColor(mPaintClolor);      /*計算當前動畫進度對應的數值*/    float animCurrentValue = mDecelerateInterpolator.getInterpolation(1.0f * mCurrentTime / mDuration);    mPaintLine.setColor(mLineColor1);    /*繪制第一條折線的路徑*/    for (int i = 0; i < mPerformance_1.length - 1; i++) {      /*折線圖的折線的畫筆設置粗一點*/      mPaintLine.setStrokeWidth(5);      /*計算當前節點的坐標值*/      float prePointX =mLineXs[i];      float prePointY =mLineYs[2] - (mLineYs[2] - mLineYs[mPerformance_1[i].type]) * animCurrentValue;      /*計算下一個節點的坐標值*/      float nextPointX=mLineXs[i + 1];      float nextPointY=mLineYs[2] - (mLineYs[2] - mLineYs[mPerformance_1[i + 1].type]) * animCurrentValue;      /*連接當前坐標和下一個坐標,繪制線段*/      canvas.drawLine(prePointX, prePointY, nextPointX, nextPointY, mPaintLine1);      /*當前節點坐標處繪制小圓*/      canvas.drawCircle(prePointX, prePointY, mSmallDotRadius, mPointPaint);    }    /*第一個折線圖的最后一個節點的坐標*/    float lastPointX=mLineXs[mPerformance_1.length - 1];    float lastPointY= mLineYs[2] - (mLineYs[2] - mLineYs[mPerformance_1[mPerformance_1.length - 1].type]) * animCurrentValue;    /*繪制最后一個節點的外圍小圓*/    canvas.drawCircle(lastPointX,lastPointY ,mSmallDotRadius, mPointPaint);     /*繪制第二條折線*/    mPaintLine.setColor(mLineColor2);    for (int i = 0; i < mPerformance_2.length - 1; i++) {      /*折線圖的折線的畫筆設置粗一點*/      mPaintLine.setStrokeWidth(5);      /*計算當前節點的坐標值*/      float prePointX =mLineXs[i];      float prePointY =mLineYs[2] - (mLineYs[2] - mLineYs[mPerformance_2[i].type]) * animCurrentValue;      /*計算下一個節點的坐標值*/      float nextPointX=mLineXs[i + 1];      float nextPointY=mLineYs[2] - (mLineYs[2] - mLineYs[mPerformance_2[i + 1].type]) * animCurrentValue;      /*連接當前坐標和下一個坐標,繪制線段*/      canvas.drawLine(prePointX, prePointY, nextPointX, nextPointY, mPaintLine2);      /*當前節點坐標處繪制小圓*/      canvas.drawCircle(prePointX, prePointY, mSmallDotRadius, mPointPaint);    }     /*第一個折線圖的最后一個節點的坐標*/    lastPointX=mLineXs[mPerformance_2.length - 1];    lastPointY= mLineYs[2] - (mLineYs[2] - mLineYs[mPerformance_2[mPerformance_2.length - 1].type]) * animCurrentValue;    /*繪制最后一個節點的外圍小圓*/    canvas.drawCircle(lastPointX,lastPointY ,mSmallDotRadius, mPointPaint);    mHandler.postDelayed(mAnimation, 20);  }}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 凤凰县| 梁山县| 通道| 静海县| 丘北县| 莫力| 博罗县| 深泽县| 武清区| 宜兰县| 景东| 铜川市| 岐山县| 理塘县| 晋城| 建瓯市| 平湖市| 丁青县| 石城县| 西畴县| 南木林县| 本溪市| 光泽县| 米易县| 温泉县| 苏州市| 营口市| 青河县| 大方县| 胶南市| 景德镇市| 木兰县| 百色市| 金湖县| 清镇市| 双城市| 磐石市| 信阳市| 新密市| 汝城县| 洪湖市|