所謂動(dòng)態(tài)折線圖,就是折線圖能隨著手指的滑動(dòng)進(jìn)行動(dòng)態(tài)繪制,這里很定會(huì)產(chǎn)生動(dòng)畫效果。基于這個(gè)效果,這里使用SurfaceView進(jìn)行制圖。

創(chuàng)新互聯(lián)專注于企業(yè)網(wǎng)絡(luò)營(yíng)銷推廣、網(wǎng)站重做改版、渭源網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5場(chǎng)景定制、商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為渭源等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
實(shí)現(xiàn)步奏如下:
(1): 這里新建一個(gè)繪圖ChartView,繼承SurfaceView并實(shí)現(xiàn)SurfaceHolder.Callback , Runnable接口,主要繪圖工作在子線程中完成。
(2):現(xiàn)實(shí) SurfaceHolder.Callback接口的三個(gè)方法,并在 surfaceCreated中開啟子線程進(jìn)行繪圖。
(3):重寫onTouchEvent方法,在Move事件中,根據(jù)手指的滑動(dòng)距離計(jì)算偏移量,具體實(shí)現(xiàn)請(qǐng)看代碼。
(4): 這里的折線圖的坐標(biāo)值是隨意添加的,可以在實(shí)際項(xiàng)目中根據(jù)需求自己添加。
(5):此例中有大量從集合中添加和刪除元素,建議使用LinkedList來(lái)進(jìn)行保存數(shù)據(jù)。
自定義ChartView:
public class ChartView extends SurfaceView implements SurfaceHolder.Callback , Runnable
{
private Context mContext;
private Paint mPaint;
private Resources res;
private DisplayMetrics dm;
private int canvasHeight;
private int canvasWidth;
private int bHeight = 0;
private int bWidth;
private boolean isMeasure = true;
private boolean canScrollRight = true;
private boolean canScrollLeft = true;
//y軸最大值
private int maxValue;
//y軸間隔值
private int averageValue;
private int marginTop = 20;
private int marginBottom = 80;
//曲線上的總點(diǎn)數(shù)
private Point[] mPoints;
//縱坐標(biāo)值
private LinkedList<Double> yRawData;
//橫坐標(biāo)值
private LinkedList<String> xRawData;
//根據(jù)間隔計(jì)算出的每個(gè)X的值
private LinkedList<Integer> xList = new LinkedList<>();
private LinkedList<String> xPreData = new LinkedList<>();
private LinkedList<Double> yPreData = new LinkedList<>();
private LinkedList<String> xLastData = new LinkedList<>();
private LinkedList<Double> yLastData = new LinkedList<>();
private int spacingHeight;
private SurfaceHolder holder;
private boolean isRunning = true;
private int lastX;
private int offSet;
private Rect mRect;
private int xAverageValue = 0;
public ChartView(Context context)
{
this(context , null);
}
public ChartView(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);
xPreData.add("05-18");
xPreData.add("05-17");
xPreData.add("05-16");
xPreData.add("05-15");
xPreData.add("05-14");
xPreData.add("05-13");
yPreData.add(4.53);
yPreData.add(3.45);
yPreData.add(6.78);
yPreData.add(5.21);
yPreData.add(2.34);
yPreData.add(6.32);
xLastData.add("05-26");
xLastData.add("05-27");
xLastData.add("05-28");
xLastData.add("05-29");
xLastData.add("05-30");
xLastData.add("05-31");
yLastData.add(2.35);
yLastData.add(5.43);
yLastData.add(6.23);
yLastData.add(7.33);
yLastData.add(3.45);
yLastData.add(2.45);
holder = this.getHolder();
holder.addCallback(this);
}
@Override
protected void onSizeChanged(int w , int h , int oldW , int oldH)
{
if (isMeasure)
{
this.canvasHeight = getHeight();
this.canvasWidth = getWidth();
if (bHeight == 0)
{
bHeight = canvasHeight - marginBottom;
}
bWidth = dip2px(30);
xAverageValue = (canvasWidth - bWidth) / 7;
isMeasure = false;
}
}
@Override
public void run()
{
while (isRunning)
{
drawView();
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
private void drawView()
{
Canvas canvas = holder.lockCanvas();
canvas.drawColor(Color.WHITE);
mPaint.setColor(res.getColor(R.color.color_f2f2f2));
drawAllXLine(canvas);
mRect = new Rect(bWidth - 3, marginTop - 5 ,
bWidth + (canvasWidth - bWidth) / yRawData.size() * (yRawData.size() - 1) + 3, bHeight + marginTop + marginBottom);
//鎖定畫圖區(qū)域
canvas.clipRect(mRect);
drawAllYLine(canvas);
mPoints = getPoints();
mPaint.setColor(res.getColor(R.color.color_ff4631));
mPaint.setStrokeWidth(dip2px(2.5f));
mPaint.setStyle(Paint.Style.STROKE);
drawLine(canvas);
mPaint.setStyle(Paint.Style.FILL);
for (int i = 0 ; i < mPoints.length ; i++)
{
canvas.drawCircle(mPoints[i].x , mPoints[i].y , 5 , mPaint);
}
holder.unlockCanvasAndPost(canvas);
}
//繪制折線圖
private void drawLine(Canvas canvas)
{
Point startP = null;
Point endP = null;
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 drawAllYLine(Canvas canvas)
{
for (int i = 0 ; i < yRawData.size() ; i++)
{
if (i == 0)
{
canvas.drawLine(bWidth, marginTop , bWidth, bHeight + marginTop , mPaint);
}
if (i == yRawData.size() - 1)
{
canvas.drawLine(bWidth + xAverageValue * i, marginTop , bWidth + xAverageValue * i , bHeight + marginTop , mPaint);
}
xList.add(bWidth + xAverageValue * i);
canvas.drawLine(bWidth + xAverageValue * i + offSet, marginTop , bWidth + xAverageValue * i + offSet , bHeight + marginTop , mPaint);
drawText(xRawData.get(i) , bWidth + xAverageValue * i - 30 + offSet, bHeight + dip2px(26) , canvas);
}
}
//繪制所有的橫向分割線
private void drawAllXLine(Canvas canvas)
{
for (int i = 0 ; i < spacingHeight + 1 ; i++)
{
canvas.drawLine(bWidth , bHeight - (bHeight / spacingHeight) * i + marginTop ,
bWidth + xAverageValue * (yRawData.size() - 1) , bHeight - (bHeight / spacingHeight) * i + marginTop , mPaint);
drawText(String.valueOf(averageValue * i) , bWidth / 2 , bHeight - (bHeight / spacingHeight) * i + marginTop, canvas);
}
}
//繪制坐標(biāo)值
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);
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder)
{
new Thread(this).start();
Log.d("OOK" , "Created");
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2)
{
Log.d("OOK" , "Changed");
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder)
{
isRunning = false;
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
int action = event.getAction();
int rawX = (int) event.getX();
switch (action)
{
case MotionEvent.ACTION_DOWN:
lastX = rawX;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = rawX - lastX;
if (xPreData.size() == 0 && offSet > 0)
{
offSet = 0;
canScrollRight = false;
}
if (xLastData.size() == 0 && offSet < 0)
{
offSet = 0;
canScrollLeft = false;
}
offSet = offSet + offsetX;
if (offSet > xAverageValue && canScrollRight)
{
offSet = offSet % xAverageValue;
xRawData.addFirst(xPreData.pollFirst());
yRawData.addFirst(yPreData.pollFirst());
xLastData.addFirst(xRawData.removeLast());
yLastData.addFirst(yRawData.removeLast());
canScrollLeft = true;
}
if (offSet < -xAverageValue && canScrollLeft)
{
offSet = offSet % xAverageValue;
xRawData.addLast(xLastData.pollFirst());
yRawData.addLast(yLastData.pollFirst());
xPreData.addFirst(xRawData.removeFirst());
yPreData.addFirst(yRawData.removeFirst());
canScrollRight = true;
}
lastX = rawX;
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
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) + offSet , ph + marginTop);
}
return points;
}
public void setData(LinkedList<Double> yRawData , LinkedList<String> xRawData , int maxValue , int averageValue)
{
this.maxValue = maxValue;
this.averageValue = averageValue;
this.mPoints = new Point[yRawData.size()];
this.yRawData = yRawData;
this.xRawData = xRawData;
this.spacingHeight = maxValue / averageValue;
}
private int dip2px(float dpValue)
{
return (int) (dpValue * dm.density + 0.5f);
}
}MainActivity代碼:
public class MainActivity extends Activity
{
LinkedList<Double> yList;
LinkedList<String> xRawData;
ChartView chartView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
chartView = (ChartView) findViewById(R.id.chartView);
yList = new LinkedList<>();
yList.add(2.203);
yList.add(4.05);
yList.add(6.60);
yList.add(3.08);
yList.add(4.32);
yList.add(2.0);
yList.add(5.0);
xRawData = new LinkedList<>();
xRawData.add("05-19");
xRawData.add("05-20");
xRawData.add("05-21");
xRawData.add("05-22");
xRawData.add("05-23");
xRawData.add("05-24");
xRawData.add("05-25");
chartView.setData(yList , xRawData , 8 , 2);
}
}此例頁(yè)面布局比較簡(jiǎn)單,就是在主頁(yè)面布局中添加一個(gè)自定義的ChartView即可,這里不再貼出。可能寫得有點(diǎn)倉(cāng)促,如果不妥之處,請(qǐng)大家批評(píng)指正,謝謝!
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。
網(wǎng)站名稱:Android繪制動(dòng)態(tài)折線圖
標(biāo)題URL:http://chinadenli.net/article34/phohpe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站建設(shè)、服務(wù)器托管、響應(yīng)式網(wǎng)站、標(biāo)簽優(yōu)化、App開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)