自定义android折线图,实现左右滑动和快速滑动
16lz
2021-01-26
由于折线统计图在绘制过程中,会经常拖动,而每次拖动都需要重新绘制,所以考虑使用surfaceview。
1、继承Surfaceview,实现SurfaceHolder.Callback, Runnable接口
/** * 画布创建时候执行的方法 * * @param holder */ @Override public void surfaceCreated(SurfaceHolder holder) { // 开始绘画 mIsDrawing = true; // 启动绘画线程 new Thread(this).start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } /** * 画布销毁时候执行的方法 */ @Override public void surfaceDestroyed(SurfaceHolder holder) { // 停止绘画 mIsDrawing = false; }
2、绘制线程执行的方法
/** 子线程,循环绘制折线 */ @Override public void run() { // 如果处于绘画状态,那么就开始绘制 while (mIsDrawing) { // 设置滚动减速 setSpeedCut(); // 绘制方法 draw(); } } /** * 设置快速滚动时,末尾的减速 */ private void setSpeedCut() { if (!mIsTouch && isScroll) { // 通过当前速度计算所对应的偏移量 mOffset = mOffset + mSpeed; //当处于边缘时候使值不在变化 setOffsetRange(); } // 每次偏移量的计算 if (mSpeed != 0) { time++; //这里设置的是快速滚动时间不操作两秒 //可以看成是一个Y轴交点为(0,xVelocity) // x轴交点为(40,xVelocity) // 对称轴为40<每个单位时间为50毫秒,40对应两秒> mSpeed = (int) (xVelocity + time * time * (xVelocity / 1600.0) - (xVelocity / 20.0) * time); } else { time = 0; mSpeed = 0; } } /** 具体的绘制方法 */ private void draw() { try { long start = System.currentTimeMillis(); // 获取并锁定画布 mCanvas = mHolder.lockCanvas(); // 设置画布背景为白色 mCanvas.drawColor(0xffffffff); // 绘制坐标轴 drawAxis(); // 绘制曲线 drawLine(); long end = System.currentTimeMillis(); if (end - start < 50) { Thread.sleep(50 - (end - start)); } } catch (Exception e) { e.printStackTrace(); } finally { if (mCanvas != null) { // 保证每次都将绘制的内容提交到服务器 mHolder.unlockCanvasAndPost(mCanvas); } } }
3、绘制坐标轴
/** * 绘制x、y轴 */ private void drawXYLine() { mAxisWidth = mWidth - 2 * mPaddint; mAxisHeight = mHeight - 2 * mPaddint; mCoordinatePaint.setStrokeWidth(mLineWidth); mCoordinatePaint.setAntiAlias(true); // 绘制x轴 mCoordinatePaint.setColor(mXLineColor); mCanvas.drawLine(0, 0, mAxisWidth, 0, mCoordinatePaint); // 绘制y轴 mCoordinatePaint.setColor(mYLineColor); mCanvas.drawLine(0, 0, 0, -mAxisHeight, mCoordinatePaint); } /** 绘制刻度线和箭头 */ private void drawXYScale() { // 画x轴的刻度 // x轴的分割线数量 mXScaleNum = mXRange / mXUnit; // x轴尽头的空隙 mXBlank = dp2px(getContext(), DEFAULT_X_BLANK); // 每个刻度的宽度 mXScaleWidth = (int) ((mAxisWidth - mXBlank) * 1.0 / mXScaleNum); for (int i = 0; i < mXScaleNum; i++) { mCanvas.drawLine(mXScaleWidth * (i + 1), 0, mXScaleWidth * (i + 1), -mScaleHeight, mCoordinatePaint); } // 画y轴的刻度 mYScaleNum = mYRange / mYUnit; // y轴尽头的空间 mYBlank = dp2px(getContext(), DEFAULT_Y_BLANK); mYScaleWidth = (int) ((mAxisHeight - mYBlank) * 1.0 / mYScaleNum); for (int i = 0; i < mYScaleNum; i++) { mCanvas.drawLine(0, -mYScaleWidth * (i + 1), mScaleHeight, -mYScaleWidth * (i + 1), mCoordinatePaint); } // 画X轴的箭头 mCanvas.drawLine(mAxisWidth, 0, mAxisWidth - mScaleHeight * 2, -mScaleHeight, mCoordinatePaint); mCanvas.drawLine(mAxisWidth, 0, mAxisWidth - mScaleHeight * 2, mScaleHeight, mCoordinatePaint); // 画Y轴的箭头 mCanvas.drawLine(0, -mAxisHeight, mScaleHeight, -mAxisHeight + 2 * mScaleHeight, mCoordinatePaint); mCanvas.drawLine(0, -mAxisHeight, -mScaleHeight, -mAxisHeight + 2 * mScaleHeight, mCoordinatePaint); }
4、绘制折线
/** 绘制折线 */ private void drawLine() { mCanvas.save(); mCanvas.translate(mPaddint, mHeight - mPaddint); // 设置画笔属性 mLinePaint.setAntiAlias(true); mLinePaint.setStrokeWidth(3); mLinePaint.setColor(mLineColor); mLinePaint.setStyle(Style.STROKE); // 如果折线集合不为空 if (mLines != null && mLines.size() > 0) { // 循环绘制所有线条 for (int i = 1; i < mLines.size(); i++) { // 上一个点的xy坐标 int previousY = (int) (mLines.get(i - 1) * 1.0 / mYRange * (mAxisHeight - mYBlank)); int previousX = (i - 1) * mXScaleWidth + mOffset; // 当前点的xy坐标 int thisY = (int) (mLines.get(i) * 1.0 / mYRange * (mAxisHeight - mYBlank)); int thisX = i * mXScaleWidth + mOffset; // 保证只绘制坐标轴范围内的部分 if (previousX > 0 && previousX < mAxisWidth - mXBlank && thisX > 0 && thisX < mAxisWidth - mXBlank) // 两个坐标连线 mCanvas.drawLine(previousX, -previousY, thisX, -thisY, mLinePaint); } } mCanvas.restore(); }
5、触摸事件处理
@Override public boolean onTouchEvent(MotionEvent event) { int rawX = (int) (event.getRawX()); // 计算当前速度 VelocityTracker velocityTracker = VelocityTracker.obtain(); velocityTracker.addMovement(event); // 计算速度的单位时间 velocityTracker.computeCurrentVelocity(50); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 记录触摸点坐标 lastX = rawX; mIsTouch = true; break; case MotionEvent.ACTION_MOVE: // 计算便宜量 int offsetX = rawX - lastX; // 在当前偏移量的基础上增加偏移量 mOffset = mOffset + offsetX; setOffsetRange(); // 偏移量修改后下次重绘会有变化 lastX = rawX; // 获取X方向上的速度 xVelocity = velocityTracker.getXVelocity(); mSpeed = (int) xVelocity; break; case MotionEvent.ACTION_UP: mIsTouch = false; break; } // 计算完成后回收内存 velocityTracker.clear(); velocityTracker.recycle(); return true; }
最后附上源码下载地址:http://download.csdn.net/detail/h55l55/9528656
更多相关文章
- Android(安卓)第一个OpenGL ES程序
- Android(安卓)Material Design-Creating Apps with Material Des
- 自定义控件其实很简单(笔记一)
- Android取得当前屏幕静态布局的截图
- Android中Toolbar随着ScrollView滑动透明度渐变效果实现
- Android(安卓)drawable 可绘制资源总结
- Android(安卓)的第三方报表组件,AChartEngine 案列demo
- 运用开源 achartengine 绘制android端的折线图片,多表显示
- Android(安卓)Canvas drawArc方法介绍