編輯:關於Android編程
最近項目裡要做一個簡單的曲線圖來標識數據,開始以為很簡單,android已經有那麼多的開源圖表庫了,什麼achartenginee,hellochart,mpandroidchart等等,下載Demo一找,都強大到有點不適合我這個小小的展示功能了,直是無語了。於是只能自已去畫了,繼承自View去重繪。
下面先看一下效果圖:
思路:根據點的數量將Canvas等分,等分後先繪制圖表的所有橫軸和縱軸。再將數據轉化為點坐標,繪制到屏幕上,最後將相鄰兩點連成線即可。
源碼如下:
import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Path; import android.graphics.Point; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.View; import android.view.WindowManager; /********************************************************** * @文件名稱:LineGraphicView.java * @文件作者:rzq * @創建時間:2015年5月27日 下午3:05:19 * @文件描述:自定義簡單曲線圖 * @修改歷史:2015年5月27日創建初始版本 **********************************************************/ class LineGraphicView extends View { /** * 公共部分 */ private static final int CIRCLE_SIZE = 10; private static enum Linestyle { Line, Curve } private Context mContext; private Paint mPaint; private Resources res; private DisplayMetrics dm; /** * data */ private Linestyle mStyle = Linestyle.Curve; private int canvasHeight; private int canvasWidth; private int bheight = 0; private int blwidh; private boolean isMeasure = true; /** * Y軸最大值 */ private int maxValue; /** * Y軸間距值 */ private int averageValue; private int marginTop = 20; private int marginBottom = 40; /** * 曲線上總點數 */ private Point[] mPoints; /** * 縱坐標值 */ private ArrayListyRawData; /** * 橫坐標值 */ private ArrayList xRawDatas; private ArrayList xList = new ArrayList ();// 記錄每個x的值 private int spacingHeight; public LineGraphicView(Context context) { this(context, null); } public LineGraphicView(Context context, AttributeSet attrs) { super(context, attrs); this.mContext = context; initView(); } private void initView() { this.res = mContext.getResources(); this.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); dm = new DisplayMetrics(); WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); wm.getDefaultDisplay().getMetrics(dm); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { if (isMeasure) { this.canvasHeight = getHeight(); this.canvasWidth = getWidth(); if (bheight == 0) bheight = (int) (canvasHeight - marginBottom); blwidh = dip2px(30); isMeasure = false; } } @Override protected void onDraw(Canvas canvas) { mPaint.setColor(res.getColor(R.color.color_f2f2f2)); drawAllXLine(canvas); // 畫直線(縱向) drawAllYLine(canvas); // 點的操作設置 mPoints = getPoints(); mPaint.setColor(res.getColor(R.color.color_ff4631)); mPaint.setStrokeWidth(dip2px(2.5f)); mPaint.setStyle(Style.STROKE); if (mStyle == Linestyle.Curve) { drawScrollLine(canvas); } else { drawLine(canvas); } mPaint.setStyle(Style.FILL); for (int i = 0; i < mPoints.length; i++) { canvas.drawCircle(mPoints[i].x, mPoints[i].y, CIRCLE_SIZE / 2, mPaint); } } /** * 畫所有橫向表格,包括X軸 */ private void drawAllXLine(Canvas canvas) { for (int i = 0; i < spacingHeight + 1; i++) { canvas.drawLine(blwidh, bheight - (bheight / spacingHeight) * i + marginTop, (canvasWidth - blwidh), bheight - (bheight / spacingHeight) * i + marginTop, mPaint);// Y坐標 drawText(String.valueOf(averageValue * i), blwidh / 2, bheight - (bheight / spacingHeight) * i + marginTop, canvas); } } /** * 畫所有縱向表格,包括Y軸 */ private void drawAllYLine(Canvas canvas) { for (int i = 0; i < yRawData.size(); i++) { xList.add(blwidh + (canvasWidth - blwidh) / yRawData.size() * i); canvas.drawLine(blwidh + (canvasWidth - blwidh) / yRawData.size() * i, marginTop, blwidh + (canvasWidth - blwidh) / yRawData.size() * i, bheight + marginTop, mPaint); drawText(xRawDatas.get(i), blwidh + (canvasWidth - blwidh) / yRawData.size() * i, bheight + dip2px(26), canvas);// X坐標 } } private void drawScrollLine(Canvas canvas) { Point startp = new Point(); Point endp = new Point(); for (int i = 0; i < mPoints.length - 1; i++) { startp = mPoints[i]; endp = mPoints[i + 1]; int wt = (startp.x + endp.x) / 2; Point p3 = new Point(); Point p4 = new Point(); p3.y = startp.y; p3.x = wt; p4.y = endp.y; p4.x = wt; Path path = new Path(); path.moveTo(startp.x, startp.y); path.cubicTo(p3.x, p3.y, p4.x, p4.y, endp.x, endp.y); canvas.drawPath(path, mPaint); } } private void drawLine(Canvas canvas) { Point startp = new Point(); Point endp = new Point(); for (int i = 0; i < mPoints.length - 1; i++) { startp = mPoints[i]; endp = mPoints[i + 1]; canvas.drawLine(startp.x, startp.y, endp.x, endp.y, mPaint); } } private void drawText(String text, int x, int y, Canvas canvas) { Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); p.setTextSize(dip2px(12)); p.setColor(res.getColor(R.color.color_999999)); p.setTextAlign(Paint.Align.LEFT); canvas.drawText(text, x, y, p); } private Point[] getPoints() { Point[] points = new Point[yRawData.size()]; for (int i = 0; i < yRawData.size(); i++) { int ph = bheight - (int) (bheight * (yRawData.get(i) / maxValue)); points[i] = new Point(xList.get(i), ph + marginTop); } return points; } public void setData(ArrayList yRawData, ArrayList xRawData, int maxValue, int averageValue) { this.maxValue = maxValue; this.averageValue = averageValue; this.mPoints = new Point[yRawData.size()]; this.xRawDatas = xRawData; this.yRawData = yRawData; this.spacingHeight = maxValue / averageValue; } public void setTotalvalue(int maxValue) { this.maxValue = maxValue; } public void setPjvalue(int averageValue) { this.averageValue = averageValue; } public void setMargint(int marginTop) { this.marginTop = marginTop; } public void setMarginb(int marginBottom) { this.marginBottom = marginBottom; } public void setMstyle(Linestyle mStyle) { this.mStyle = mStyle; } public void setBheight(int bheight) { this.bheight = bheight; } /** * 根據手機的分辨率從 dp 的單位 轉成為 px(像素) */ private int dip2px(float dpValue) { return (int) (dpValue * dm.density + 0.5f); } }
package com.example; import java.util.ArrayList; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { LineGraphicView tu; ArrayListyList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tu = (LineGraphicView) findViewById(R.id.line_graphic); yList = new ArrayList (); yList.add((double) 2.103); yList.add(4.05); yList.add(6.60); yList.add(3.08); yList.add(4.32); yList.add(2.0); yList.add(5.0); ArrayList xRawDatas = new ArrayList (); xRawDatas.add(05-19); xRawDatas.add(05-20); xRawDatas.add(05-21); xRawDatas.add(05-22); xRawDatas.add(05-23); xRawDatas.add(05-24); xRawDatas.add(05-25); xRawDatas.add(05-26); tu.setData(yList, xRawDatas, 8, 2); } }
指紋識別已經成為智能手機新一代必備功能,指紋識別讓你的手指有了更多用途。除了免輸密碼解鎖,它還有更多便捷功能,例如:指紋支付購物,查看私密文件等
寫在前面:在暴雨天能去上課的都是好學生,能去上班的都是游泳運動員~ 問大家一個問題:Android中一個應用程序的真正入口是什麼?無論你知道不知道,別著急回答,
下面結合我對這一部分的學習,自己做一個小節。Android5.0之後組件必須使用顯示intent來啟動,如果為隱示的,則設置Intent的包名。intent.setPac
前言作為android六大布局中最為簡單的布局之一,該布局直接在屏幕上開辟出了一塊空白區域,當我們往裡面添加組件的時候,所有的組件都會放置於這塊區域的左上角;幀布局的大小