Android自定義View實現天氣預報折線圖
本文實例為大家分享了Android自定義View畫天氣預報折線圖的具體代碼,供大家參考,具體內容如下
效果圖如下:
剛開始嘗試用第三方畫曲線的框架來畫效果圖,后來發(fā)現曲線間的陰影當有負數的度數的時候畫不出來,而且不需要點擊放大、點點可點的效果,用框架顯得很臃腫,所以最后用自定義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();
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Android實現創(chuàng)建或升級數據庫時執(zhí)行語句
這篇文章主要介紹了Android實現創(chuàng)建或升級數據庫時執(zhí)行語句,是比較實用的功能,需要的朋友可以參考下2014-08-08Android通過HttpURLConnection和HttpClient接口實現網絡編程
這篇文章主要介紹了Android通過HttpURLConnection和HttpClient接口實現網絡編程的相關資料,需要的朋友可以參考下2015-02-02Convert WebP to PNG using java
本文主要介紹Convert WebP to PNG using java,這里對 WebP 做了詳細說明,并講解Linux 環(huán)境下WebP 轉png格式的示例,有興趣的小伙伴可以參考下2016-08-08