在Android中绘制图片 [英] Draw on Picture in android
问题描述
我正在一个自定义的imageview可以绘制线条,问题是绘图区域大小不完全与位图大小。
例如,在其他应用程序中,它如下所示:
但是,在我的应用程序中,
>
这是我的程序,这似乎位图不适合画布。感谢您的帮助
public class DrawingView extends View {
//绘制路径
private路径drawPath;
//绘画和画布油画
private Paint drawPaint,canvasPaint;
//初始颜色
private int paintColor = 0xFF660000;
// canvas
private Canvas drawCanvas;
// canvas bitmap
private Bitmap canvasBitmap;
public DrawingView(Context context,AttributeSet attrs){
super(context,attrs);
setupDrawing();
}
//设置绘图
private void setupDrawing(){
//准备绘制和设置绘图笔画属性
drawPath = new Path();
drawPaint = new Paint();
drawPaint.setColor(paintColor);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(15.0f);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
//分配给查看的大小
@Override
protected void onSizeChanged(int w,int h,int oldw,int oldh){
super.onSizeChanged(w,h,oldw,oldh);
canvasBitmap = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
}
//绘制视图 - 将在触摸事件后调用
@Override
protected void onDraw(Canvas canvas){
canvas.drawBitmap (BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher),0,0,canvasPaint);
canvas.drawBitmap(canvasBitmap,0,0,canvasPaint);
canvas.drawPath(drawPath,drawPaint);
}
//注册用户触动作为绘图操作
@Override
public boolean onTouchEvent(MotionEvent event){
float touchX = event.getX );
float touchY = event.getY();
//响应down,move和up事件
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
drawPath.moveTo(touchX,touchY);
break;
case MotionEvent.ACTION_MOVE:
drawPath.lineTo(touchX,touchY);
break;
case MotionEvent.ACTION_UP:
drawPath.lineTo(touchX,touchY);
drawCanvas.drawPath(drawPath,drawPaint);
drawPath.reset();
break;
默认值:
return false;
}
// redraw
invalidate();
return true;
}
//更新颜色
public void setColor(String newColor){
invalidate();
paintColor = Color.parseColor(newColor);
drawPaint.setColor(paintColor);
}
//开始新绘图
public void startNew(){
drawCanvas.drawColor(0,PorterDuff.Mode.CLEAR);
invalidate();
}
}
我发现了类似的教程代码,问题是触摸事件有错误,它计数在操作栏和其余的UI元素,所以触摸是奇怪的。建议查看
http://www.java2s.com/Code/Android/2D-Graphics/DrawonPictureandsave.htm
所以,这个目标主题,是
的解决方案1)可绘图像
能够(可以使用库)(当有效缩放,缩放,非活动缩放,绘制时)
可以参考截图1的想法
感谢您的帮助
您可以避免计算样本中其他UI项目的坐标创建自己的ImageView。试试此代码 Activity
:
public class DrawOnBitmapActivity extends Activity implements OnClickListener
{
DrawableImageView choosenImageView;
按钮choosePicture;
button savePicture;
位图bmp;
Bitmap alteredBitmap;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
choosenImageView =(DrawableImageView)this.findViewById(R.id.ChoosenImageView);
choosePicture =(Button)this.findViewById(R.id.ChoosePictureButton);
savePicture =(Button)this.findViewById(R.id.SavePictureButton);
savePicture.setOnClickListener(this);
choosePicture.setOnClickListener(this);
}
public void onClick(View v)
{
if(v == choosePicture)
{
Intent choosePictureIntent = new Intent (
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(choosePictureIntent,0);
}
else if(v == savePicture)
{
if(alteredBitmap!= null)
{
ContentValues contentValues = new ContentValues ;
contentValues.put(Media.DISPLAY_NAME,Draw On Me);
Uri imageFileUri = getContentResolver()。insert(
Media.EXTERNAL_CONTENT_URI,contentValues);
try {
OutputStream imageFileOS = getContentResolver()
.openOutputStream(imageFileUri);
alteredBitmap
.compress(CompressFormat.JPEG,90,imageFileOS);
Toast t = Toast
.makeText(this,Saved!,Toast.LENGTH_SHORT);
t.show();
} catch(Exception e){
Log.v(EXCEPTION,e.getMessage());
}
}
}
}
protected void onActivityResult(int requestCode,int resultCode,
Intent intent){
super.onActivityResult(requestCode,resultCode,intent);
if(resultCode == RESULT_OK){
Uri imageFileUri = intent.getData();
try {
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
bmp = BitmapFactory
.decodeStream(
getContentResolver()。OpenInputStream(
imageFileUri),null,bmpFactoryOptions);
bmpFactoryOptions.inJustDecodeBounds = false;
bmp = BitmapFactory
.decodeStream(
getContentResolver()。openInputStream(
imageFileUri),null,bmpFactoryOptions);
alteredBitmap = Bitmap.createBitmap(bmp.getWidth(),
bmp.getHeight(),bmp.getConfig());
choosenImageView.setNewImage(alteredBitmap,bmp);
}
catch(Exception e){
Log.v(ERROR,e.toString());
}
}
}
}
必须稍微更改 activity_main
布局:
<?xml version = 1.0encoding =utf-8?
< LinearLayout xmlns:android =http://schemas.android.com/apk/res/android
android:orientation =vertical
android:layout_width =fill_parent
android:layout_height =fill_parent
>
< Button
android:layout_width =fill_parent
android:layout_height =wrap_content
android:text =Choose Pictureandroid:id =@ + id / ChoosePictureButton/>
< ru.pristalovpavel.drawonimage.DrawableImageView android:layout_width =wrap_content
android:layout_height =wrap_content
android:id =@ + id / ChoosenImageView>
< /ru.pristalovpavel.drawonimage.DrawableImageView>
< Button
android:layout_width =fill_parent
android:layout_height =wrap_content
android:text =Save Pictureandroid:id =@ + id / SavePictureButton/>
< / LinearLayout>
和您的自定义 ImageView
:
public class DrawableImageView extends ImageView implements OnTouchListener
{
float downx = 0;
float downy = 0;
float upx = 0;
float upy = 0;
画布
油漆;
矩阵;
public DrawableImageView(Context context)
{
super(context);
setOnTouchListener(this);
}
public DrawableImageView(Context context,AttributeSet attrs)
{
super(context,attrs);
setOnTouchListener(this);
}
public DrawableImageView(Context context,AttributeSet attrs,
int defStyleAttr)
{
super(context,attrs,defStyleAttr);
setOnTouchListener(this);
}
public void setNewImage(Bitmap alteredBitmap,Bitmap bmp)
{
canvas = new Canvas(alteredBitmap);
paint = new Paint();
paint.setColor(Color.GREEN);
paint.setStrokeWidth(5);
matrix = new Matrix();
canvas.drawBitmap(bmp,matrix,paint);
setImageBitmap(alteredBitmap);
}
@Override
public boolean onTouch(View v,MotionEvent event)
{
int action = event.getAction();
switch(action)
{
case MotionEvent.ACTION_DOWN:
downx = getPointerCoords(event)[0]; // event.getX
downy = getPointerCoords(event)[1]; // event.getY();
break;
case MotionEvent.ACTION_MOVE:
upx = getPointerCoords(event)[0]; // event.getX()
upy = getPointerCoords(event)[1]; // event.getY();
canvas.drawLine(downx,downy,upx,upy,paint);
invalidate();
downx = upx;
downy = upy;
break;
case MotionEvent.ACTION_UP:
upx = getPointerCoords(event)[0]; // event.getX();
upy = getPointerCoords(event)[1]; // event.getY();
canvas.drawLine(downx,downy,upx,upy,paint);
invalidate();
break;
case MotionEvent.ACTION_CANCEL:
break;
默认值:
break;
}
return true;
}
final float [] getPointerCoords(MotionEvent e)
{
final int index = e.getActionIndex();
final float [] coords = new float [] {e.getX(index),e.getY(index)};
Matrix matrix = new Matrix();
getImageMatrix()。invert(matrix);
matrix.postTranslate(getScrollX(),getScrollY());
matrix.mapPoints(coords);
return coords;
}
}
eclipse中项目的所有源代码:链接
UPDATE:
新的源代码 DrawableImageView
!
详情请参阅我的博客。
I was working on a custom imageview that can draw line on it, the problem is that the drawing area size is not exactly with the bitmap size.
For example, in the other app, it looks like:
However, in my app, it looks like
Here is my program, which seems the bitmap is not fit with the canvas. Thanks for helping
public class DrawingView extends View {
//drawing path
private Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor = 0xFF660000;
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap canvasBitmap;
public DrawingView(Context context, AttributeSet attrs){
super(context, attrs);
setupDrawing();
}
//setup drawing
private void setupDrawing(){
//prepare for drawing and setup paint stroke properties
drawPath = new Path();
drawPaint = new Paint();
drawPaint.setColor(paintColor);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(15.0f);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
//size assigned to view
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
}
//draw the view - will be called after touch event
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher), 0, 0, canvasPaint);
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
//register user touches as drawing action
@Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
//respond to down, move and up events
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawPath.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
drawPath.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
drawPath.lineTo(touchX, touchY);
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
break;
default:
return false;
}
//redraw
invalidate();
return true;
}
//update color
public void setColor(String newColor){
invalidate();
paintColor = Color.parseColor(newColor);
drawPaint.setColor(paintColor);
}
//start new drawing
public void startNew(){
drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
}
}
And I found the similar tutorial code, the problem is that the touch event has bug, it count in the action bar and the rest UI element so the touching is weird. Recommend to have a look
http://www.java2s.com/Code/Android/2D-Graphics/DrawonPictureandsave.htm
So, the goal of this topic , is the solution of
1) draw-able image
2) zoom-able and pan-able(can use library) (when active zoom , zoom, when inactive zoom , draw)
can reference the screenshot 1 for the idea
Thanks a lot for helping
You can avoid counting coordinates of other UI items in your sample by creation your own ImageView. Try this code for Activity
:
public class DrawOnBitmapActivity extends Activity implements OnClickListener
{
DrawableImageView choosenImageView;
Button choosePicture;
Button savePicture;
Bitmap bmp;
Bitmap alteredBitmap;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
choosenImageView = (DrawableImageView) this.findViewById(R.id.ChoosenImageView);
choosePicture = (Button) this.findViewById(R.id.ChoosePictureButton);
savePicture = (Button) this.findViewById(R.id.SavePictureButton);
savePicture.setOnClickListener(this);
choosePicture.setOnClickListener(this);
}
public void onClick(View v)
{
if (v == choosePicture)
{
Intent choosePictureIntent = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(choosePictureIntent, 0);
}
else if (v == savePicture)
{
if (alteredBitmap != null)
{
ContentValues contentValues = new ContentValues(3);
contentValues.put(Media.DISPLAY_NAME, "Draw On Me");
Uri imageFileUri = getContentResolver().insert(
Media.EXTERNAL_CONTENT_URI, contentValues);
try {
OutputStream imageFileOS = getContentResolver()
.openOutputStream(imageFileUri);
alteredBitmap
.compress(CompressFormat.JPEG, 90, imageFileOS);
Toast t = Toast
.makeText(this, "Saved!", Toast.LENGTH_SHORT);
t.show();
} catch (Exception e) {
Log.v("EXCEPTION", e.getMessage());
}
}
}
}
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (resultCode == RESULT_OK) {
Uri imageFileUri = intent.getData();
try {
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
bmp = BitmapFactory
.decodeStream(
getContentResolver().openInputStream(
imageFileUri), null, bmpFactoryOptions);
bmpFactoryOptions.inJustDecodeBounds = false;
bmp = BitmapFactory
.decodeStream(
getContentResolver().openInputStream(
imageFileUri), null, bmpFactoryOptions);
alteredBitmap = Bitmap.createBitmap(bmp.getWidth(),
bmp.getHeight(), bmp.getConfig());
choosenImageView.setNewImage(alteredBitmap, bmp);
}
catch (Exception e) {
Log.v("ERROR", e.toString());
}
}
}
}
You have to change activity_main
layout slightly:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Choose Picture" android:id="@+id/ChoosePictureButton"/>
<ru.pristalovpavel.drawonimage.DrawableImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/ChoosenImageView">
</ru.pristalovpavel.drawonimage.DrawableImageView>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Save Picture" android:id="@+id/SavePictureButton"/>
</LinearLayout>
and your custom ImageView
:
public class DrawableImageView extends ImageView implements OnTouchListener
{
float downx = 0;
float downy = 0;
float upx = 0;
float upy = 0;
Canvas canvas;
Paint paint;
Matrix matrix;
public DrawableImageView(Context context)
{
super(context);
setOnTouchListener(this);
}
public DrawableImageView(Context context, AttributeSet attrs)
{
super(context, attrs);
setOnTouchListener(this);
}
public DrawableImageView(Context context, AttributeSet attrs,
int defStyleAttr)
{
super(context, attrs, defStyleAttr);
setOnTouchListener(this);
}
public void setNewImage(Bitmap alteredBitmap, Bitmap bmp)
{
canvas = new Canvas(alteredBitmap );
paint = new Paint();
paint.setColor(Color.GREEN);
paint.setStrokeWidth(5);
matrix = new Matrix();
canvas.drawBitmap(bmp, matrix, paint);
setImageBitmap(alteredBitmap);
}
@Override
public boolean onTouch(View v, MotionEvent event)
{
int action = event.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
downx = getPointerCoords(event)[0];//event.getX();
downy = getPointerCoords(event)[1];//event.getY();
break;
case MotionEvent.ACTION_MOVE:
upx = getPointerCoords(event)[0];//event.getX();
upy = getPointerCoords(event)[1];//event.getY();
canvas.drawLine(downx, downy, upx, upy, paint);
invalidate();
downx = upx;
downy = upy;
break;
case MotionEvent.ACTION_UP:
upx = getPointerCoords(event)[0];//event.getX();
upy = getPointerCoords(event)[1];//event.getY();
canvas.drawLine(downx, downy, upx, upy, paint);
invalidate();
break;
case MotionEvent.ACTION_CANCEL:
break;
default:
break;
}
return true;
}
final float[] getPointerCoords(MotionEvent e)
{
final int index = e.getActionIndex();
final float[] coords = new float[] { e.getX(index), e.getY(index) };
Matrix matrix = new Matrix();
getImageMatrix().invert(matrix);
matrix.postTranslate(getScrollX(), getScrollY());
matrix.mapPoints(coords);
return coords;
}
}
All source code of the project in eclipse: link
UPDATE:
new source code for DrawableImageView
!
More information is in my blog.
这篇关于在Android中绘制图片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!