我想创建一个小型绘画应用程序,我可以使用一些颜色绘制,我只测试了一个颜色更改,直到现在它不能正常工作。当我单击按钮并开始使用新颜色绘制时,我所做的所有先前绘图也会更改颜色。有人能帮助我吗?
public class MyTouchEventView extends View {
private Paint paint = new Paint();
private Path path = new Path();
public Button btnChange;
public LayoutParams params;
public MyTouchEventView(Context context) {
super(context);
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(1f);
btnChange = new Button(context);
btnChange.setText("Chaneg color");
params = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
btnChange.setLayoutParams(params);
btnChange.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
paint.setColor(Color.GREEN);
}
});
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float pointX = event.getX();
float pointY = event.getY();
// Checks for the event that occurs
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(pointX, pointY);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(pointX, pointY);
break;
default:
return false;
}
postInvalidate();
return true;
}
}
答案 0 :(得分:4)
这里的问题是你只使用一个路径。
您应该在每个ACTION_DOWN上创建一个新路径。对于每个这些路径,您还必须存储Paint。
例如,您可以定义一个具有两个元素作为成员的类:
public class Stroke {
private Path _path;
private Paint _paint;
}// add constructor(Path, Paint) and accessors
您的上下文中的笔划列表:
List<Stroke> allStrokes = new ArrayList<Stroke>();
因此,在每个ACTION_DOWN
上,您创建一个新的描边(所以一个新的路径,以及一个带有您选择颜色的新油漆)。
在每个ACTION_MOVE
上,您都可以检索最后添加的路径,然后您可以lineTo
最后一点。
然后在你的onDraw上,只绘制所有创建的Stroke:
for (Stroke s : allStrokes) {
canvas.drawPath(s.getPath(), s.getPaint());
}
请注意,使用此简单解决方案,您无法执行multiTouch绘图。为此,您还必须存储和处理MotionEvent ID。
编辑:这是一个可用的多点触控绘画示例,可以创建充满随机颜色的笔触:
<强> DrawArea.java:强>
import android.content.Context;
import android.graphics.*;
import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class DrawArea extends View {
private List<Stroke> _allStrokes; //all strokes that need to be drawn
private SparseArray<Stroke> _activeStrokes; //use to retrieve the currently drawn strokes
private Random _rdmColor = new Random();
public DrawArea(Context context) {
super(context);
_allStrokes = new ArrayList<Stroke>();
_activeStrokes = new SparseArray<Stroke>();
setFocusable(true);
setFocusableInTouchMode(true);
setBackgroundColor(Color.WHITE);
}
public void onDraw(Canvas canvas) {
if (_allStrokes != null) {
for (Stroke stroke: _allStrokes) {
if (stroke != null) {
Path path = stroke.getPath();
Paint painter = stroke.getPaint();
if ((path != null) && (painter != null)) {
canvas.drawPath(path, painter);
}
}
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getActionMasked();
final int pointerCount = event.getPointerCount();
switch (action) {
case MotionEvent.ACTION_DOWN: {
pointDown((int)event.getX(), (int)event.getY(), event.getPointerId(0));
break;
}
case MotionEvent.ACTION_MOVE: {
for (int pc = 0; pc < pointerCount; pc++) {
pointMove((int) event.getX(pc), (int) event.getY(pc), event.getPointerId(pc));
}
break;
}
case MotionEvent.ACTION_POINTER_DOWN: {
for (int pc = 0; pc < pointerCount; pc++) {
pointDown((int)event.getX(pc), (int)event.getY(pc), event.getPointerId(pc));
}
break;
}
case MotionEvent.ACTION_UP: {
break;
}
case MotionEvent.ACTION_POINTER_UP: {
break;
}
}
invalidate();
return true;
}
private void pointDown(int x, int y, int id) {
//create a paint with random color
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10);
paint.setColor(_rdmColor.nextInt());
//create the Stroke
Point pt = new Point(x, y);
Stroke stroke = new Stroke(paint);
stroke.addPoint(pt);
_activeStrokes.put(id, stroke);
_allStrokes.add(stroke);
}
private void pointMove(int x, int y, int id) {
//retrieve the stroke and add new point to its path
Stroke stroke = _activeStrokes.get(id);
if (stroke != null) {
Point pt = new Point(x, y);
stroke.addPoint(pt);
}
}
}
<强> Stroke.java:强>
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
public class Stroke {
private Path _path;
private Paint _paint;
public Stroke (Paint paint) {
_paint = paint;
}
public Path getPath() {
return _path;
}
public Paint getPaint() {
return _paint;
}
public void addPoint(Point pt) {
if (_path == null) {
_path = new Path();
_path.moveTo(pt.x, pt.y);
} else {
_path.lineTo(pt.x, pt.y);
}
}
}
<强> MyActivity.java:强>
import android.app.Activity;
import android.os.Bundle;
public class MyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DrawArea da = new DrawArea(this);
setContentView(da);
}
}
答案 1 :(得分:1)
我的解决方案:
public class PaintView extends ImageView {
private class Holder {
Path path;
Paint paint;
Holder(int color) {
path = new Path();
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(4f);
paint.setColor(color);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
}
}
private int color = Color.WHITE;
private List<Holder> holderList = new ArrayList<Holder>();
public PaintView(Context context) {
super(context);
init();
}
public PaintView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PaintView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
holderList.add(new Holder(color));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (Holder holder : holderList) {
canvas.drawPath(holder.path, holder.paint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
holderList.add(new Holder(color));
holderList.get(holderList.size() - 1).path.moveTo(eventX, eventY);
return true;
case MotionEvent.ACTION_MOVE:
holderList.get(holderList.size() - 1).path.lineTo(eventX, eventY);
break;
case MotionEvent.ACTION_UP:
break;
default:
return false;
}
invalidate();
return true;
}
public void resetPaths() {
for (Holder holder : holderList) {
holder.path.reset();
}
invalidate();
}
public void setBrushColor(int color) {
this.color = color;
}
}
答案 2 :(得分:0)
切换到新颜色时应该使用Path.reset(),它应该可以解决您的问题。 docs