我使用android.graphics.Path绘制android.graphics.Canvas。我希望允许用户使用一系列颜色和笔触宽度进行绘制,但是,每当更改颜色或笔触宽度时,都会使用新的颜色或笔触宽度重新绘制所有内容。我该如何解决这个问题?
的xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/btnW10"
android:layout_margin="3sp"
android:layout_weight="1"
android:text="Width10"/>
<Button
android:id="@+id/btnW40"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="3sp"
android:layout_weight="1"
android:text="Width40"/>
<Button
android:id="@+id/btnW70"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="3sp"
android:layout_weight="1"
android:text="Width70"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="20dp"></LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="3sp"
android:layout_weight="1"
android:id="@+id/btnBlue"
android:text="Blue"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="3sp"
android:layout_weight="1"
android:id="@+id/btnRed"
android:text="Red"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="3sp"
android:layout_weight="1"
android:id="@+id/btnGreen"
android:text="Green"/>
</LinearLayout>
<com.vladislav.canvaswc.DrawLine
android:id="@+id/drwLine"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
main.java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener
{
DrawLine dr;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnB=(Button) findViewById(R.id.btnBlue);
Button btnG=(Button) findViewById(R.id.btnGreen);
Button btnR=(Button) findViewById(R.id.btnRed);
Button btnW10=(Button) findViewById(R.id.btnW10);
Button btnW40=(Button) findViewById(R.id.btnW40);
Button btnW70=(Button) findViewById(R.id.btnW70);
dr =(DrawLine) findViewById(R.id.drwLine);
btnB.setOnClickListener(this);
btnG.setOnClickListener(this);
btnR.setOnClickListener(this);
btnW10.setOnClickListener(this);
btnW40.setOnClickListener(this);
btnW70.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch(v.getId())
{
case R.id.btnBlue : dr.changeColor(Color.BLUE);break;
case R.id.btnGreen : dr.changeColor(Color.GREEN);break;
case R.id.btnRed : dr.changeColor(Color.RED);break;
case R.id.btnW10 : dr.changeWidth(10f);break;
case R.id.btnW40 : dr.changeWidth(40f);break;
case R.id.btnW70 : dr.changeWidth(70f);break;
}
}
}
drawline.java ChangeWidthColor它的界面有2个方法changeColor() 和changeWidth()
public class DrawLine extends View implements ChangeWidthColor {
private Paint paint = new Paint();
private Path path = new Path();
public float x;
public float y;
public DrawLine(Context context) {
super(context);
init(context);
}
public DrawLine(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public DrawLine(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public void init(Context context) {
//paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.MITER);
//paint.setStrokeWidth(5f);
}
@Override
public void changeColor(int color) {
paint.setColor(color);
}
@Override
public void changeWidth(float width) {
paint.setStrokeWidth(width);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path,paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x= event.getX();
y= event.getY();
path.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
x= event.getX();
y= event.getY();
path.lineTo(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
invalidate();
break;
}
invalidate();
return true;
}
}
答案 0 :(得分:3)
此解决方案维护一个Path对象列表和一个用于存储颜色的整数列表。这些列表是并行的 - 路径和颜色对的每个列表中有1个条目。 onDraw迭代这些列表,使用相应的颜色绘制每个路径。
每次用户单击以更改颜色时,都会创建一个新路径。 ACTION_DOWN和ACTION_MOVE在路径上调用moveTo(x,y)和lineTo(x,y),ACTION_UP会将路径和当前颜色添加到列表中。
注意:我没有实现笔触宽度的解决方案,但是,您应该能够按照示例自行添加。
public class DrawLine extends View {
private Path path = new Path();
private Paint paint = new Paint();
private int currentColor = Color.BLACK;
private List<Path> paths = new ArrayList<Path>();
private List<Integer> colors = new ArrayList<Integer>();
private float x;
private float y;
public DrawLine(Context context) {
super(context);
init(context);
}
public DrawLine(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public DrawLine(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public void init(Context context) {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.MITER);
paint.setColor(currentColor);
}
public void changeColor(int color) {
currentColor = color;
path = new Path();
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int x = 0; x < paths.size(); x++) {
paint.setColor(colors.get(x));
canvas.drawPath(paths.get(x), paint);
}
}
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = event.getX();
y = event.getY();
path.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
x = event.getX();
y = event.getY();
path.lineTo(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
paths.add(path);
colors.add(currentColor);
invalidate();
break;
}
invalidate();
return true;
}
}
`
答案 1 :(得分:0)
public class DrawLine extends View implements ChangeWidthColor {
private Path path = new Path();
private Paint paint = new Paint();
private int currentColor = Color.BLACK;
private float width = 1f;
public float x;
public float y;
private LinkedList<Integer> color = new LinkedList<Integer>();
private LinkedList<Float> widthSize = new LinkedList<Float>();
private LinkedList<Path> paths = new LinkedList<Path>();
public DrawLine(Context context) {
super(context);
init(context);
}
public DrawLine(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public DrawLine(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public void init(Context context) {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.MITER);
paint.setColor(currentColor);
paint.setStrokeWidth(5f);
}
@Override
public void changeColor(int color) {
currentColor = color;
path = new Path();
}
@Override
public void changeWidth(float width) {
this.width = width;
path = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < paths.size(); i++) {
paint.setStrokeWidth(widthSize.get(i));
paint.setColor(color.get(i));
canvas.drawPath(paths.get(i), paint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = event.getX();
y = event.getY();
path.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
x = event.getX();
y = event.getY();
path.lineTo(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
color.add(currentColor);
paths.add(path);
widthSize.add(width);
break;
default:
return false;
}
invalidate();
return true;
}
}
答案 2 :(得分:-1)
每当您修改与UI相关的内容时,您都需要在自定义视图中调用invalidate()
。所以更新的方法将是:
@Override
public void changeColor(int color) {
paint.setColor(color);
invalidate();
}
@Override
public void changeWidth(float width) {
paint.setStrokeWidth(width);
invalidate();
}