我的活动类文件:
package com.drawing.test;
import android.app.Activity;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.LinearLayout;
public class TstActivity extends Activity implements OnTouchListener
{
float x1 = 0, y1 = 0, x2 = 0, y2 = 0;
public static boolean action=false;
private Bitmap mBitmap;
private Canvas mCanvas;
private Paint mBitmapPaint;
Drawer mDrawer;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout mLinearLayout = (LinearLayout) findViewById(R.id.drawView);
mLinearLayout.setOnTouchListener((OnTouchListener) this);
mLinearLayout.addView(new Drawer(this));
}
public boolean onTouch(View v, MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
y1 = event.getY();
action=false;
//v.invalidate();
return true;
case MotionEvent.ACTION_MOVE:
x1=x2;
y1=y2;
x2 = event.getX();
y2 = event.getY();
v.invalidate();
action=true;
return true;
case MotionEvent.ACTION_UP:
x2 = event.getX();
y2 = event.getY();
v.invalidate();
action=true;
return true;
}
return false;
}
public class Drawer extends View
{
public Drawer(Context context)
{
super(context);
mBitmap = Bitmap.createBitmap(400, 800, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mBitmapPaint.setColor(Color.MAGENTA);
invalidate();
}
protected void onDraw(Canvas canvas)
{
if(x1==x2 && y1==y2)return;
Paint p = new Paint();
// Canvas mCanvas1=new Canvas(mBitmap);
p.setColor(Color.parseColor("#7CFC00"));
canvas.drawBitmap(mBitmap, 0, 0, p);
// canvas.drawLine(x1, y1, x2 , y2, p);
p.setColor(Color.RED);
// mCanvas1.drawLine(x1, y1, x2, y2,p);
if(action==true)mCanvas.drawLine(x1, y1, x2, y2, mBitmapPaint);
}
}
}
我的布局XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/drawView">
</LinearLayout>
当我在模拟器上尝试此操作时,线条在中间断开但继续绘制。我也尝试过设备,同样的问题发生但数量较少。此外,显示屏有时会闪烁,或者完全消失。当它完全变成黑色时,如果我触摸一次就会回来。
我做错了什么,我是否应该改变方法。
任何建议都表示赞赏。感谢
答案 0 :(得分:2)
这是一个同步问题。基本上,invalidate()
不阻塞调用:它只是告诉系统在将来的某个时刻重绘。那么会发生什么:
invaldate()
计划尽快重绘您可以通过添加两个匹配计数器来证明它,一个用于invalidate()
,另一个用于onDraw()
。一段时间后,您会看到invalidate()
的来电次数大于onDraw()
的次数。我的建议是将点数与Queue
中的触摸事件保持一致。另请注意,每次分配Bitmap
时,都需要在完成后调用recycle
以避免内存泄漏。事实上,像素存储在本机内存中,并且在视图被销毁时不会被垃圾收集。当我的活动停止时,我通常会拨打recycle
。这是我的代码:
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public static class Drawer extends View {
private Bitmap cache;
private Queue<PointF> points;
private PointF from;
public Drawer(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
points = new ConcurrentLinkedQueue<PointF>();
}
@Override
public boolean onTouchEvent(MotionEvent evt) {
switch (evt.getAction()) {
case MotionEvent.ACTION_DOWN: from = new PointF(evt.getX(), evt.getY()); break;
case MotionEvent.ACTION_MOVE: points.add(new PointF(evt.getX(), evt.getY())); invalidate(); break;
case MotionEvent.ACTION_UP: from = null; break;
default: from = null;
}
return true;
}
@Override
public void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w == 0 || h == 0)
return;
cache = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
}
@Override
public void onDraw(Canvas systemCanvas) {
int w = getWidth();
int h = getHeight();
if (w == 0 || h == 0)
return;
if (cache == null)
cache = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
// Draw on the cache
Canvas canvas = new Canvas(cache);
Paint paint = new Paint();
paint.setStrokeWidth(4);
paint.setColor(Color.MAGENTA);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
drawPoints(points, canvas, paint);
// Draw the cache with the system canvas
systemCanvas.drawBitmap(cache, 0, 0, paint);
}
private void drawPoints(Queue<PointF> points, Canvas canvas, Paint paint) {
if (from == null)
return;
PointF to;
while ((to = points.poll()) != null) {
canvas.drawLine(from.x, from.y, to.x, to.y, paint);
from = to;
}
}
}
}
这是布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="@+id/drawView">
<view
class="com.zybnet.test.MainActivity$Drawer"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
您可以看到海关视图也可以在XML中使用:)
答案 1 :(得分:0)
对于motionEvent.ACTION_MOVE,他们可以并将进行批处理。我相信这就是为什么会出现中断的原因。
请参阅文档:
<强>配料强>
为了提高效率,使用ACTION_MOVE的运动事件可以将单个对象内的多个运动样本一起批处理。使用getX(int)和getY(int)可以获得最新的指针坐标。使用getHistoricalX(int,int)和getHistoricalY(int,int)访问批处理中的早期坐标。坐标只是“历史”,只要它们比批次中的当前坐标更旧;但是,它们仍然不同于先前运动事件中报告的任何其他坐标。要按时间顺序处理批次中的所有坐标,首先使用历史坐标,然后使用当前坐标。