成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Android中實(shí)現(xiàn)Bitmap在自定義View中的放大與拖動(dòng)

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)行截圖如下:

Android中實(shí)現(xiàn)Bitmap在自定義View中的放大與拖動(dòng)

附件:http://down.51cto.com/data/2366284

本文標(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)

成都網(wǎng)站建設(shè)
壶关县| 黄大仙区| 齐河县| 望奎县| 香港 | 石渠县| 那曲县| 龙门县| 滨海县| 辛集市| 兴文县| 德安县| 旺苍县| 公主岭市| 常德市| 白水县| 望江县| 呈贡县| 河东区| 逊克县| 天长市| 武乡县| 乌什县| 资阳市| 嘉禾县| 宣城市| 启东市| SHOW| 芮城县| 丰原市| 文山县| 桂平市| 苏尼特左旗| 阜南县| 兴文县| 玉环县| 洛浦县| 建德市| 阿克陶县| 夹江县| 商都县|