最近看了很多关于自定义控件的博客,其中有个关于涂鸦的博文中的例子在我的手机上就无法合适的使用,例如,我手指移动在屏幕右侧,结果线却画在了中间的位置,还以为是我手机的问题,结果发现只是代码中对各种大小和布局都是写死的。
非常难说像android自带控件一般,随便设大小,边距这些,功能也不会变样,所以在此要做一个比较正常的涂鸦控件,主要是能够像普通android控件一般,能够在xml中设置样式直接控制该控件外观。
首先该View从onMeasure()方法中获得自己的大小,接着再根据这个大小初始化Bitmap cacheBitmap,这个bitmap用来保存画的笔画的,同时也是该view的draw方法中需要画出来,展现给用户看的效果的bitmap
然后,就是用OnTouch()方法来获得用户滑动的位置和状态来不断在cacheBitmap的画出路径
完整应用在 这里,不过基本没什么其他内容了
非常难说像android自带控件一般,随便设大小,边距这些,功能也不会变样,所以在此要做一个比较正常的涂鸦控件,主要是能够像普通android控件一般,能够在xml中设置样式直接控制该控件外观。
首先该View从onMeasure()方法中获得自己的大小,接着再根据这个大小初始化Bitmap cacheBitmap,这个bitmap用来保存画的笔画的,同时也是该view的draw方法中需要画出来,展现给用户看的效果的bitmap
然后,就是用OnTouch()方法来获得用户滑动的位置和状态来不断在cacheBitmap的画出路径
最后,调用invalidate(),通知View调用自己的draw()方法
直接上代码吧,里面也有比较详细的注释了
<span style="font-size:18px;">public class TuyaView extends View {
private Canvas canvas = null;
private Paint paint = null;
private Bitmap cacheBitmap = null;
private Path path = null;
// 记录路径path的起始位置
float x, y;
public TuyaView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public TuyaView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public TuyaView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
// widthMeasureSpec、heightMeasureSpec是有高16位模式和低16位size,所以看起来会很大
// 获得模式
int mode = MeasureSpec.getMode(widthMeasureSpec);
// AT_MOST限制最大尺寸,EXACTLY则是确定好尺寸了,例如在xml文件中设置了大小
if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
// 获得View实际大小
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
init(width , height);
// 以下方法是设置View大小的方法,除非想在代码中控制大小,不然不应该在这里填写大小
// 如果希望其生效则不要调用super.onMeasure(widthMeasureSpec, heightMeasureSpec);这句了
// setMeasuredDimension(400, height);
} else if (mode == MeasureSpec.UNSPECIFIED) { // View的大小不确定时
Log.d("WOGU", "mode=UNSPECIFIED");
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private void init(int width , int height) {
cacheBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
paint = new Paint(Paint.DITHER_FLAG);
path = new Path();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
//设置画笔笔画宽度
paint.setStrokeWidth(1);
paint.setAntiAlias(true);
paint.setDither(true);
canvas = new Canvas();
canvas.setBitmap(cacheBitmap);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
float curX = event.getX();
float curY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = curX;
y = curY;
path.moveTo(x, y);
break;
case MotionEvent.ACTION_UP:
path.quadTo(x, y, curX, curY);
canvas.drawPath(path, paint);
path.reset();
break;
case MotionEvent.ACTION_MOVE:
path.quadTo(x, y, curX, curY);
canvas.drawPath(path, paint);
x = curX;
y = curY;
path.moveTo(x, y);
break;
}
invalidate();
return true;
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
canvas.drawBitmap(cacheBitmap, 0, 0 ,paint);
super.onDraw(canvas);
}
}</span>
直接在xml文件中控制大小和背景等,不影响该自定义view的使用
<com.example.tuyaview.TuyaView
android:layout_width="fill_parent"
android:layout_height="300dp"
android:background="@color/default_bg"
android:layout_gravity="center_horizontal|center"
/>
完整应用在 这里,不过基本没什么其他内容了