android 自定义view实现放大缩小,Android中实现Bitmap在自定义View中的放大与拖动

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

一:基本实现思路android

基于View类实现自定义View –MyImageView类。在使用View的Activity类中完成OnTouchListener接口,实现对自定义View的触摸事件监听canvas

放大与拖动app

基于单点触控实现Bitmap对象在View上的拖动、而且检测View的边缘,防止拖动过界。基于两个点触控实现Bitmap对象在View上的放大、而且检测放大倍数。基于Matrix对象实现对Bitmap在View上放大与平移变换ide

Bitmap对象在View中的更新与显示post

经过重载onDraw方法,使用canvas实现绘制Bitmap对象、经过view.invalidate()方法实现View的刷新。this

MyImageView类的重要方法说明:spa

initParameters()初始化全部须要用到的参数code

setStartPoint()设置图像平移的开始点坐标xml

setMovePoint()设置图像平移的移动点坐标,而后集合开始点位置,计算它们之间的距离,从而获得Bitmap对象须要平移的两个参数值sx、sy。其中还包括保证图像不会越过View边界的检查代码。

savePreviousResult() 保存当前的平移数据,下次能够继续在次基础上平移Bitmap对象。

zoomIn()根据两个点之间的欧几里德距离,经过初始距离比较,获得放大比例,实现Bitmap在View对象上的放大

Matrix.postScale方法与Matrix.postTranslate方法能够不改变Bitmap对象自己实现平移与放大。

OnTouchListener支持如下的触摸事件处理:

ACTION_DOWN事件,记录平移开始点

ACTION_UP事件,结束平移事件处理

ACTION_MOVE事件,记录平移点,计算与开始点距离,实现Bitmap平移,在多点触控时候,计算两点之间的距离,实现图像放大

ACTION_POINTER_DOWN事件,计算两点之间的距离,做为初始距离,实现图像手势放大时候使用。

ACTION_POINTER_UP事件,结束两点触控放大图像处理

二:代码实现

自定义View的在layout中的使用xml以下:

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" >

android:id="@+id/myView"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:text="@string/hello_world" />

自定义View类的实现代码以下:

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);

}

}

}

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;

}

}

运行截图以下:

1777f7d30696093e0abac71be4176c17.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值