4.2.2 在现有图像上绘制
由于是在Canvas对象上绘制,因此可以使用第三章中描述的技术,在Canvas对象上绘制 一幅图像,然后在该图像上进行绘制。
下列介绍一个完整的示例。
1 package com.nthm.androidtest; 2 3 import android.app.Activity; 4 import android.content.Intent; 5 import android.graphics.Bitmap; 6 import android.graphics.BitmapFactory; 7 import android.graphics.Canvas; 8 import android.graphics.Color; 9 import android.graphics.Matrix; 10 import android.graphics.Paint; 11 import android.net.Uri; 12 import android.os.Bundle; 13 import android.view.Display; 14 import android.view.MotionEvent; 15 import android.view.View; 16 import android.view.View.OnClickListener; 17 import android.view.View.OnTouchListener; 18 import android.widget.Button; 19 import android.widget.ImageView;
活动将实现OnClickListener和OnTouchListener。OnClickListener使得活动可以响应按钮的单击事件;而OnTouchListener使得我们可以使用触摸屏在ImageView上绘制。
1 public class ChoosePictureDraw extends Activity implements OnTouchListener, 2 OnClickListener {
有两个主要的UI元素。第一个是ImageView,他会显示将要在其上进行绘制的位图对象。第二个是一个按钮,用户可以按下它以从Gallery应用程序中选择图像。
1 private ImageView chooseImageView; 2 private Button choosePicture;
需要有两个位图对象。第一个包含了选定图像的缩放版本,第二个是可变的版本。首先将第一个位图对象绘制到第二个位图对象中,然后在其上方绘制。
1 private Bitmap bmp; 2 private Bitmap alteredBitmap; 3 private Canvas canvas; 4 private Paint paint; 5 private Matrix matrix; 6 @Override 7 protected void onCreate(Bundle savedInstanceState) { 8 super.onCreate(savedInstanceState); 9 setContentView(R.layout.choosepicturedraw); 10 chooseImageView=(ImageView) findViewById(R.id.ChooseImageView); 11 choosePicture=(Button) findViewById(R.id.ChoosePictureButton);
在获得ImageView和按钮的引用之后,将每个事件(OnClick和OnTouch)的监听器设置为活动。
1 choosePicture.setOnClickListener(this); 2 chooseImageView.setOnTouchListener(this); 3 }
onClick方法如下所示。它使用标准的意图,允许用户从Gallery应用程序中选择一幅图像。
1 @Override 2 public void onClick(View v) { 3 Intent choosePictureIntent=new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 4 startActivityForResult(choosePictureIntent, 0); 5 }
在用户选择图像之后调用onActivityResult方法。它将选择的图像加载到一个位图对象中,并将其缩放至屏幕大小。
1 @Override 2 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 3 super.onActivityResult(requestCode, resultCode, data); 4 if(resultCode==RESULT_OK){ 5 Uri imageFileUri=data.getData(); 6 Display currentDisplay=getWindowManager().getDefaultDisplay(); 7 int dw=currentDisplay.getWidth(); 8 int dh=currentDisplay.getHeight(); 9 try{ 10 BitmapFactory.Options bmpBitmapFactoryOptions=new BitmapFactory.Options(); 11 bmpBitmapFactoryOptions.inJustDecodeBounds=true; 12 bmp=BitmapFactory.decodeStream(getContentResolver().openInputStream(imageFileUri), null, bmpBitmapFactoryOptions); 13 int heightRatio=bmpBitmapFactoryOptions.outHeight; 14 int widthRatio=bmpBitmapFactoryOptions.outWidth; 15 if(heightRatio>1&&widthRatio>1){ 16 if(heightRatio>widthRatio){ 17 bmpBitmapFactoryOptions.inSampleSize=heightRatio; 18 }else{ 19 bmpBitmapFactoryOptions.inSampleSize=widthRatio; 20 } 21 } 22 bmpBitmapFactoryOptions.inJustDecodeBounds=false; 23 bmp=BitmapFactory.decodeStream(getContentResolver().openInputStream(imageFileUri), null, bmpBitmapFactoryOptions);
在加载位图对象之后,创建一个可变的位图对象alteredBitmap,并在其中绘制第一个位图对象。
1 alteredBitmap=Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig()); 2 canvas=new Canvas(alteredBitmap); 3 paint=new Paint(); 4 paint.setColor(Color.GREEN); 5 paint.setStrokeWidth(5); 6 matrix=new Matrix(); 7 canvas.drawBitmap(bmp, matrix, paint); 8 chooseImageView.setImageBitmap(alteredBitmap); 9 chooseImageView.setOnTouchListener(this); 10 }catch(Exception e){ 11 12 } 13 } 14 }
现在只是采用之前的相同方式实现onTouch方法。不同于在空白的位图Canvas对象上绘制,现在是在一幅现有的图像上面进行绘制。
1 private float downx=0; 2 private float downy=0; 3 private float upx=0; 4 private float upy=0; 5 @Override 6 public boolean onTouch(View v, MotionEvent event) { 7 switch (event.getAction()) { 8 case MotionEvent.ACTION_DOWN: 9 downx=event.getX(); 10 downy=event.getY(); 11 break; 12 case MotionEvent.ACTION_MOVE: 13 upx=event.getX(); 14 upy=event.getY(); 15 canvas.drawLine(downx, downy, upx, upy, paint); 16 chooseImageView.invalidate(); 17 downx=upx; 18 downy=upy; 19 break; 20 case MotionEvent.ACTION_UP: 21 upx=event.getX(); 22 upy=event.getY(); 23 canvas.drawLine(downx, downy, upx, upy, paint); 24 chooseImageView.invalidate(); 25 break; 26 case MotionEvent.ACTION_CANCEL: 27 28 break; 29 default: 30 break; 31 } 32 return true; 33 } 34 35 }
下面是用于上述活动的布局XML文件。它在一个标准的LinearLayout中指定这个ImageView和按钮。
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="match_parent" 3 android:layout_height="match_parent" 4 android:orientation="vertical" 5 > 6 <Button 7 android:id="@+id/ChoosePictureButton" 8 android:layout_width="fill_parent" 9 android:layout_height="wrap_content" 10 android:text="Choose Picture"/> 11 <ImageView 12 android:id="@+id/ChooseImageView" 13 android:layout_width="wrap_content" 14 android:layout_height="wrap_content" 15 android:contentDescription="@string/app_name"/> 16 </LinearLayout>
posted on 2014-08-26 16:17 宁静致远,一览众山小 阅读(367) 评论(0) 编辑 收藏 举报