先說下我要解決的問題,如圖,界面上的小圖片可以隨意拖動,背景的大圖片能夠放大(超過屏幕)也能夠隨意拖動,我如今要作的是將小圖片的位置記錄下來,放大大圖片裏造成一張新的圖片並且要保證兩張圖片的相對位置和大小保持不變,花點時間實現這個效果:html
1.背景圖片的放大可拖動我使用的是Google提供的PhototView開源包,就在再這裏展現了;android
2.小圖片的隨意拖動,這個相信對你們來講都不是大問題,我附上本身寫的,參考下:canvas
package com.example.androidhtmldemo; import android.app.Activity; import android.util.DisplayMetrics; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; /** * View隨手勢在屏幕上移動 * @author Administrator * */ public class OnViewMoveTouchListener implements OnTouchListener { private View imgView; private int lastX,lastY; private int left,right,top,bottom; private DisplayMetrics dm; public OnViewMoveTouchListener(View v,Activity context) { this.imgView = v; dm = context.getResources().getDisplayMetrics();; } @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastX = (int) event.getRawX(); lastY = (int) event.getRawY(); break; case MotionEvent.ACTION_MOVE: int dx = (int) (event.getRawX() - lastX); int dy = (int) (event.getRawY() - lastY); left = v.getLeft() + dx; right = v.getRight() + dx; top = v.getTop() + dy; bottom = v.getBottom() + dy; if (left < 0) { left = 0; right = left + v.getWidth(); } if (right > dm.widthPixels) { right = dm.widthPixels; left = dm.widthPixels - v.getWidth(); } if (top < 0) { top = 0; bottom = dm.heightPixels + v.getHeight(); } if (bottom > dm.heightPixels) { bottom = dm.heightPixels; top = dm.heightPixels - v.getHeight(); } imgView.layout(left, top, right, bottom); lastX = (int) event.getRawX(); lastY = (int) event.getRawY(); break; case MotionEvent.ACTION_UP: break; } return true; } }
3.相關方法:app
①RectF mRect = mPhotoView.getDisplayRect(); 這裏獲取的是圖片佔據的矩形,能夠獲取矩形四個角的座標,固然獲取的值是相對於咱們應用在屏幕上佔據的空間若是超出屏幕會獲取負值ide
②mCanvas.drawBitmap(bitmap, left, top, paint); bitmap:要在畫布上繪製的圖片,left:在畫布上繪製圖片X起點;Top:在畫布上繪製圖片的Y起點;paint畫筆,能夠爲null;佈局
③ mCanvas.drawBitmap(bitmap, src, dst, paint);bitmap:在要畫布上繪製的Bitmap,src:bitmap在畫布上佔據的矩形,dst:這個是Bitmap在畫布上佔據的矩形和位置,我解釋的可能不太清楚(簡單的說:src就是說明這個Bitmap須要多大的空間,固然若是這個空間小於位圖的尺寸,位圖只會顯示一部分,具體顯示哪一部分能夠調整這個Rect來獲取;dst:這個標示要把Bitmap繪製在畫布上的哪一個位置),能夠參考下下面代碼:this
Rect mSrcRect = new Rect(0, 0, dpDrawable.getWidth(), dpDrawable.getHeight()); Rect mDstRect = new Rect((int)x, (int)y, (int)(x + width), (int)(y + height));
4.相關代碼:spa
package com.example.androidhtmldemo; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Rect; import android.util.Log; public class DrawBpOnBpUtils { private Context context; private Bitmap bgDrawable, dpDrawable; private int bgDrawableId,dpDrawableId; /** * * @param context 上下文環境 * @param bgDrawableId 背景圖片 * @param dpDrawableId 印章 */ public DrawBpOnBpUtils(Context context, int bgDrawableId, int dpDrawableId) { this.context = context; this.bgDrawableId = bgDrawableId; this.dpDrawableId = dpDrawableId; } /**
*畫布上能分配給Bitmap的空間是有限的,爲了讓圖片所有顯示就對圖片作適當的壓縮 * @param drawableId * @param scale 圖片相對比例 * @return */ private Bitmap getBitmapByBitmap(int drawableId,float width,float height) { int simpleSize = 1 ; BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(context.getResources(), drawableId,options); while ((options.outWidth / simpleSize > width) || (options.outHeight / simpleSize > height)) { simpleSize *= 2; } options.inJustDecodeBounds = false; options.inSampleSize = simpleSize; return BitmapFactory.decodeResource(context.getResources(), drawableId); } /** * 繪製圖片 * @param scale 兩張Bitmap相對比例 * @param x dpDrawable在canvas的 left * @param y dpDrawable在canvase的 top * @return */ public Bitmap onDrawBitmap(float width,float height,float x,float y){ bgDrawable = BitmapFactory.decodeResource(context.getResources(), bgDrawableId); dpDrawable = getBitmapByBitmap(dpDrawableId, width,height); Bitmap result = Bitmap.createBitmap(bgDrawable.getWidth(), bgDrawable.getHeight(), Config.ARGB_8888); Rect mSrcRect = new Rect(0, 0, dpDrawable.getWidth(), dpDrawable.getHeight()); Rect mDesRect = new Rect((int)x, (int)y, (int)(x + width), (int)(y + height)); Canvas mCanvas = new Canvas(result); mCanvas.drawBitmap(bgDrawable, 0, 0, null); mCanvas.drawBitmap(dpDrawable, mSrcRect, mDesRect, null); Log.e(getClass().getName(), "x:" + x + ";y:" + y + ";top:" + (x + dpDrawable.getWidth()) + "right:" + (y + dpDrawable.getHeight())); bgDrawable.recycle(); dpDrawable.recycle(); bgDrawable = null; dpDrawable = null; return result; } }
package com.example.androidhtmldemo; import uk.co.senab.photoview.PhotoView; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.RectF; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.Button; import com.example.androidhtmldemo.OnViewMoveTouchListener.OnViewMoveRsultCallback; public class ShowPhotoActivity extends Activity{ private PhotoView mPhotoView; private PhotoView imgSeal; private Button btnTakePhoto; private Bitmap newBitmap; private float newLeft = 0; private float newTop = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_showphoto); mPhotoView = (PhotoView) findViewById(R.id.photoView1); imgSeal = (PhotoView) findViewById(R.id.imgPutSeal); btnTakePhoto = (Button) findViewById(R.id.btnTakePhoto); OnViewMoveTouchListener onTouchListener = new OnViewMoveTouchListener(imgSeal, this);
//imgSeal是能夠隨意拖動的,嘗試獲取他的座標結果都不太滿意,只好作一個回調讓結果返回到這裏(汗顏) onTouchListener.setOnViewMoveRsultCallback(new OnViewMoveRsultCallback() { @Override public void onViewMoveResultCallback(float left, float top, float right, float bottom) { newLeft = left; newTop = top; } }); imgSeal.setOnTouchListener(onTouchListener); imgSeal.setDrawingCacheEnabled(true); btnTakePhoto.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { drawBitmap(newLeft,newTop); } }); } /** * * @param left 印章 left * @param top 印章 Top */ private void drawBitmap(float left,float top){ if(newBitmap != null){ newBitmap.recycle(); newBitmap = null; } Log.e(getPackageName(), "newLeft:" + newLeft + ";newTop:" + newTop); RectF mRect = mPhotoView.getDisplayRect(); float x = left; float y = top; if(mRect.left < 0){ x += Math.abs(mRect.left); } if(mRect.top < 0){ y += Math.abs(mRect.top); } if(mRect.left > 0){ x -= mRect.left; } if(mRect.top > 0){ y -= mRect.top; } BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = false; Bitmap bp = BitmapFactory.decodeResource(getResources(), R.drawable.img_test,options); float scale = bp.getWidth() / mRect.width(); //原圖的寬與有效區域寬的比值 bp.recycle(); bp = null; newBitmap = new DrawBpOnBpUtils(this, R.drawable.img_test, R.drawable.images) .onDrawBitmap(imgSeal.getWidth() * scale,imgSeal.getHeight() * scale, x * scale,y * scale); mPhotoView.setImageBitmap(newBitmap); } }
附上佈局:code
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <uk.co.senab.photoview.PhotoView android:id="@+id/photoView1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center_horizontal" android:adjustViewBounds="true" android:src="@drawable/img_test" /> <uk.co.senab.photoview.PhotoView android:id="@+id/imgPutSeal" android:layout_width="48dp" android:layout_height="48dp" android:adjustViewBounds="true" android:src="@drawable/images" /> <Button android:id="@+id/btnTakePhoto" android:layout_width="96dp" android:layout_height="48dp" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:text="快照" /> </RelativeLayout>
還要須要改進的地方:①imgSeal的大小能夠隨着mPhotoView的大小和位置而改變②以後生成新圖片應該根據背景圖片的大小和位置來顯示,歡迎你們交流xml