生活随笔
收集整理的這篇文章主要介紹了
Android中实现Bitmap在自定义View中的放大与拖动
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一基本實現思路:
基于View類實現自定義View –MyImageView類。在使用View的Activity類中完成OnTouchListener接口,實現對MotionEvent事件的監聽與處理,常見的MotionEvent事件如下:
ACTION_DOWN事件,記錄平移開始點
ACTION_UP事件,結束平移事件處理
ACTION_MOVE事件,記錄平移點,計算與開始點距離,實現Bitmap平移,在多點觸控時候,計算兩點之間的距離,實現圖像放大
ACTION_POINTER_DOWN事件,計算兩點之間的距離,作為初始距離,實現圖像手勢放大時候使用。
ACTION_POINTER_UP事件,結束兩點觸控放大圖像處理
放大與拖動
基于單點觸控實現Bitmap對象在View上的拖動、并且檢測View的邊緣,防止拖動過界。基于兩個點觸控實現Bitmap對象在View上的放大、并且檢測放大倍數。基于Matrix對象實現對Bitmap在View上放大與平移變換,Matrix對象是android中實現圖像幾何變換的矩陣,支持平移、放大、縮小、錯切、旋轉等常見操作。
Bitmap對象在View中的更新與顯示
通過重載onDraw方法,使用canvas實現繪制Bitmap對象、通過view.invalidate()方法實現View的刷新。
MyImageView類的重要方法說明:
initParameters()初始化所有需要用到的參數
setStartPoint()設置圖像平移的開始點坐標
setMovePoint()設置圖像平移的移動點坐標,然后集合開始點位置,計算它們之間的距離,從而得到Bitmap對象需要平移的兩個參數值sx、sy。其中還包括保證圖像不會越過View邊界的檢查代碼。
savePreviousResult()保存當前的平移數據,下次可以繼續在次基礎上平移Bitmap對象。
zoomIn()根據兩個點之間的歐幾里德距離,通過初始距離比較,得到放大比例,實現Bitmap在View對象上的放大
Matrix中關于放大與平移的API
Matrix.postScale方法與Matrix.postTranslate方法可以不改變Bitmap對象本身實現平移與放大。
二:代碼實現
自定義View類使用xml布局如下:
[html]?view plaincopy
<RelativeLayout?xmlns:android="http://schemas.android.com/apk/res/android"?? ????xmlns:tools="http://schemas.android.com/tools"?? ????android:layout_width="match_parent"?? ????android:layout_height="match_parent"?? ????android:paddingBottom="@dimen/activity_vertical_margin"?? ????android:paddingLeft="@dimen/activity_horizontal_margin"?? ????android:paddingRight="@dimen/activity_horizontal_margin"?? ????android:paddingTop="@dimen/activity_vertical_margin"?? ????tools:context=".MainActivity"?>?? ?? ????<com.example.matrixdemo.MyImageView?? ????????android:id="@+id/myView"?? ????????android:layout_width="fill_parent"?? ????????android:layout_height="fill_parent"?? ????????android:text="@string/hello_world"?/>?? ?? </RelativeLayout>??
自定義View實現代碼如下:
[java]?view plaincopy
package?com.example.matrixdemo;?? ?? import?android.content.Context;?? import?android.graphics.Bitmap;?? import?android.graphics.Canvas;?? import?android.graphics.Color;?? import?android.graphics.Matrix;?? import?android.graphics.Paint;?? import?android.graphics.Paint.Style;?? import?android.graphics.Point;?? import?android.graphics.Rect;?? import?android.util.AttributeSet;?? import?android.view.View;?? ?? public?class?MyImageView?extends?View?{?? ????private?Paint?mPaint;?? ????private?Bitmap?bitmap;?? ????private?Matrix?matrix;?? ?????? ?????? ????private?Point?startPoint;?? ????private?Point?movePoint;?? ????private?float?initDistance;?? ?? ?????? ????private?int?sx;?? ????private?int?sy;?? ?????? ?????? ????private?int?oldsx;?? ????private?int?oldsy;?? ?????? ?????? ????private?float?widthRate;?? ????private?float?heightRate;?? ?????? ????public?MyImageView(Context?context)?{?? ????????super(context);?? ????}?? ?????? ????public?MyImageView(Context?context,?AttributeSet?attrs)?{?? ????????super(context,?attrs);?? ????}?? ?????? ????public?void?setBitmap(Bitmap?bitmap)?{?? ????????this.bitmap?=?bitmap;?? ????}?? ?????? ????private?void?initParameters()?{?? ?????????? ????????mPaint?=?new?Paint();?? ????????mPaint.setColor(Color.BLACK);?? ????????matrix?=?new?Matrix();?? ????????if(bitmap?!=?null)?? ????????{?? ????????????float?iw?=?bitmap.getWidth();?? ????????????float?ih?=?bitmap.getHeight();?? ????????????float?width?=?this.getWidth();?? ????????????float?height?=?this.getHeight();?? ?????????????? ????????????widthRate?=?width?/?iw;?? ????????????heightRate?=?height?/?ih;?? ????????}?? ?????????? ????????sx?=?0;?? ????????sy?=?0;?? ?????????? ????????oldsx?=?0;?? ????????oldsy?=?0;?? ?????????? ????}?? ?????? ????public?void?setStartPoint(Point?startPoint)?{?? ????????this.startPoint?=?startPoint;?? ????}?? ?????? ????public?void?setInitDistance(float?initDistance)?{?? ????????this.initDistance?=?initDistance;?? ????}?? ?????? ????public?void?zoomIn(float?distance)?? ????{?? ????????float?rate?=?distance?/?this.initDistance;?? ????????float?iw?=?bitmap.getWidth();?? ????????float?ih?=?bitmap.getHeight();?? ????????float?width?=?this.getWidth();?? ????????float?height?=?this.getHeight();?? ?????????? ????????widthRate?=?(width?/?iw?)?*?rate;?? ????????heightRate?=?(height?/?ih)?*?rate;?? ?????????? ?????????? ????????float?iwr?=?(width?/?iw?);?? ????????float?ihr?=?(height?/?ih);?? ????????if(iwr?>=?widthRate)?? ????????{?? ????????????widthRate?=?(width?/?iw?);?? ????????}?? ????????if(ihr?>=?heightRate)?? ????????{?? ????????????heightRate?=?(height?/?ih);?? ????????}?? ?????????? ?????????? ????????oldsx?=?(int)((width?-?widthRate?*?iw)?/?2);?? ????????oldsy?=?(int)((height?-?heightRate?*?ih)?/?2);?? ????}?? ?? ????public?void?setMovePoint(Point?movePoint)?{?? ????????this.movePoint?=?movePoint;?? ????????sx?=?this.movePoint.x?-?this.startPoint.x;?? ????????sy?=?this.movePoint.y?-?this.startPoint.y;?? ?????????? ????????float?iw?=?bitmap.getWidth();?? ????????float?ih?=?bitmap.getHeight();?? ?????????? ?????????? ????????int?deltax?=?(int)((widthRate?*?iw)?-?this.getWidth());?? ????????int?deltay?=?(int)((heightRate?*?ih)?-?this.getHeight());?? ????????if((sx?+?this.oldsx)?>=?0)?? ????????{?? ????????????this.oldsx?=?0;?? ????????????sx?=?0;?? ????????}?? ????????else?if((sx?+?this.oldsx)?<=?-deltax)?? ????????{?? ????????????this.oldsx?=?-deltax;?? ????????????sx?=?0;?? ????????}?? ?????????? ????????if((sy?+?this.oldsy)?>=?0)?? ????????{?? ????????????this.oldsy?=?0;?? ????????????this.sy?=?0;?? ????????}?? ????????else?if((sy?+?this.oldsy)?<=?-deltay)?? ????????{?? ????????????this.oldsy?=?-deltay;?? ????????????this.sy?=?0;?? ????????}?? ?????????? ????????float?width?=?this.getWidth();?? ?????????? ?????????? ????????float?iwr?=?width?/?iw;?? ????????if(iwr?==?widthRate)?? ????????{?? ????????????sx?=?0;?? ????????????sy?=?0;?? ????????????oldsx?=?0;?? ????????????oldsy?=?0;?? ????????}?? ????}?? ?????? ????public?void?savePreviousResult()?? ????{?? ????????this.oldsx?=?this.sx?+?this.oldsx;?? ????????this.oldsy?=?this.sy?+?this.oldsy;?? ?????????? ?????????? ????????sx?=?0;?? ????????sy?=?0;?? ????}?? ?? ????@Override?? ????protected?void?onDraw(Canvas?canvas)?{?? ????????if(matrix?==?null)?? ????????{?? ????????????initParameters();?? ????????}?? ????????if(bitmap?!=?null)?? ????????{?? ????????????matrix.reset();?? ????????????matrix.postScale(widthRate,?heightRate);?? ????????????matrix.postTranslate(oldsx+sx,?oldsy?+?sy);?? ????????????canvas.drawBitmap(bitmap,?matrix,?mPaint);?? ????????}?? ????????else?? ????????{?? ?????????????? ????????????Rect?rect?=?new?Rect(0,?0,?getWidth(),?getHeight());?? ????????????mPaint.setAntiAlias(true);?? ????????????mPaint.setColor(Color.BLACK);?? ????????????mPaint.setStyle(Style.FILL_AND_STROKE);?? ????????????canvas.drawRect(rect,?mPaint);?? ????????}?? ????}?? }??
Activity類中實現對View的OnTouchListener監聽與MotionEvent事件處理的代碼如下:
[java]?view plaincopy
package?com.example.matrixdemo;?? ?? import?android.app.Activity;?? import?android.graphics.Bitmap;?? import?android.graphics.BitmapFactory;?? import?android.graphics.Point;?? import?android.os.Bundle;?? import?android.util.Log;?? import?android.view.Menu;?? import?android.view.MotionEvent;?? import?android.view.View;?? import?android.view.View.OnTouchListener;?? ?? public?class?MainActivity?extends?Activity?implements?OnTouchListener?{?? ?? ????public?static?final?int?SCALE_MODE?=?4;?? ????public?static?final?int?TRANSLATION_MODE?=?2;?? ????public?static?final?int?NULL_MODE?=?1;?? ????private?MyImageView?myView;?? ????private?int?mode;?? ?? ????@Override?? ????protected?void?onCreate(Bundle?savedInstanceState)?{?? ????????super.onCreate(savedInstanceState);?? ????????setContentView(R.layout.activity_main);?? ????????startMyImageView();?? ????}?? ?? ????private?void?startMyImageView()?{?? ????????myView?=?(MyImageView)?this.findViewById(R.id.myView);?? ????????Bitmap?bitmap?=?BitmapFactory.decodeResource(this.getResources(),?? ????????????????R.drawable.flower_001);?? ????????myView.setBitmap(bitmap);?? ????????myView.setOnTouchListener(this);?? ????????myView.invalidate();?? ????}?? ?? ????@Override?? ????public?boolean?onCreateOptionsMenu(Menu?menu)?{?? ????????getMenuInflater().inflate(R.menu.main,?menu);?? ????????return?true;?? ????}?? ?? ????@Override?? ????public?boolean?onTouch(View?view,?MotionEvent?event)?{?? ????????Log.i("touch?event","touch?x?=?"?+?event.getX());?? ????????switch?(MotionEvent.ACTION_MASK?&?event.getAction())??? ????????{?? ????????????case?MotionEvent.ACTION_DOWN:?? ????????????????mode?=?TRANSLATION_MODE;?? ????????????????myView.setStartPoint(new?Point((int)event.getX(),?(int)event.getY()));?? ????????????????break;?? ????????????case?MotionEvent.ACTION_POINTER_UP:?? ????????????case?MotionEvent.ACTION_OUTSIDE:?? ????????????case?MotionEvent.ACTION_UP:?? ????????????????mode?=?NULL_MODE;?? ????????????????myView.savePreviousResult();?? ????????????????break;?? ????????????case?MotionEvent.ACTION_POINTER_DOWN:?? ????????????????mode?=?SCALE_MODE;?? ????????????????myView.setInitDistance(calculateDistance(event));?? ????????????????break;?? ????????????case?MotionEvent.ACTION_MOVE:?? ????????????????if(mode?==?SCALE_MODE)?? ????????????????{?? ????????????????????float?dis?=?calculateDistance(event);?? ????????????????????myView.zoomIn(dis);?? ????????????????}?? ????????????????else?if(mode?==?TRANSLATION_MODE)?? ????????????????{?? ????????????????????myView.setMovePoint(new?Point((int)event.getX(),?(int)event.getY()));?? ????????????????}?? ????????????????else?? ????????????????{?? ????????????????????Log.i("unknow?mode?tag","do?nothing......");?? ????????????????}?? ????????????????break;?? ????????}?? ????????myView.invalidate();?? ????????return?true;?? ????}?? ?? ????private?float?calculateDistance(MotionEvent?event)?{?? ????????float?dx?=?event.getX(0)?-?event.getX(1);?? ????????float?dy?=?event.getY(0)??-?event.getY(1);?? ????????float?distance?=?(float)Math.sqrt(dx*dx?+?dy*dy);?? ????????return?distance;?? ????}?? ?? }??
三:運行效果如下
總結
以上是生活随笔為你收集整理的Android中实现Bitmap在自定义View中的放大与拖动的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。