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

首頁(yè) > 系統(tǒng) > Android > 正文

Android 曲線圖的繪制示例代碼

2019-12-12 01:09:04
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

本文介紹了Android 曲線圖的繪制示例代碼,分享給大家,具體如下:

效果展示

效果展示.gif

使用方式

// 初始化數(shù)據(jù)表格相關(guān)with(mTableView) {  // 配置坐標(biāo)系  setupCoordinator("日", "人", /*這里是橫坐標(biāo)的值*/0f, 5f, 10f, 15f, 20f, 25f, 30f)  // 添加曲線, 確保縱坐標(biāo)的數(shù)值位數(shù)相等  addWave(ContextCompat.getColor(this@MainActivity, R.color.colorYellow), false,      0f, 10f, 30f, 54f, 30f, 100f, 10f)  addWave(ContextCompat.getColor(this@MainActivity, R.color.colorGreen), false,      0f, 30f, 20f, 20f, 46f, 25f, 5f)  addWave(ContextCompat.getColor(this@MainActivity, R.color.colorPink), false,      0f, 30f, 20f, 50f, 46f, 30f, 30f)  addWave(Color.parseColor("#8596dee9"), true,      0f, 15f, 10f, 10f, 40f, 20f, 5f)}

實(shí)現(xiàn)思路

  1. 橫坐標(biāo)是固定的, 縱坐標(biāo)需要跟隨曲線傳入的數(shù)值去動(dòng)態(tài)的調(diào)整
  2. 繪制坐標(biāo)軸: 縱橫交錯(cuò)的網(wǎng)格
  3. 根據(jù)用戶傳入坐標(biāo)數(shù)值去繪制坐標(biāo)軸上的數(shù)值
  4. 給X軸和Y軸添加單位信息
  5. 根據(jù)用戶傳入的具體的數(shù)值繪制曲線(這里不采用Bezier, 不容易精確的控制頂點(diǎn)的位置)
  6. 繪制填充效果
  7. 添加屬性動(dòng)畫

代碼實(shí)現(xiàn)

/** * Created by FrankChoo on 2017/12/29. * Email: frankchoochina@gmail.com * Version: 1.0 * Description: 表格自定義View */public class TableView extends View {  private List<WaveConfigData> mWaves;// 數(shù)值集合  // 坐標(biāo)軸的數(shù)值  private int mCoordinateYCount = 8;  private float[] mCoordinateXValues;// 外界傳入  private float[] mCoordinateYValues;// 動(dòng)態(tài)計(jì)算  // 坐標(biāo)的單位  private String mXUnit;  private String mYUnit;  // 所有曲線中所有數(shù)據(jù)中的最大值  private float mGlobalMaxValue;// 用于確認(rèn)是否需要調(diào)整坐標(biāo)系  private Paint mCoordinatorPaint;  private Paint mTextPaint;  private Paint mWrapPaint;  // 坐標(biāo)軸上描述性文字的空間大小  private int mTopUnitHeight;// 頂部Y軸單位高度  private int mBottomTextHeight;  private int mLeftTextWidth;  // 網(wǎng)格尺寸  private int mGridWidth, mGridHeight;  private float mAnimProgress;  public TableView(Context context) {    this(context, null);  }  public TableView(Context context, @Nullable AttributeSet attrs) {    this(context, attrs, 0);  }  public TableView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);    init();    post(new Runnable() {      @Override      public void run() {        showAnimator();      }    });  }  private void init() {    // 初始化數(shù)據(jù)集合的容器    mWaves = new ArrayList<>();    // 坐標(biāo)系的單位    mBottomTextHeight = dp2px(40);// X軸底部字體的高度    mLeftTextWidth = mBottomTextHeight;// Y軸左邊字體的寬度    mTopUnitHeight = dp2px(30);// 頂部Y軸的單位    // 初始化坐標(biāo)軸Paint    mCoordinatorPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);    mCoordinatorPaint.setColor(Color.LTGRAY);    // 初始化文本Paint    mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);    mTextPaint.setColor(Color.GRAY);    mTextPaint.setTextSize(sp2px(12));    // 初始化曲線Paint    mWrapPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);    mWrapPaint.setPathEffect(new CornerPathEffect(200f));  }  /**   * 配置坐標(biāo)軸信息   *   * @param xUnit       X 軸的單位   * @param yUnit       Y 軸的單位   * @param coordinateXValues X 坐標(biāo)軸上的數(shù)值   */  public void setupCoordinator(String xUnit, String yUnit, float... coordinateXValues) {    mXUnit = xUnit;    mYUnit = yUnit;    mCoordinateXValues = coordinateXValues;  }  /**   * 添加一條曲線, 確保與橫坐標(biāo)的數(shù)值對(duì)應(yīng)   *   * @param color   * @param isCoverRegion   * @param values   */  public void addWave(int color, boolean isCoverRegion, float... values) {    mWaves.add(new WaveConfigData(color, isCoverRegion, values));    // 根據(jù)value的值去計(jì)算縱坐標(biāo)的數(shù)值    float maxValue = 0;    for (float value : values) {      maxValue = Math.max(maxValue, value);    }    if (maxValue < mGlobalMaxValue) return;    mGlobalMaxValue = maxValue;    // 保證網(wǎng)格的數(shù)值都為 5 的倍數(shù)    float gridValue = mGlobalMaxValue / (mCoordinateYCount - 1);    if (gridValue % 5 != 0) {      gridValue += 5 - (gridValue % 5);    }    // 給縱坐標(biāo)的數(shù)值賦值    mCoordinateYValues = new float[mCoordinateYCount];    for (int i = 0; i < mCoordinateYCount; i++) {      mCoordinateYValues[i] = i * gridValue;    }    invalidate();  }  @Override  protected void onDraw(Canvas canvas) {    drawCoordinate(canvas);    drawWrap(canvas);  }  public void showAnimator() {    ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f).setDuration(1000);    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {      @Override      public void onAnimationUpdate(ValueAnimator animation) {        mAnimProgress = (float) animation.getAnimatedValue();        invalidate();      }    });    animator.start();  }  /**   * 繪制坐標(biāo)系   */  private void drawCoordinate(Canvas canvas) {    Point start = new Point();    Point stop = new Point();    // 1. 繪制橫軸線和縱坐標(biāo)單位    int xLineCount = mCoordinateYValues.length;    mGridHeight = (getHeight() - getPaddingTop() - getPaddingBottom() - mBottomTextHeight - mTopUnitHeight) / (xLineCount - 1);    for (int i = 0; i < xLineCount; i++) {      start.x = getPaddingLeft() + mLeftTextWidth;      start.y = getHeight() - getPaddingBottom() - mBottomTextHeight - mGridHeight * i;      stop.x = getRight() - getPaddingRight();      stop.y = start.y;      // 繪制橫軸線      canvas.drawLine(start.x, start.y, stop.x, stop.y, mCoordinatorPaint);      // 繪制縱坐標(biāo)單位      if (i == 0) continue;      String drawText = String.valueOf((int) mCoordinateYValues[i]);      Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();      float offsetY = ((fontMetrics.bottom - fontMetrics.top) / 2 + fontMetrics.bottom) / 2;      float baseLine = start.y + offsetY;      float left = getPaddingLeft() + mLeftTextWidth / 2 - mTextPaint.measureText(drawText) / 2;      canvas.drawText(drawText, left, baseLine, mTextPaint);      // 繪制Y軸單位      if (i == xLineCount - 1) {        drawText = mYUnit;        baseLine = getPaddingTop() + mTopUnitHeight / 2;        canvas.drawText(drawText, left, baseLine, mTextPaint);      }    }    // 2. 繪制縱軸線和橫坐標(biāo)單位    int yLineCount = mCoordinateXValues.length;    mGridWidth = (getWidth() - getPaddingLeft() - getPaddingRight() - mLeftTextWidth) / (yLineCount - 1);    for (int i = 0; i < yLineCount; i++) {      start.x = getPaddingTop() + mLeftTextWidth + mGridWidth * i;      start.y = getPaddingTop() + mTopUnitHeight;      stop.x = start.x;      stop.y = getHeight() - mBottomTextHeight - getPaddingBottom();      // 繪制縱軸線      canvas.drawLine(start.x, start.y, stop.x, stop.y, mCoordinatorPaint);      // 繪制橫坐標(biāo)單位      String drawText = String.valueOf((int) mCoordinateXValues[i]);      Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();      float offsetY = ((fontMetrics.bottom - fontMetrics.top) / 2 + fontMetrics.bottom) / 2;      float baseLine = getHeight() - getPaddingBottom() - mBottomTextHeight / 2 + offsetY;      float left = start.x - mTextPaint.measureText(drawText) / 2;      // 繪制X軸單位      if (i == 0) {        drawText = mXUnit;        left = getPaddingLeft() + mLeftTextWidth / 2 - mTextPaint.measureText(drawText) / 2;      }      canvas.drawText(drawText, left, baseLine, mTextPaint);    }  }  /**   * 繪制曲線   */  private void drawWrap(Canvas canvas) {    canvas.clipRect(new RectF(        mLeftTextWidth,        getPaddingTop() + mTopUnitHeight,        (getRight() - getPaddingRight()) * mAnimProgress,        getHeight() - getPaddingBottom() - mBottomTextHeight)    );    float yHeight = mGridHeight * (mCoordinateYCount - 1);    for (WaveConfigData wave : mWaves) {      Path path = new Path();      path.moveTo(0, getHeight());      float maxY = mCoordinateYValues[mCoordinateYCount - 1];// Y軸坐標(biāo)的最大值      for (int index = 1; index < wave.values.length; index++) {        path.lineTo(            mLeftTextWidth + mGridWidth * index,            getHeight() - getPaddingBottom() - mBottomTextHeight                - yHeight * (wave.values[index] / maxY)        );      }      if (wave.isCoverRegion) {        mWrapPaint.setStyle(Paint.Style.FILL);        path.lineTo(getRight() - getPaddingRight(), getHeight());        path.close();      } else {        mWrapPaint.setStyle(Paint.Style.STROKE);        mWrapPaint.setStrokeWidth(10);      }      mWrapPaint.setColor(wave.color);      canvas.drawPath(path, mWrapPaint);    }  }  private int dp2px(float dp) {    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,        dp, getResources().getDisplayMetrics());  }  private int sp2px(float sp) {    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,        sp, getResources().getDisplayMetrics());  }  public static class WaveConfigData {    int color;    boolean isCoverRegion;    float values[];    public WaveConfigData(int color, boolean isCoverRegion, float[] values) {      this.color = color;      this.isCoverRegion = isCoverRegion;      this.values = values;    }  }}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 巴南区| 宜章县| 富顺县| 西贡区| 湘阴县| 沭阳县| 五原县| 桓台县| 泗洪县| 龙里县| 共和县| 高平市| 丰原市| 绿春县| 基隆市| 万盛区| 济源市| 木里| 丰宁| 罗平县| 五家渠市| 那坡县| 沁阳市| 安岳县| 太保市| 山丹县| 高阳县| 和顺县| 白城市| 花莲市| 鄢陵县| 台中市| 抚顺县| 东阿县| 文山县| 辰溪县| 蕲春县| 靖宇县| 扎兰屯市| 乐山市| 科技|