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

【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); }@Overrideprotected 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 = https://www.it610.com/article/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 yAxisy轴集合* @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 yAxisy轴集合* @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
布局代码:

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

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

    推荐阅读