亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > 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開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
色偷偷偷综合中文字幕;dd| 亚洲综合中文字幕68页| 国产偷亚洲偷欧美偷精品| 草民午夜欧美限制a级福利片| 日韩大片在线观看视频| 日韩电影免费观看在线观看| 日韩精品视频免费在线观看| 国产亚洲精品久久久| 国产亚洲精品一区二555| 国产成人亚洲综合91精品| 日韩中文字幕网站| 久热国产精品视频| 96pao国产成视频永久免费| 亚洲成人精品视频| 久久人人爽人人爽人人片av高请| 亚洲欧美变态国产另类| 欧美国产日韩中文字幕在线| 久久亚洲欧美日韩精品专区| 欧美裸体xxxx| 欧美黑人一级爽快片淫片高清| 亚洲免费人成在线视频观看| 欧美精品日韩www.p站| 久久九九有精品国产23| 国产欧美一区二区三区在线| 欧美电影免费在线观看| 亚洲国产精品热久久| 日韩暖暖在线视频| 亚洲成人网av| 欧美精品少妇videofree| 亚洲欧美日韩一区二区三区在线| 久久99热精品这里久久精品| 国模视频一区二区三区| 国产一区二区丝袜高跟鞋图片| 欧美日韩国产一区二区三区| 国产一区在线播放| 成人av在线网址| 国产欧美亚洲精品| 国产精品自拍视频| 亚洲天堂网站在线观看视频| 国产成人一区二区在线| 久久国产精品久久久久久久久久| 欧美成人精品一区二区三区| 亚洲自拍偷拍色图| 欧洲美女免费图片一区| 亚洲影院色无极综合| 国产va免费精品高清在线观看| 日韩精品免费在线观看| 亚洲精品v天堂中文字幕| 日韩视频在线观看免费| 视频一区视频二区国产精品| 日韩欧美在线第一页| 亚洲精品久久久久久久久久久| 国产精品久久久久免费a∨| 538国产精品一区二区免费视频| 日韩国产高清污视频在线观看| 日韩av中文字幕在线免费观看| 国产精品视频地址| 国产va免费精品高清在线| 日产日韩在线亚洲欧美| 欧美在线视频一区二区| 国产精品高潮粉嫩av| 亚洲日韩第一页| 热门国产精品亚洲第一区在线| 国产精品久久久久久久久| 欧美激情视频一区二区三区不卡| 成人免费在线视频网址| 在线观看亚洲视频| 免费97视频在线精品国自产拍| 久久色免费在线视频| 最近中文字幕mv在线一区二区三区四区| 亚洲性日韩精品一区二区| 亚洲精品永久免费| 亚洲深夜福利网站| 欧美亚洲视频一区二区| 日韩欧美亚洲国产一区| 午夜剧场成人观在线视频免费观看| 亚洲第一级黄色片| 久久伊人精品视频| 久久久久久欧美| 久久伊人91精品综合网站| 日韩美女在线看| 精品二区三区线观看| 亚洲国产小视频在线观看| 欧美日韩综合视频网址| 日韩成人在线播放| 欧美性jizz18性欧美| 欧美性xxxx18| 亚洲无亚洲人成网站77777| 欧美与欧洲交xxxx免费观看| 91久久在线观看| 久久视频国产精品免费视频在线| 国产欧美一区二区白浆黑人| 国产精品精品久久久久久| 国产99久久精品一区二区永久免费| 人人澡人人澡人人看欧美| 亚洲欧美另类人妖| 亚洲a在线播放| 另类专区欧美制服同性| 97在线观看免费| 亚洲午夜小视频| 丝袜亚洲另类欧美重口| 亚洲色图国产精品| 亚洲美女视频网| 色偷偷偷亚洲综合网另类| 一个人www欧美| 91色精品视频在线| 97在线免费观看视频| 国产精品久久久久久久久久尿| 亚洲精品久久久一区二区三区| 久久99视频免费| 欧美成人午夜免费视在线看片| 欧美性猛交xxxx| 中文日韩在线观看| 91精品国产高清久久久久久91| 久久精品国产成人精品| 亚洲视频视频在线| 成人在线精品视频| 夜夜狂射影院欧美极品| 高清欧美性猛交| 欧美老少做受xxxx高潮| 欧美多人乱p欧美4p久久| 91产国在线观看动作片喷水| 国产精品夫妻激情| 日韩av快播网址| 91日本视频在线| 精品久久久国产| 九九热最新视频//这里只有精品| 成人黄色生活片| 欧美高清视频在线观看| 久久99亚洲精品| 国产成人精彩在线视频九色| 97国产一区二区精品久久呦| 91精品国产91久久久久福利| 在线精品高清中文字幕| 日本一区二三区好的精华液| 成人做爰www免费看视频网站| 久热在线中文字幕色999舞| 亚洲国产另类 国产精品国产免费| 欧美电影在线观看网站| 欧美在线视频一区二区| 夜夜躁日日躁狠狠久久88av| 91干在线观看| 九九热最新视频//这里只有精品| 97成人超碰免| 欧美激情精品久久久| 欧美放荡办公室videos4k| 久久人人爽人人爽人人片av高请| 一本久久综合亚洲鲁鲁| 国产欧美日韩精品在线观看| 中文字幕久精品免费视频| 亚洲精品国产拍免费91在线| 97久久国产精品| 中文日韩电影网站| 国产精品视频午夜| 成人午夜在线视频一区| 国产精品一区二区三区免费视频| 亚洲一区二区免费| 久久亚洲电影天堂| 日韩精品在线免费观看视频| 日韩精品小视频| 国产99视频在线观看| 久久精品国产欧美激情| 亚洲成人性视频| 欧美理论电影在线观看|