Android自定义控件实现折线图

作者:袖梨 2022-06-25

本文实例实现一个如下图所示的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));

测试代码及效果;

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

完整代码如下:

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

相关文章

精彩推荐