Java 如何在android中绘制不同颜色的多条线并撤销、重做路径?
我想用不同的颜色在视图上画多条线,然后在android中撤销、重做路径 我使用位图绘制选项,每个路径都有唯一的颜色,但“撤消”、“重做”不起作用 以下是我的bitmappaint代码:Java 如何在android中绘制不同颜色的多条线并撤销、重做路径?,java,android,bitmap,Java,Android,Bitmap,我想用不同的颜色在视图上画多条线,然后在android中撤销、重做路径 我使用位图绘制选项,每个路径都有唯一的颜色,但“撤消”、“重做”不起作用 以下是我的bitmappaint代码: public MyView(Context context, Object object) { super(context); setFocusable(true); setFocusableInTouchMode(true); mPath = new Path(); m
public MyView(Context context, Object object) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
mPath = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(0xFFFFFF00);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(3);
mBitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
}
protected void onDraw(Canvas canvas)
{
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for (Path p : paths)
{
canvas.drawPath(p, mPaint);
}
canvas.drawPath(mPath, mPaint);
}
public boolean onTouchEvent(MotionEvent event)
{
float x = event.getX();
float y = event.getY();
int action = event.getAction();
int action1=event.getAction();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
undonePaths.clear();
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
startPoint = new PointF(event.getX(), event.getY());
endPoint = new PointF();
invalidate();
// isDrawing = true;
break;
case MotionEvent.ACTION_MOVE:
float dx = Math.abs(x - mX);
System.out.println("action move");
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
{
// currentDrawingPath.path.quadTo(mX,mY,(x + mX)/2, (y + mY)/2);
}
mX = x;
mY = y;
endPoint.x = event.getX();
endPoint.y = event.getY();
isDrawing = true;
invalidate();
break;
case MotionEvent.ACTION_UP:
mPath.lineTo(mX, mY);
paths.add(mPath);
mPath = new Path();
// mCanvas.drawPath(mPath, ppaint);
endPoint.x = event.getX();
endPoint.y = event.getY();
isDrawing = false;
invalidate();
break;
default:
break;
}
}
!![bitmappaint画布的输出][1]
[1] :
如果没有使用位图,我将面临颜色问题,如果我为路径选择蓝色,则意味着之前的所有路径都将更改为蓝色
这是我的密码
protected void onDraw(Canvas canvas)
{
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for (Path p : paths)
{
canvas.drawPath(p, mPaint);
}
canvas.drawPath(mPath, mPaint);
}
!![使用画布绘制的无位图输出][2]
[2] :
请帮我在android中画出多条不同颜色的唯一路径。
当您处理MotionEvent时,请提前感谢……。操作:您需要保存用于绘制路径的颜色,如下所示:
case MotionEvent.ACTION_UP:
paths.add(mPath);
colorsMap.put(mPath,selectedColor); // store the color of mPath
...
绘制路径之前,需要设置绘制颜色:
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for (Path p : paths)
{
mPaint.setColor(colorsMap.get(p));
canvas.drawPath(p, mPaint);
}
mPaint.setColor(selectedColor);
canvas.drawPath(mPath, mPaint);
}
colorsMap是一个简单的实例变量:
private Map<Path, Integer> colorsMap = new HashMap<Path, Integer>();
private Map colorsMap=new HashMap();
要实现撤销/重做功能,只需从路径中删除最后一个元素(并将其存储在撤销列表中,以便重做时可以恢复它)。请参阅此工作代码。我在自己的应用程序上对其进行了测试,效果非常好。 可能对你有帮助。请评论一下
public class Main extends Activity implements OnColorChangedListener {
//public static int selectedColor = Color.BLACK;
public static ArrayList<Path> mMaindialog;
// private ArrayList<Path> undonePaths;
// public int selectedcolor;
private static final String COLOR_PREFERENCE_KEY = "color";
private FrameLayout relativelayout;
static String sdpath,location;
Boolean i;
// Instance variables
private Bitmap mBitmap=null;
Bitmap bitmap;
private Paint mPaint, mBitmapPaint, mPaint1;
private MyView mView;
ImageView idd;
// private Path mPath;
int slll = Color.BLACK;
Bitmap map=ListView5.bMap;
private Button ClearPaint, Colorpaint;
Ghostdatabase gost;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
idd=(ImageView)findViewById(R.id.imageView1);
relativelayout = (FrameLayout) findViewById(R.id.frameLayout);
DisplayMetrics metrics = getBaseContext().getResources()
.getDisplayMetrics();
int w = metrics.widthPixels;
int h = metrics.heightPixels;
System.out.println(" width " + w);
System.out.println(" height " + h);
mView = new MyView(this, w, h);
mView.setDrawingCacheEnabled(true);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(4);
ClearPaint = (Button) findViewById(R.id.ne);
ClearPaint.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// mBitmap.eraseColor(Color.TRANSPARENT);
// mPath.reset();
// mView.invalidate();
mView.onClickUndo();
}
});
Button save22 = (Button) findViewById(R.id.save);
save22.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
File cacheDir;
Toast.makeText(Main.this, "Photo", 500).show();
Bitmap icon;
relativelayout.setDrawingCacheEnabled(true);
icon = Bitmap.createBitmap(relativelayout.getDrawingCache());
Bitmap bitmap = icon;
relativelayout.setDrawingCacheEnabled(false);
// File mFile1 = Environment.getExternalStorageDirectory();
Date d = new Date();
String fileName = d.getTime() + "mg1.jpg";
File storagePath = (Environment.getExternalStorageDirectory());
File dest = new File(storagePath + "/CityAppImages");
if (!dest.exists()) {
dest.mkdirs();
}
File mFile2 = new File(dest, fileName);
sdpath = mFile2.getAbsolutePath();
Log.d("qqqqqqqqqqqqqqqqqqqqqqq", "zzzzzzzz" + sdpath);
try {
FileOutputStream outStream;
outStream = new FileOutputStream(mFile2);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
Toast.makeText(Main.this, "Photo Saved Sucessfully", 500)
.show();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(Main.this, "Photo Not Saved Sucessfully",
500).show();
}
gost = new Ghostdatabase(Main.this);
gost.open();
gost.insertTitle(sdpath);
}
});
Button view = (Button) findViewById(R.id.listtt);
view.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent ii = new Intent(Main.this, ListView5.class);
startActivity(ii);
}
});
Button Colorpaint = (Button) findViewById(R.id.Color);
Colorpaint.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
int color = PreferenceManager.getDefaultSharedPreferences(
Main.this).getInt(COLOR_PREFERENCE_KEY, Color.WHITE);
// int _color = R.color.red;
new ColorPickerDialog(v.getContext(),
new OnColorChangedListener() {
public void colorChanged(int color) {
mPaint.setColor(color);
slll = color;
Log.i("TAG", "mpaint one" + mPaint);
}
}, mPaint.getColor()).show();
Log.i("TAG", "mpaint two" + mPaint);
}
});
relativelayout.addView(mView);
}
// //////////******************* Pinting view
// *******************///////////////////
public class MyView extends View implements OnTouchListener {
private Map<Path, Integer> colorsMap = new HashMap<Path, Integer>();
private ArrayList<Path> mMaindialog = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
int colorPicked = slll;
// Paint mPaint1;
private Canvas mCanvas;
private Path mPath;
public MyView(Context c, int w, int h) {
super(c);
if(GlobalVariable.impath==1)
{
Log.d("","111111"+GlobalVariable.impath);
System.out.println(GlobalVariable.impath);
Intent ii = getIntent();
location = ii.getStringExtra("IMAGE");
// bitmap.recycle();
Log.d("","location"+location);
bitmap = BitmapFactory.decodeFile(location);
mBitmap = Bitmap.createScaledBitmap(bitmap,300, 300,false);
Log.d("hhhhhhhhhhhhhhhssssssss","mBitmap"+mBitmap);
//mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
// idd.setImageBitmap(mBitmap);
Log.d("hhhhhhhhhhhhhhhssssssss","GlobalVariable.impath"+GlobalVariable.impath);
}
else if(GlobalVariable.impath==2){
//bitmap.recycle();
Log.d("","22222222222222222222222"+GlobalVariable.impath);
bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.base);
mBitmap = Bitmap.createScaledBitmap(bitmap,100, 100, false);
//mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Log.d("hhhhhhhhhhhhhhhssssssss1111111","mBitmap"+mBitmap);
}
//
mCanvas = new Canvas(mBitmap);
mPath = new Path();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for (Path p : mMaindialog) {
mPaint.setColor(colorsMap.get(p));
canvas.drawPath(p, mPaint);
}
mPaint.setColor(slll);
canvas.drawPath(mPath, mPaint);
}
// //////************touching evants for painting**************///////
private float mX, mY;
private static final float TOUCH_TOLERANCE = 0;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
undonePaths.clear();
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath = new Path();
mPath.reset();
mMaindialog.add(mPath);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// touch_start(x, y);
// invalidate();
undonePaths.clear();
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
// touch_move(x, y);
// invalidate();
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
invalidate();
break;
case MotionEvent.ACTION_UP:
// touch_up();
// invalidate();
mPath.lineTo(mX, mY);
mMaindialog.add(mPath);
colorsMap.put(mPath, slll);
mPath = new Path();
mPath.reset();
invalidate();
break;
}
return true;
} // end of touch events for image
private Paint createPen(int colorPicked) {
// TODO Auto-generated method stub
mPaint1 = new Paint();
mPaint1.setColor(colorPicked);
mPaint1.setAntiAlias(true);
mPaint1.setDither(true);
mPaint1.setStyle(Paint.Style.STROKE);
mPaint1.setStrokeJoin(Paint.Join.ROUND);
mPaint1.setStrokeCap(Paint.Cap.ROUND);
// mPaint1.setStrokeWidth(3);
return mPaint1;
}
public void onClickRedo() {
if (undonePaths.size() > 0) {
mMaindialog.add(undonePaths.remove(undonePaths.size() - 1));
mView.invalidate();
} else {
}
// toast the user
}
public void onClickUndo() {
if (mMaindialog.size() > 0) {
undonePaths.add(mView.mMaindialog.remove(mView.mMaindialog
.size() - 1));
mView.invalidate();
}
else {
}
}
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
return false;
}
}// end MyView
@Override
public void colorChanged(int color) {
// TODO Auto-generated method stub
PreferenceManager.getDefaultSharedPreferences(this).edit()
.putInt(COLOR_PREFERENCE_KEY, color).commit();
slll = color;
}
}
公共类主扩展活动实现OnColorChangedListener{
//公共静态int selectedColor=Color.BLACK;
公共静态数组列表mMaindialog;
//私人ArrayList undonePaths;
//公共int-selectedcolor;
私有静态最终字符串COLOR\u PREFERENCE\u KEY=“COLOR”;
私有框架布局相对论;
静态字符串sdpath、位置;
布尔i;
//实例变量
私有位图mBitmap=null;
位图;
私人油漆mPaint、mBitmapPaint、mPaint1;
私人MyView mView;
ImageView-idd;
//专用路径mPath;
int slll=Color.BLACK;
位图映射=ListView5.bMap;
私人按钮ClearPaint、Colorpaint;
幽灵数据库gost;
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
idd=(ImageView)findViewById(R.id.imageView1);
relativelayout=(FrameLayout)findViewById(R.id.FrameLayout);
DisplayMetrics metrics=getBaseContext().getResources()
.getDisplayMetrics();
int w=度量值。宽度像素;
int h=metrics.heightPixels;
系统输出打印项次(“宽度”+w);
系统输出打印长度(“高度”+h);
mView=新的MyView(this,w,h);
mView.setDrawingCacheEnabled(true);
mPaint=新油漆();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(油漆、样式、笔划);
mPaint.setStrokeJoin(油漆.连接.圆形);
mPaint.setStrokeCap(油漆盖圆形);
mPaint.设定行程宽度(4);
ClearPaint=(按钮)findViewById(R.id.ne);
setOnClickListener(新的OnClickListener(){
公共void onClick(视图v){
//mBitmap.橡皮擦颜色(颜色.透明);
//mPath.reset();
//mView.invalidate();
mView.onClickUndo();
}
});
按钮save22=(按钮)findViewById(R.id.save);
save22.setOnClickListener(新的OnClickListener(){
@凌驾
公共void onClick(视图v){
//TODO自动生成的方法存根
文件cacheDir;
Toast.makeText(Main.this,“Photo”,500.show();
位图图标;
relativelayout.setDrawingCacheEnabled(真);
icon=Bitmap.createBitmap(relativelayout.getDrawingCache());
位图=图标;
relativelayout.setDrawingCacheEnabled(false);
//文件mFile1=Environment.getExternalStorageDirectory();
日期d=新日期();
字符串文件名=d.getTime()+“mg1.jpg”;
文件storagePath=(Environment.getExternalStorageDirectory());
File dest=新文件(storagePath+“/CityAppImages”);
如果(!dest.exists()){
dest.mkdirs();
}
File mFile2=新文件(dest,fileName);
sdpath=mFile2.getAbsolutePath();
Log.d(“qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq;
试一试{
FileOutputStream扩展流;
outStream=新文件OutputStream(mFile2);
压缩(bitmap.CompressFormat.JPEG,100,扩展);
冲水;
exptream.close();
Toast.makeText(Main.this,“照片成功保存”,500)
.show();
}catch(filenotfounde异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
Toast.makeText(Main.this,“照片未成功保存”,
500)show();
}
gost=新的Ghostdatabase(Main.this);
gost.open();
gost.插入标题(sdpath);
}
});
按钮视图=(按钮)findViewById(R.id.listtt);
view.setOnClickListener(新OnCl