Android自定义View实现天气预报折线图

2022-09-13 09:11:16

本文实例为大家分享了Android自定义View画天气预报折线图的具体代码,供大家参考,具体内容如下效果图如下:刚开始尝试用第三方画曲线的框架来画效果图,后来发现曲线间的阴影当有负数的度数的时候画不出...

本文实例为大家分享了android自定义View画天气预报折线图的具体代码,供大家参考,具体内容如下

效果图如下:

Android自定义View实现天气预报折线图

刚开始尝试用第三方画曲线的框架来画效果图,后来发现曲线间的阴影当有负数的度数的时候画不出来,而且不需要点击放大、点点可点的效果,用框架显得很臃肿,所以最后用自定义View来画的折线图。自定义画折线图的大致思路:这个图是有多个四边形组成的(4个点连接起来就是一个四边形),两边延伸:添加四个多余的点,将左右的边距设置成负数即可。

代码如下:

public class WeatherChartView extends View {

  /**
  * x轴集合
  */
  private float mXAxis[] ;

  /**
  * 白天y轴集合
  */
  private float mYAxisDay[] ;

  /**
  * 夜间y轴集合
  */
  private float mYAxisNight[] ;

  /**
  * x,y轴集合数
  */
  private int LENGTH ;

  /**
  * 白天温度集合
  */
  private int mTempDay[] ;

  /**
  * 夜间温度集合
  */
  private int mTempNight[] ;

  /**
  * 控件高
  */
  private int mHeight;

  /**
  * 字体大小
  */
  private float mTextSize;

  /**
  * 圓半径
  */
  private float mRadius ;

  /**
  * 圓半径今天
  */
  private float mRadiusToday ;

  /**
  * 文字移动位置距离
  */
  private float mTextSpace ;

  /**
  * 线的大小
  */
  private float mStokeWidth ;

  /**
  * 白天折线颜色
  */
  private int mColorDay = Color.parseColor("#ffffff");

  /**
  * 夜间折线颜色
  */
  private int mColorNight = Color.parseColor("#ffffff");;

  /**
  * 字体颜色
  */
  private int mTextColor = Color.parseColor("#ffffff");;

  /**
  * 屏幕密度
  */
  private float mDensity;

  /**
  * 控件边的空白空间
  */
  private float mSpace;

  @SuppressWarnings("deprecation")
  public WeatherChartView(Context context, AttributeSet attrs) {
    super(context, attrs);
    mDensity = getResources().getDisplayMetrics().density;
    mRadius = 3 * mDensity;
    mRadiusToday = 3 * mDensity;
    //mSpace = 3 * mDensity;
    mTextSpace = 10 * mDensity;
    mStokeWidth = 2 * mDensity;
    mTextSize = BreakRuleTools.dip2px(context, 12);
  }

  public WeatherChartView(Context context) {
    super(context);
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (mHeight == 0) {
      // 设置控件高度,x轴集合
      setHeightandXAxis();
    }
    // 计算y轴集合数值
    computeYAxisValues();
    // 画白天折线图
    drawChart(canvas, mColorDay, mTempDay, mYAxisDay, 0);
    // 画夜间折线图
    drawChart(canvas, mColorNight, mTempNight, mYAxisNight, 1);
  }

  /**
  * 计算y轴集合数值
  */
  private void computeYAxisValues() {
    // 存放白天最低温度
    int minTempDay = mTempDay[0];
    // 存放白天最高温度
    int maxTempDay = mTempDay[0];
    for (int item : mTempDay) {
      if (item < minTempDay) {
        minTempDay = item;
      }
      if (item > maxTempDay) {
        maxTempDay = item;
      }
    }

    // 存放夜间最低温度
    int minTempNight = mTempNight[0];
    // 存放夜间最高温度
    int maxTempNight = mTempNight[0];
    for (int item : mTempNight) {
      if (item < minTempNight) {
        minTempNight = item;
      }
      if (item > maxTempNight) {
        maxTempNight = item;
      }
    }

    // 白天,夜间中的最低温度
    int minTemp = minTempNight < minTemandroidpDay ? minTempNight : minTempDay;
    // 白天,夜间中的最高温度
    int maxTemp = maxTempDay > maxTempNight ? maxTempDay : maxTempNight;

    // 份数(白天,夜间综合温差)
    float parts = maxTemp - minTemp;
    // y轴一端到控件一端的距离
    float length = mSpace + mTextSize + mTextSpace + mRadius;
    // y轴高度
    float yAxisHeight = mHeight - length * 2;

    // 当温度都相同时(被除数不能为0)
    if (parts == 0) {
      for (int i = 0; i < LENGTH; i++) {
        mYAxisDay[i] = yAxisHeight / 2 + length;
        mYAxisNight[i] = yAxisHeight / 2 + length;
      }
    } else {
      float partValue = yAxisHeight / parts;
      for (int i = 0; i < LENGTH; i++) {
        mYAxisDay[i] = mHeight - partValue * (mTempDay[i] - minTemp) - length;
        mYAxisNight[i] = mHeight - partValue * (mTempNight[i] - minTemp) - length;
      }
    }
  }

  /**
  * 画折线图
  *
  * @param canvas 画布
  * @param color 画图颜色
  * @param temp  温度集合
  * @param yAxis y轴集合
  * @param type  折线种类:0,白天;1,夜间
  */
  private void drawChart(Canvas canvas, int color, int temp[], float[] yAxis, int type) {
    color = Color.parseColor("#ffffff");
    // 线画笔
    Paint linePaint = new Paint();
    // 抗锯齿
    linePaint.setAntiAlias(true);
    // 线宽
    linePaint.setStrokeWidth(mStokeWidth);
    linePaint.setColor(color);
    // 空心
    linePaint.setStyle(Paint.Style.STROKE);

    // 点画笔
    Paint pointPaint = new Paint();
    pointPaint.setAntiAlias(true);
    pointPaint.setColor(color);

    // 字体画笔
    Paint textPaint = new Paint();
    textPaint.setAntiAlias(true);
    textPaint.setColor(mTextColor);
    textPaint.setTextSize(mTextSize);
    // 文字居中
    textPaint.setTextAlign(Paint.Align.CENTER);

    int alpha1 = 102;
    int alpha2 = 255;
    for (int i = 0; i < LENGTH; i++) {
      // 画线
      if (i < LENGTH - 1) {
        // 昨天
        if (i == -1) {
          linePaint.setAlpha(alpha1);
          // 设置虚线效果
          linePaint.setPathEffect(new DashPathEffect(new float[]{2 * mDensity, 2 * mDensity}, 0));
          // 路径
          Path path = new Path();
          // 路径起点
          path.moveTo(mXAxis[i], yAxis[i]);
          // 路径连接到
          path.lineTo(mXAxis[i + 1], yAxis[i + 1]);
          canvas.drawpath(path, linePaint);
        } else {
          if(type == 0) {
            linePaint.setAlpha(76);
            linePaint.setPathEffect(null);

            linePaint.setStyle(Paint.Style.FILL);//设置实心
            Path path = new Path();           //Path对象
            path.moveTo(mXAxis[i], mYAxisDay[i]);              //起始点
            path.lineTo(mXAxis[i + 1], mYAxisDay[i + 1]);              //连线到下一点
            path.lineTo(mXAxis[i + 1], 编程mYAxisNight[i + 1]);           //连线到下一点
            path.lineTo(mXAxis[i], mYAxisNight[i]);           //连线到下一点
            path.lineTo(mXAxis[i], mYAxisDay[i]);           //连线到下一点
            canvas.drawPhttp://www.cppcns.comath(path, linePaint);          //绘制任意多边形
          }
          //canvas.drawLine(mXAxis[i], yAxis[i], mXAxis[i + 1], yAxis[i + 1], linePaint);
        }
      }

      // 画点
      if (i != 1) {
        // 昨天
        if (i == 0 || i == LENGTH - 1) {
          /*pointPaint.setAlpha(alpha1);
          canvas.drawCircle(mXAxis[i], yAxis[i], mRadius, pointPaint);*/
        } else {
          pointPaint.setAlpha(alpha2);
          canvas.drawCircle(mXAxis[i], yAxis[i], mRadius, pointPaint);
        }
        // 今天
      } else {
        pointPaint.setAlpha(alpha2);
        canvas.drawCircle(mXAxis[i], yAxis[i], mRadiusToday, pointPaint);
      }

      // 画字
      // 昨天
      if (i == 0 || i == LENGTH - 1) {
        /*textPaint.setAlpha(alpha1);
        drawText(canvas, textPaint, i, temp, yAxis, type);*/
   js   } else {
        textPaint.setAlpha(alpha2);
        drawText(canvas, textPaint, i, temp, yAxis, type);
      }
    }
  }

  /**
  * 绘制文字
  *
  * @param canvas  画布
  * @param textPaint 画笔
  * @param i     索引
  * @param temp   温度集合
  * @param yAxis   y轴集合
  * @param type   折线种类:0,白天;1,夜间
  */
  private void drawText(Canvas canvas, Paint textPaint, int i, int[] temp, float[] yAxis, int type) {
    switch (type) {
      case 0:
        // 显示白天气温
        canvas.drawText(temp[i] + "", mXAxis[i], yAxis[i] - mRadius - mTextSpace, textPaint);
        break;
      case 1:
        // 显示夜间气温
        canvas.drawText(temp[i] + "", mXAxis[i], yAxis[i] + mTextSpace + mTextSize, textPaint);
        break;
    }
  }

  /**
  * 设置高度,x轴集合
  */
  private void setHeightAndXAxis() {
    mHeight = getHeight();
    // 控件宽
    int width = getWidth();
    int i = LENGTH - 2;
    // 每一份宽
    float w = width / (i*2);

    for(int j =0;j<LENGTH;j++){
      if(j == 0){
        mXAxis[j] = 0;
      } else if(j == LENGTH -1){
        mXAxis[j] = width;
      } else{
        mXAxis[j] = w * (2*j -1);
      }
    }
   /* mXAxis[0] = 0;
    mXAxis[1] = w;
    mXAxis[2] = w * 3;
    mXAxis[3] = w * 5;
    mXAxis[4] = w * 7;
    mXAxis[5] = w * 9;
    mXAxis[6] = width;*/
   /* mXAxis[5] = w * 11;
    mXAxis[6] = w * 13;*/
  }

  /**
  * 设置白天温度
  *
  * @param tempDay 温度数组集合
  */
  public void setTempDay(int[] tempDay) {
    mTempDay = tempDay;
    LENGTH = mTempDay.length;

    mXAxis = new float[LENGTH];
    mYAxisDay = new float[LENGTH];
    mYAxisNight = new float[LENGTH];
    /*mTempDay = new int[LENGTH];
    mTempNight = new int[LENGTH];*/
  }

  /**
  * 设置夜间温度
  *
  * @param tempNight 温度数组集合
  */
  public void setTempNight(int[] tempNight) {
    mTempNight = tempNight;
  }

  /**
  * 设置白天曲线的颜色
  */
  public void setColorDay(){}
}

布局代码:

<com.pingan.carowner.weather.view.WeatherChartView
      android:id="@+id/line_char"
      android:layout_width="match_parent"
      android:layout_height="180dp"
      android:layout_below="@id/weather_over_view_item3"
      android:layout_centerInParent="true"/>

代码引用:

// 设置白天温度曲线
mChartView = (WeatherChartView) findViewById(R.id.line_char);
mChartView.setTempDay(highTemp);//highTemp 高温度集合
// 设置夜间温度曲线
mChartView.setTempNight(lowTemp);//lowTemp 低温集合
mChartView.invalidate();

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。