返回
轻松定制刻度尺——Android绘制工具大盘点
Android
2023-11-10 02:00:58
在上一篇文章中,我们讨论了Android事件传递机制,这次我们来实战一下,自定义一把可以滑动的刻度尺。通过这个小案例,你将能够掌握Canvas、Paint、触摸反馈、Scroller、VelocityTracker的基本使用。
1. 绘制刻度
每十个刻度有一个粗长的刻度线,刻度值从-100到100,刻度尺总长度为200dp。
private void drawScale() {
Canvas canvas = new Canvas(mBitmap);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStrokeWidth(2);
int width = mBitmap.getWidth();
int height = mBitmap.getHeight();
// 绘制刻度线
for (int i = -100; i <= 100; i += 10) {
if (i % 50 == 0) {
paint.setStrokeWidth(4);
canvas.drawLine(i * dp + width / 2, 0, i * dp + width / 2, height, paint);
} else {
paint.setStrokeWidth(2);
canvas.drawLine(i * dp + width / 2, 0, i * dp + width / 2, height / 2, paint);
}
}
// 绘制刻度值
paint.setTextSize(20);
paint.setStrokeWidth(1);
for (int i = -100; i <= 100; i += 10) {
if (i % 50 == 0) {
canvas.drawText(String.valueOf(i), i * dp + width / 2 - 10, height - 10, paint);
}
}
}
2. 触摸反馈
当用户触摸刻度尺时,刻度尺应该能够平滑地滑动。实现这一功能需要用到Scroller和VelocityTracker。
private void initTouchListener() {
mScaleView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// 记录按下的位置
mDownX = event.getX();
mScroller.abortAnimation();
return true;
case MotionEvent.ACTION_MOVE:
// 计算移动的距离
float dx = event.getX() - mDownX;
// 更新刻度尺的位置
mScrollX += dx;
invalidate();
return true;
case MotionEvent.ACTION_UP:
// 计算速度
mVelocityTracker.computeCurrentVelocity(1000);
float velocityX = mVelocityTracker.getXVelocity();
// 启动惯性滑动
mScroller.fling(mScrollX, 0, (int) velocityX, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0);
invalidate();
return true;
default:
break;
}
return false;
}
});
}
3. 绘制刻度尺
在onDraw方法中,将刻度尺的Bitmap绘制到画布上,并根据mScrollX的值平移刻度尺。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, -mScrollX, 0, null);
}
4. 惯性滑动
Scroller负责惯性滑动的实现。在computeScroll方法中,如果Scroller还没有结束滑动,则更新刻度尺的位置并重绘刻度尺。
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
mScrollX = mScroller.getCurrX();
invalidate();
}
}
5. 完整代码
public class ScaleView extends View {
private Bitmap mBitmap;
private Canvas mCanvas;
private Paint mPaint;
private int mWidth;
private int mHeight;
private float mDownX;
private float mScrollX;
private Scroller mScroller;
private VelocityTracker mVelocityTracker;
public ScaleView(Context context) {
super(context);
init();
}
private void init() {
mBitmap = Bitmap.createBitmap(2000, 200, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(2);
mWidth = getResources().getDisplayMetrics().widthPixels;
mHeight = 200;
mScroller = new Scroller(getContext());
mVelocityTracker = VelocityTracker.obtain();
drawScale();
initTouchListener();
}
private void drawScale() {
Canvas canvas = new Canvas(mBitmap);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStrokeWidth(2);
int width = mBitmap.getWidth();
int height = mBitmap.getHeight();
// 绘制刻度线
for (int i = -100; i <= 100; i += 10) {
if (i % 50 == 0) {
paint.setStrokeWidth(4);
canvas.drawLine(i * dp + width / 2, 0, i * dp + width / 2, height, paint);
} else {
paint.setStrokeWidth(2);
canvas.drawLine(i * dp + width / 2, 0, i * dp + width / 2, height / 2, paint);
}
}
// 绘制刻度值
paint.setTextSize(20);
paint.setStrokeWidth(1);
for (int i = -100; i <= 100; i += 10) {
if (i % 50 == 0) {
canvas.drawText(String.valueOf(i), i * dp + width / 2 - 10, height - 10, paint);
}
}
}
private void initTouchListener() {
mScaleView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// 记录按下的位置
mDownX = event.getX();
mScroller.abortAnimation();
return true;
case MotionEvent.ACTION_MOVE:
// 计算移动的距离
float dx = event.getX() - mDownX;
// 更新刻度尺的位置
mScrollX += dx;
invalidate();
return true;
case MotionEvent.ACTION_UP:
// 计算速度
mVelocityTracker.computeCurrentVelocity(1000);
float velocityX = mVelocityTracker.getXVelocity();
// 启动惯性滑动
mScroller.fling(mScrollX, 0, (int) velocityX, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0);
invalidate();
return true;
default:
break;
}
return false;
}
});
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, -mScrollX, 0, null);
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
mScrollX = mScroller.getCurrX();
invalidate();
}
}
}
这个小案例涵盖了Canvas、Paint、触摸反馈、Scroller、VelocityTracker等基本知识,希望对你有所帮助。