最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android自定義控件實(shí)現(xiàn)折線圖

 更新時(shí)間:2018年12月25日 09:29:12   作者:王世暉  
這篇文章主要為大家詳細(xì)介紹了Android自定義控件實(shí)現(xiàn)折線圖,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例實(shí)現(xiàn)一個(gè)如下圖所示的Android折線圖,供大家參考,具體內(nèi)容如下

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

確定表格的行列數(shù),首先繪制一個(gè)三行八列的網(wǎng)格,設(shè)置好行列的坐標(biāo)后開始繪制

/*繪制三條橫線*/
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);
}

網(wǎng)格繪制完成后,開始繪制折線圖

根據(jù)輸入的節(jié)點(diǎn)數(shù)據(jù),分別繪制兩條折線

通過canvas的drawLine方法依次連接兩點(diǎn)即可

在每個(gè)數(shù)據(jù)節(jié)點(diǎn)處繪制一個(gè)小圓,突出顯示

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

兩條折線重合的地方,需要特殊考慮,比如希望兩條折線重合的地方折線變?yōu)榘咨?/p>

設(shè)置下兩條折線的畫筆即可

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

測(cè)試代碼及效果;

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);
  }
});

完整代碼如下:

public class LineChartView extends View {
  private Context context;
  /*動(dòng)畫插值器*/
  DecelerateInterpolator mDecelerateInterpolator = new DecelerateInterpolator();
  /*動(dòng)畫刷新的次數(shù)*/
  private int mDuration = 10;
  /*當(dāng)前動(dòng)畫進(jìn)度值*/
  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();
  /*坐標(biāo)點(diǎn)的小圓點(diǎn)畫筆*/
  private Paint mPointPaint = new Paint();
  private float mSmallDotRadius = 4;
  private TypedValue typedValue;
  private int mPaintClolor;
  /*Handler刷新界面產(chǎn)生動(dòng)畫效果*/
  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();
    }
  }
 
  /**
   * 設(shè)置折線1的顏色
   *
   * @param mLineColor1
   */
  public void setLineColor1(int mLineColor1) {
    this.mLineColor1 = mLineColor1;
  }
 
  /**
   * 設(shè)置折線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;
    /*左邊留一點(diǎn)空白*/
    float left_offset = 10;
    /*折線圖的總寬度等于控件的總寬度減去表頭和留白*/
    float chartWide = totalWidth - textWide - left_offset;
    /*一共三行,設(shè)置每一行的垂直坐標(biāo)*/
    float[] mLineYs = new float[]{totalHeight / 8, totalHeight / 2, totalHeight * 7 / 8};
    /*一共八列,設(shè)置每一列的水平坐標(biāo)*/
    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);
    /*測(cè)量文字大小,并計(jì)算偏移量*/
    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("負(fù)場", textWide / 2, mLineYs[2] + textBaseLineOffset, mPaintText);
 
    /*繪制表格畫筆設(shè)置*/
    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);
    }
    /*折線圖畫筆設(shè)置*/
    mPaintLine1.setStyle(Paint.Style.STROKE);
    /*設(shè)置透明度,取值范圍為0~255,數(shù)值越小越透明,0表示完全透明*/
    mPaintLine1.setAlpha(0);
    mPaintLine1.setAntiAlias(true);
    mPaintLine1.setColor(mLineColor1);
    mPaintLine1.setStrokeWidth(5);
    mPaintLine2.setStyle(Paint.Style.STROKE);
    /*設(shè)置透明度,取值范圍為0~255,數(shù)值越小越透明,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));
    }
    /*畫節(jié)點(diǎn)處的小圓點(diǎn)的畫筆設(shè)置*/
    mPointPaint.setStyle(Paint.Style.STROKE);
    mPointPaint.setAntiAlias(true);
    mPointPaint.setColor(mPaintClolor);
 
 
    /*計(jì)算當(dāng)前動(dòng)畫進(jìn)度對(duì)應(yīng)的數(shù)值*/
    float animCurrentValue = mDecelerateInterpolator.getInterpolation(1.0f * mCurrentTime / mDuration);
    mPaintLine.setColor(mLineColor1);
    /*繪制第一條折線的路徑*/
    for (int i = 0; i < mPerformance_1.length - 1; i++) {
      /*折線圖的折線的畫筆設(shè)置粗一點(diǎn)*/
      mPaintLine.setStrokeWidth(5);
      /*計(jì)算當(dāng)前節(jié)點(diǎn)的坐標(biāo)值*/
      float prePointX =mLineXs[i];
      float prePointY =mLineYs[2] - (mLineYs[2] - mLineYs[mPerformance_1[i].type]) * animCurrentValue;
      /*計(jì)算下一個(gè)節(jié)點(diǎn)的坐標(biāo)值*/
      float nextPointX=mLineXs[i + 1];
      float nextPointY=mLineYs[2] - (mLineYs[2] - mLineYs[mPerformance_1[i + 1].type]) * animCurrentValue;
      /*連接當(dāng)前坐標(biāo)和下一個(gè)坐標(biāo),繪制線段*/
      canvas.drawLine(prePointX, prePointY, nextPointX, nextPointY, mPaintLine1);
      /*當(dāng)前節(jié)點(diǎn)坐標(biāo)處繪制小圓*/
      canvas.drawCircle(prePointX, prePointY, mSmallDotRadius, mPointPaint);
    }
    /*第一個(gè)折線圖的最后一個(gè)節(jié)點(diǎn)的坐標(biāo)*/
    float lastPointX=mLineXs[mPerformance_1.length - 1];
    float lastPointY= mLineYs[2] - (mLineYs[2] - mLineYs[mPerformance_1[mPerformance_1.length - 1].type]) * animCurrentValue;
    /*繪制最后一個(gè)節(jié)點(diǎn)的外圍小圓*/
    canvas.drawCircle(lastPointX,lastPointY ,mSmallDotRadius, mPointPaint);
 
    /*繪制第二條折線*/
    mPaintLine.setColor(mLineColor2);
    for (int i = 0; i < mPerformance_2.length - 1; i++) {
      /*折線圖的折線的畫筆設(shè)置粗一點(diǎn)*/
      mPaintLine.setStrokeWidth(5);
      /*計(jì)算當(dāng)前節(jié)點(diǎn)的坐標(biāo)值*/
      float prePointX =mLineXs[i];
      float prePointY =mLineYs[2] - (mLineYs[2] - mLineYs[mPerformance_2[i].type]) * animCurrentValue;
      /*計(jì)算下一個(gè)節(jié)點(diǎn)的坐標(biāo)值*/
      float nextPointX=mLineXs[i + 1];
      float nextPointY=mLineYs[2] - (mLineYs[2] - mLineYs[mPerformance_2[i + 1].type]) * animCurrentValue;
      /*連接當(dāng)前坐標(biāo)和下一個(gè)坐標(biāo),繪制線段*/
      canvas.drawLine(prePointX, prePointY, nextPointX, nextPointY, mPaintLine2);
      /*當(dāng)前節(jié)點(diǎn)坐標(biāo)處繪制小圓*/
      canvas.drawCircle(prePointX, prePointY, mSmallDotRadius, mPointPaint);
    }
     /*第一個(gè)折線圖的最后一個(gè)節(jié)點(diǎn)的坐標(biāo)*/
    lastPointX=mLineXs[mPerformance_2.length - 1];
    lastPointY= mLineYs[2] - (mLineYs[2] - mLineYs[mPerformance_2[mPerformance_2.length - 1].type]) * animCurrentValue;
    /*繪制最后一個(gè)節(jié)點(diǎn)的外圍小圓*/
    canvas.drawCircle(lastPointX,lastPointY ,mSmallDotRadius, mPointPaint);
    mHandler.postDelayed(mAnimation, 20);
  }
}

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android Fragment(動(dòng)態(tài),靜態(tài))碎片詳解及總結(jié)

    Android Fragment(動(dòng)態(tài),靜態(tài))碎片詳解及總結(jié)

    這篇文章主要介紹了Android Fragment詳解及總結(jié)的相關(guān)資料,這里對(duì)Android Fragment 動(dòng)態(tài),靜態(tài)碎片進(jìn)行了整理總結(jié),需要的朋友可以參考下
    2016-12-12
  • 詳解Android Studio實(shí)現(xiàn)用戶登陸界面demo(xml實(shí)現(xiàn))

    詳解Android Studio實(shí)現(xiàn)用戶登陸界面demo(xml實(shí)現(xiàn))

    這篇文章主要介紹了詳解Android Studio實(shí)現(xiàn)用戶登陸界面demo,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Android開發(fā)實(shí)現(xiàn)加載網(wǎng)絡(luò)圖片并下載至本地SdCard的方法

    Android開發(fā)實(shí)現(xiàn)加載網(wǎng)絡(luò)圖片并下載至本地SdCard的方法

    這篇文章主要介紹了Android開發(fā)實(shí)現(xiàn)加載網(wǎng)絡(luò)圖片并下載至本地SdCard的方法,涉及Android圖片文件的讀取、保存及權(quán)限相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01
  • Android如何自定義升級(jí)對(duì)話框示例詳解

    Android如何自定義升級(jí)對(duì)話框示例詳解

    對(duì)話框是我們?cè)谄綍r(shí)經(jīng)常會(huì)遇到的一個(gè)功能,但自帶的對(duì)話框不夠美觀,大家一般都會(huì)自定義,下面這篇文章主要給大家介紹了關(guān)于Android如何自定義升級(jí)對(duì)話框的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-08-08
  • Android實(shí)現(xiàn)快速滾動(dòng)FastScrollView效果

    Android實(shí)現(xiàn)快速滾動(dòng)FastScrollView效果

    這篇文章主要介紹了Android實(shí)現(xiàn)快速滾動(dòng)FastScrollView效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • Android編程動(dòng)態(tài)按鈕實(shí)現(xiàn)方法

    Android編程動(dòng)態(tài)按鈕實(shí)現(xiàn)方法

    這篇文章主要介紹了Android編程動(dòng)態(tài)按鈕實(shí)現(xiàn)方法,分享了onTouch方法及xml調(diào)用兩種實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-10-10
  • android實(shí)現(xiàn)一鍵鎖屏和一鍵卸載的方法實(shí)例

    android實(shí)現(xiàn)一鍵鎖屏和一鍵卸載的方法實(shí)例

    這篇文章主要給大家介紹了關(guān)于android如何實(shí)現(xiàn)一鍵鎖屏和一鍵卸載的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-05-05
  • Android自定義View繪制流程詳解

    Android自定義View繪制流程詳解

    這篇文章主要為大家介紹了Android自定義View繪制流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • Android實(shí)現(xiàn)上下菜單雙向滑動(dòng)效果

    Android實(shí)現(xiàn)上下菜單雙向滑動(dòng)效果

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)上下菜單雙向滑動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • Android程序開發(fā)仿新版QQ鎖屏下彈窗功能

    Android程序開發(fā)仿新版QQ鎖屏下彈窗功能

    最近做了一個(gè)項(xiàng)目,其中涉及到這樣一個(gè)功能:新版的qq能在鎖屏下彈窗顯示qq消息,下面小編抽時(shí)間把實(shí)現(xiàn)代碼分享給大家感興趣的朋友參考下吧
    2016-09-09

最新評(píng)論

稷山县| 桂平市| 伊宁市| 宝应县| 板桥市| 同德县| 个旧市| 海晏县| 东台市| 汝州市| 潮州市| 尼木县| 英吉沙县| 安丘市| 吉安县| 南京市| 徐水县| 福州市| 科技| 大同县| 托克托县| 西乌珠穆沁旗| 聊城市| 安远县| 高安市| 紫阳县| 越西县| 庆元县| 珠海市| 英超| 合阳县| 志丹县| 瑞安市| 新宁县| 淮安市| 西华县| 武威市| 金乡县| 报价| 辽宁省| 三河市|