Bitmap与Matrix旋转ImageView
例说明
先前曾看过ImageView Widget的展示,虽可以将许多ImageView层层叠叠放在一起,再控制ImageView的图片来模拟动画的效果,但ImageView默认是没办法旋转的,那么要如何让ImageView产生旋转的效果呢?
要旋转ImageView其实很简单,先将前一次ImageView里的图片放入暂存Bitmap,接着再利用Bitmap.createBitmap来创建新的Bitmap对象,在创建新的Bitmap对象的同时,搭配Matrix对象里的setRotate()方法动态旋转新创建的Bitmap。然后,再将旋转好的Bitmap对象,以新构造的方式创建新的Bitmap对象,最后再“放入”ImageView中显示,就可以达到旋转ImageView的效果,这个范例的学习重点则在于如何操作BitmapFactory.decodeResource()方法来使用Matrix对图像的控制,为了让旋转能够通过事件来进行,所以在Layout中配置了两个Button Widget,以及一个ImageView Widget。当单击“向左旋转”按钮时,画面的小河马就会向左倾斜;当单击“向右旋转”按钮时,画面的小河马就会向右倾斜。
范例程序
src/irdc.ex04_24/EX04_24.java
程序设置了两个按钮,分别处理向左及向右旋转的语句,而为了防止旋转角度超过数值范围,所以默认参考值(ScaleAngle)向左最多为−5、向右则最多为5,再利用Matrix对象里的matrix.setRotate()方法,将5*ScaleAngle的计算结果传入作为参数,使其产生每次至少5°的变化,在−20°和20°之间。
Bitmap.createBitmap()方法所扮演的角色为产生暂存的Bitmap,使之每一次(单击按钮时)都“复制”来自原始图“mySourceBmp”的数据,自坐标(0,0)-(原图宽,原图高)复制成为新图,而由于createBitmap()方法的第六个参数可指定Matrix对象,这也就是本范例程序旋转画面的唯一关键。
/* import程序略 */
public class EX04_24 extends Activity
{
private Button mButton1;
private Button mButton2;
private TextView mTextView1;
private ImageView mImageView1;
private int ScaleTimes;
private int ScaleAngle;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mButton1 =(Button) findViewById(R.id.myButton1);
mButton2 =(Button) findViewById(R.id.myButton2);
mTextView1 = (TextView) findViewById(R.id.myTextView1);
mImageView1 = (ImageView) findViewById(R.id.myImageView1);
ScaleTimes = 1;
ScaleAngle = 1;
final Bitmap mySourceBmp =
BitmapFactory.decodeResource(getResources(), R.drawable.hippo);
final int widthOrig = mySourceBmp.getWidth();
final int heightOrig = mySourceBmp.getHeight();
/* 程序刚运行,加载默认的Drawable */
mImageView1.setImageBitmap(mySourceBmp);
/* 向左旋转按钮 */
mButton1.setOnClickListener(new Button.OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
ScaleAngle--;
if(ScaleAngle<-5)
{
ScaleAngle = -5;
}
/* ScaleTimes=1,维持1:1的宽高比例*/
int newWidth = widthOrig * ScaleTimes;
int newHeight = heightOrig * ScaleTimes;
float scaleWidth = ((float) newWidth) / widthOrig;
float scaleHeight = ((float) newHeight) / heightOrig;
Matrix matrix = new Matrix();
/* 使用Matrix.postScale设置维度 */
matrix.postScale(scaleWidth, scaleHeight);
/* 使用Matrix.postRotate方法旋转Bitmap*/
//matrix.postRotate(5*ScaleAngle);
matrix.setRotate(5*ScaleAngle);
/* 创建新的Bitmap对象 */
Bitmap resizedBitmap =
Bitmap.createBitmap
(mySourceBmp, 0, 0, widthOrig, heightOrig, matrix, true);
/**/
BitmapDrawable myNewBitmapDrawable =
new BitmapDrawable(resizedBitmap);
mImageView1.setImageDrawable(myNewBitmapDrawable);
mTextView1.setText(Integer.toString(5*ScaleAngle));
}
});
/* 向右旋转按钮 */
mButton2.setOnClickListener(new Button.OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
ScaleAngle++;
if(ScaleAngle>5)
{
ScaleAngle = 5;
}
/* ScaleTimes=1,维持1:1的宽高比例*/
int newWidth = widthOrig * ScaleTimes;
int newHeight = heightOrig * ScaleTimes;
/* 计算旋转的Matrix比例 */
float scaleWidth = ((float) newWidth) / widthOrig;
float scaleHeight = ((float) newHeight) / heightOrig;
Matrix matrix = new Matrix();
/* 使用Matrix.postScale设置维度 */
matrix.postScale(scaleWidth, scaleHeight);
/* 使用Matrix.postRotate方法旋转Bitmap*/
//matrix.postRotate(5*ScaleAngle);
matrix.setRotate(5*ScaleAngle);
/* 创建新的Bitmap对象 */
Bitmap resizedBitmap =
Bitmap.createBitmap
(mySourceBmp, 0, 0, widthOrig, heightOrig, matrix, true);
/**/
BitmapDrawable myNewBitmapDrawable =
new BitmapDrawable(resizedBitmap);
mImageView1.setImageDrawable(myNewBitmapDrawable);
mTextView1.setText(Integer.toString(5*ScaleAngle));
}
});
}
}
扩展学习
Matrix类的设计,不仅是二维空间的结构,事实上,它原始的设计是3´3的矩阵,由于Matrix类并不需要构造器,因此在声明Matrix对象之后,可以调用reset()方法或set()方法产生新的矩阵,如同本范例的setRotate一样。
回来看看,我们在这个范例程序中,也放上了添加注释的语句matrix.postRotate(5*ScaleAngle),经测试后,无论是使用postRotate()方法或setRotate()方法,效果都是相同的,但较困惑的是Google的官方SDK文件中,所描述的postRotate()方法的原型如下:
boolean postRotate(float degrees, float px, float py)
经测试postRotate()方法并没有第二、第三个参数需要传递,这是在Android SDK 1.0_r2才发现的,未来可能会因为改版而有所改变。
另外,Matrix还有一个常用的postScale()方法,可通过矩阵的方式用以指定其缩放大小,其原型如下:
public boolean postScale(float sx, float sy, float px, float py)
使用的公式为:M' = S(sx, sy, px, py)* M,示意的片段程序如下。
final Bitmap mySourceBmp =
BitmapFactory.decodeResource(getResources(), R.drawable.hippo);
Matrix mx = new Matrix();
mx.postScale
(
(float)20/mySourceBmp.getWidth(),
(float)20/mySourceBmp.getHeight()
);
mySourceBmp = Bitmap.createBitmap
(bm, 0, 0, bm.getWidth(), bm.getHeight(), mx, true);
mImageView1.setImageBitmap(mySourceBmp);
Bitmap与Matrix旋转ImageView的更多相关文章
- Android应用程序开发之图片操作(一)——Bitmap,surfaceview,imageview,Canvas
Android应用程序开发之图片操作(一)——Bitmap,surfaceview,imageview,Canvas 1,Bitmap对象的获取 首先说一下Bitmap,Bitmap是Androi ...
- 我的Android进阶之旅------>Android通过使用Matrix旋转图片来模拟碟片加载过程
今天实现了一个模拟碟片加载过程的小demo,在此展示一下.由于在公司,不好截取动态图片,因此就在这截取两张静态图片看看效果先. 下面简单的将代码列出来. setp1.准备两张用于旋转的图片,如下:lo ...
- android在假设绘制自己定义的bitmap,然后返回给ImageView
先来说一下FontMetrics这个类.这个类是关于字符属性和測量的类 用图能够更精确的知道各个属性的含义: 我们在Layout中有一个ImageView,我们能够通过: <span style ...
- Android 学习笔记之Bitmap位图的旋转
位图的旋转也可以借助Matrix或者Canvas来实现. 通过postRotate方法设置旋转角度,然后用createBitmap方法创建一个经过旋转处理的Bitmap对象,最后用drawBitmap ...
- Android学习笔记之Bitmap位图的旋转
位图的旋转也可以借助Matrix或者Canvas来实现. 通过postRotate方法设置旋转角度,然后用createBitmap方法创建一个经过旋转处理的Bitmap对象,最后用drawBitmap ...
- Android Bitmap太大导致ImageView不显示的问题
今天做我们的智能相冊的项目时,遇到了非常奇妙的问题,当照片太大时,导致ImageView.setImageBitmap不显示,上网上搜了非常多办法.感觉都不是那么靠谱.最后使用了简单粗暴的手段: // ...
- 054 Spiral Matrix 旋转打印矩阵
给出一个 m x n 的矩阵(m 行, n 列),请按照顺时针螺旋顺序返回元素.例如,给出以下矩阵:[ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ]]应该返回 [1,2, ...
- 成为Android高手必须掌握的28大项内容和10个建议
(一)成为Android高手必须掌握的8项基本要求 [1] Android操作系统概述1. Android系统架构. 2. Android利用设计理念. 3. ...
- 成为Android高手必须掌握的8项基本要求
[1] Android操作系统概述 1. Android系统架构. 2. Android利用设计理念. 3. Android 开源知识. 4. Android 参考网站与权威信息.[2] Androi ...
随机推荐
- 对Big O的新的认识
对Big O的新的认识 一个问题,它有很多种算法都能实现.每种算法它的时间.空间复杂度不一样.比如: 问题1: 求最大连续子序列和的问题,可以有O(n3).O(n2).O(nlogn)和O(n)四种时 ...
- MVC3+EF4.1学习系列(六)-----导航属性数据更新的处理
通过上一篇的学习 我们已经知道怎么查询关系 这篇就来说说怎么导航属性数据更新时的处理 以及EF又会为我们生成哪些SQL~ 老规矩 先看下今天的图 添加和修改页面基本就是这样 这节的内容相对简单~~ 主 ...
- c++的函数模板和类模板
函数模板和普通函数区别结论: 函数模板不允许自动类型转化 普通函数能够进行自动类型转换 函数模板和普通函数在一起,调用规则: 1 函数模板可以像普通函数一样被重载 2 C++编译器优先考虑普通函数 3 ...
- html5 读写sqlite数据库
var db = openDatabase('MyData','','My Database',102400); //首先它创建一个数据库表,里面有3个字段 db.transaction(functi ...
- sublime 配置 python IDE
安装sublime下载地址:http://www.sublimetext.com/,请自行根据系统版本进行下载.下载好之后直接安装即可. 汉化包 汉化包下载: 汉化方法: 1.运行sublime te ...
- 域名、网站名、url的定义
网址:http://jingyan.baidu.com/article/2c8c281df0afd00008252aa7.html
- 小箭头的写法,z-index在ie7显示混乱问题
一.jQuery 发布 1.9 正式版,最后支持 IE 6/7/8,2.0以上的版本都不支持这三个浏览器了. 二.小箭头的写法与旋转切换(一直以为这样的只以切图片,原来未必哦.) <style& ...
- Microsoft SqlSever 数据库--软谋1
百度百科--Microsoft SqlSever SQL是英文Structured Query Language的缩写,意思为结构化查询语言.SQL语言的主要功能就是同各种数据库建立联系,进行沟通.按 ...
- gson学习以及进阶文章推荐
Json转换利器Gson之实例一-简单对象转化和带泛型的List转化 (http://blog.csdn.net/lk_blog/article/details/7685169)Json转换利器Gso ...
- HDU 5776 sum
猜了一下,发现对了.n>m是一定有解的.所以最多m*m暴力,一定能找到.而T较小,所以能过. #pragma comment(linker, "/STACK:1024000000,10 ...