Android自定义View天气预报折线图
xiao芝麻 人气:0效果图如下:
刚开始尝试用第三方画曲线的框架来画效果图,后来发现曲线间的阴影当有负数的度数的时候画不出来,而且不需要点击放大、点点可点的效果,用框架显得很臃肿,所以最后用自定义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();
加载全部内容