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

Oria ·
更新时间:2024-09-20
· 663 次阅读

本文实例为大家分享了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 < minTempDay ? 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.drawPath(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);*/             } 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();



折线图 天气预报 view 天气 Android

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章