版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】Android中实现Bitmap在自定义View中的放大与拖动
Android中实现Bitmap在自定义View中的放大与拖动
一:基本实现思路基于View类实现自定义View–MyImageView类。在使用View的Activity类中完成OnTouchListener接口,实现对自定义View的触摸事件监听
放大与拖动基于单点触控实现Bitmap对象在View上的拖动、并且检测View的边缘,防止拖动过界。基于两个点触控实现Bitmap对象在View上的放大、并且检测放大倍数。基于Matrix对象实现对Bitmap在View上放大与平移变换
Bitmap对象在View中的更新与显示通过重载onDraw方法,使用canvas实现绘制Bitmap对象、通过view.invalidate()方法实现View的刷新。
MyImageView类的重要方法说明:initParameters()初始化所有需要用到的参数setStartPoint()设置图像平移的开始点坐标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如下:<RelativeLayout
xmlns:android="/apk/res/android"
xmlns:tools="/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类的实现代码如下: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;
myV
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026陕西西安东方航空食品招聘考试备考试题及答案解析
- 2026年西安理工大学附属小学教师招聘考试备考题库及答案解析
- 2026江西吉安市井冈山市城投控股集团有限公司招聘5人考试参考题库及答案解析
- 2025重庆城口县国有企业招聘考试情况考试参考试题及答案解析
- 2025浙江杭州临平环境科技有限公司招聘49人考试备考试题及答案解析
- 2026云南大理州剑川县文化和旅游局招聘2人考试备考试题及答案解析
- 2026年淮北安徽淮海实业发展集团有限公司社会招聘考试备考题库及答案解析
- 2026贵州铜仁市第二人民医院收费室见习生招募1人考试备考题库及答案解析
- 2026黑龙江哈尔滨工业大学商学院招聘考试参考题库及答案解析
- 2026广东东莞松山湖科学城集团有限公司下属企业市场化选聘6人考试备考题库及答案解析
- 广告标识牌采购投标方案
- 北京市2025年第一次普通高中学业水平合格性考试政治试题(原卷版)
- GB/T 45732-2025再生资源回收利用体系回收站点建设规范
- 中国特色社会主义知识点总结中职高考政治一轮复习
- 计算机应用专业发展规划
- 结算审核实施方案
- 企业管理的基础工作包括哪些内容
- 2025-2030中国奶瓶消毒烘干器行业市场发展分析及竞争格局与投资前景研究报告
- 铝合金门窗工程技术规范
- 食材配送服务方案投标文件(技术标)
- 电力储能知识培训课件
评论
0/150
提交评论