Android中實(shí)現(xiàn)Bitmap在自定義View中的放大與拖動(dòng)
站在用戶的角度思考問(wèn)題,與客戶深入溝通,找到黑龍江網(wǎng)站設(shè)計(jì)與黑龍江網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類(lèi)型包括:網(wǎng)站建設(shè)、成都網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊(cè)、網(wǎng)頁(yè)空間、企業(yè)郵箱。業(yè)務(wù)覆蓋黑龍江地區(qū)。
一:基本實(shí)現(xiàn)思路
基于View類(lèi)實(shí)現(xiàn)自定義View –MyImageView類(lèi)。在使用View的Activity類(lèi)中完成OnTouchListener接口,實(shí)現(xiàn)對(duì)自定義View的觸摸事件監(jiān)聽(tīng)
放大與拖動(dòng)
基于單點(diǎn)觸控實(shí)現(xiàn)Bitmap對(duì)象在View上的拖動(dòng)、并且檢測(cè)View的邊緣,防止拖動(dòng)過(guò)界。基于兩個(gè)點(diǎn)觸控實(shí)現(xiàn)Bitmap對(duì)象在View上的放大、并且檢測(cè)放大倍數(shù)?;贛atrix對(duì)象實(shí)現(xiàn)對(duì)Bitmap在View上放大與平移變換
Bitmap對(duì)象在View中的更新與顯示
通過(guò)重載onDraw方法,使用canvas實(shí)現(xiàn)繪制Bitmap對(duì)象、通過(guò)view.invalidate()方法實(shí)現(xiàn)View的刷新。
MyImageView類(lèi)的重要方法說(shuō)明:
initParameters()初始化所有需要用到的參數(shù)
setStartPoint()設(shè)置圖像平移的開(kāi)始點(diǎn)坐標(biāo)
setMovePoint()設(shè)置圖像平移的移動(dòng)點(diǎn)坐標(biāo),然后集合開(kāi)始點(diǎn)位置,計(jì)算它們之間的距離,從而得到Bitmap對(duì)象需要平移的兩個(gè)參數(shù)值sx、sy。其中還包括保證圖像不會(huì)越過(guò)View邊界的檢查代碼。
savePreviousResult() 保存當(dāng)前的平移數(shù)據(jù),下次可以繼續(xù)在次基礎(chǔ)上平移Bitmap對(duì)象。
zoomIn()根據(jù)兩個(gè)點(diǎn)之間的歐幾里德距離,通過(guò)初始距離比較,得到放大比例,實(shí)現(xiàn)Bitmap在View對(duì)象上的放大
Matrix.postScale方法與Matrix.postTranslate方法可以不改變Bitmap對(duì)象本身實(shí)現(xiàn)平移與放大。
OnTouchListener支持以下的觸摸事件處理:
ACTION_DOWN事件,記錄平移開(kāi)始點(diǎn)
ACTION_UP事件,結(jié)束平移事件處理
ACTION_MOVE事件,記錄平移點(diǎn),計(jì)算與開(kāi)始點(diǎn)距離,實(shí)現(xiàn)Bitmap平移,在多點(diǎn)觸控時(shí)候,計(jì)算兩點(diǎn)之間的距離,實(shí)現(xiàn)圖像放大
ACTION_POINTER_DOWN事件,計(jì)算兩點(diǎn)之間的距離,作為初始距離,實(shí)現(xiàn)圖像手勢(shì)放大時(shí)候使用。
ACTION_POINTER_UP事件,結(jié)束兩點(diǎn)觸控放大圖像處理
二:代碼實(shí)現(xiàn)
自定義View的在layout中的使用xml如下:
<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類(lèi)的實(shí)現(xiàn)代碼如下:
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; // 平移開(kāi)始點(diǎn)與移動(dòng)點(diǎn) private Point startPoint; private Point movePoint; private float initDistance; // 記錄當(dāng)前平移距離 private int sx; private int sy; // 保存平移狀態(tài) 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() { // 初始化畫(huà)筆 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(); // 檢測(cè)邊緣 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); } } }
MainActivity的代碼如下:
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; } }
運(yùn)行截圖如下:
本文標(biāo)題:Android中實(shí)現(xiàn)Bitmap在自定義View中的放大與拖動(dòng)
分享地址:http://jinyejixie.com/article44/iejihe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動(dòng)態(tài)網(wǎng)站、營(yíng)銷(xiāo)型網(wǎng)站建設(shè)、ChatGPT、網(wǎng)站導(dǎo)航、、標(biāo)簽優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)