日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android中实现Bitmap在自定义View中的放大与拖动

發布時間:2025/6/15 Android 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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;??
  • ??????
  • ????//?scale?rate??
  • ????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();??
  • ????????//?get?scale?rate??
  • ????????widthRate?=?(width?/?iw?)?*?rate;??
  • ????????heightRate?=?(height?/?ih)?*?rate;??
  • ??????????
  • ????????//?make?it?same?as?view?size??
  • ????????float?iwr?=?(width?/?iw?);??
  • ????????float?ihr?=?(height?/?ih);??
  • ????????if(iwr?>=?widthRate)??
  • ????????{??
  • ????????????widthRate?=?(width?/?iw?);??
  • ????????}??
  • ????????if(ihr?>=?heightRate)??
  • ????????{??
  • ????????????heightRate?=?(height?/?ih);??
  • ????????}??
  • ??????????
  • ????????//?go?to?center??
  • ????????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;??
  • ??????????
  • ????????//?zero??
  • ????????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??
  • ????????{??
  • ????????????//?fill?rect??
  • ????????????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中的放大与拖动的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。