转载自:http://www.eoeandroid.com/blog-659748-5465.html
上面讲到,Matrix由3*3矩阵中9个值来决定。而我们对Matrix的所有设置,也是对这9个值的各种不同的改变,来达到我们想要的效果。
下面是Matrix3*3的矩阵结构
- {MSCALE_X,MSKEW_X,MTRANS_X,
- MSKEW_Y,MSCALE_Y,MTRANS_Y,
- MPERSP_0,MPERSP_1,MPERSP_2}
一、首先介绍Scale缩放的控制
scale就是缩放,我们调用Matrix的setScale、preScale、postScale,实际在内部,就是通过修改MSCALE_X和MSCALE_Y来实现的。
下面就是一个简单的例子
- public class MatrixTestActivity extends Activity {
- private int screenWidth;
- private int screenHeight;
- private int bitmapWidth;
- private int bitmapHeight;
- private float baseScale;
- private float originalScale;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- // 获得屏幕的宽高
- screenWidth = getWindow().getWindowManager().getDefaultDisplay().getWidth();
- screenHeight = getWindow().getWindowManager().getDefaultDisplay().getHeight();
- // 加载Imageview和获得图片的信息
- final ImageView imageView = (ImageView) findViewById(R.id.imgView);
- final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.a);
- bitmapWidth = bitmap.getWidth();
- bitmapHeight = bitmap.getHeight();
- // 计算缩放比,因为如果图片的尺寸超过屏幕,那么就会自动匹配到屏幕的尺寸去显示。
- // 那么,我们就不知道图片实际上在屏幕上显示的宽高,所以先计算需要全部显示的缩放比,
- // 在去计算图片显示时候的实际宽高,然后,才好进行下一步的缩放。
- // 要不然,会导致缩小和放大没效果,或者内存泄漏等等
- float scaleX = screenWidth / (float) bitmapWidth;
- float scaleY = screenHeight / (float) bitmapHeight;
- baseScale = Math.min(scaleX, scaleY);// 获得缩放比例最大的那个缩放比,即scaleX和scaleY中小的那个
- originalScale = baseScale;
- final Matrix matrix = new Matrix();
- matrix.setScale(originalScale, originalScale);
- // 关于setScale和preScale和postScale的区别以后再说
- // matrix.preScale(originalScale, originalScale);
- // matrix.postScale(originalScale, originalScale);
- Bitmap bitmap2 = Bitmap
- .createBitmap(bitmap, 0, 0, bitmapWidth, bitmapHeight, matrix, false);
- imageView.setImageBitmap(bitmap2);
- final Button scale_btn = (Button) findViewById(R.id.scale_btn);
- final EditText scale_text = (EditText) findViewById(R.id.scale_editView);
- scale_btn.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- String scaleStr = scale_text.getText().toString();
- if (scaleStr == null || "".equals(scaleStr))
- return;
- float scale = 0.0f;
- try {
- scale = Float.parseFloat(scaleStr);
- } catch (NumberFormatException e) {
- return;
- }
- matrix.reset();
- originalScale = scale * originalScale;//看
- if (originalScale < 0.05 ){
- originalScale=0.05f;
- }
- if(originalScale > baseScale){
- originalScale=baseScale;
- }
- matrix.setScale(originalScale, originalScale);
- Bitmap bitmapChange = Bitmap.createBitmap(bitmap, 0, 0, bitmapWidth, bitmapHeight,
- matrix, false);
- imageView.setImageBitmap(bitmapChange);
- }
- });
- }
- }
可以发现,对于Scale的设置,Matrix提供了3中不同的方式来设置。
setScale、preScale、postScale。
这三种方法之间有什么区别呢?看下面的。
二、set....、pre....、post...的区别
1、setScale(sx,sy),首先会将该Matrix设置为对角矩阵,即相当于调用reset()方法,然后在设置该Matrix的MSCALE_X和MSCALE_Y直接设置为sx,sy的值
2、preScale(sx,sy),不会重置Matrix,而是直接与Matrix之前的MSCALE_X和MSCALE_Y值结合起来(相乘),M' = M * S(sx, sy)。
3、postScale(sx,sy),不会重置Matrix,而是直接与Matrix之前的MSCALE_X和MSCALE_Y值结合起来(相乘),M' = S(sx, sy) * M。
preScale和post都是与之前的Matrix结合起来,那它们之间又有什么区别呢?
举几个例子测试下关于pre....和post....的区别:
对一个Matrix如下设置
1、pre....的执行顺序
- Matrix matrix=new Matrix();
- float[] points=new float[]{10.0f,10.0f};
- matrix.preScale(2.0f, 3.0f);//
- matrix.preTranslate(8.0f,7.0f);//
- matrix.mapPoints(points);
- Log.i("test", points[0]+"");
- Log.i("test", points[1]+"");
结果为点坐标为(36.0,51.0)
可以得出结论,进行变换的顺序是先执行preTranslate(8.0f,7.0f),在执行的preScale(2.0f,3.0f)。这也是为什么有的人比喻为pre...是向后生长的,即对于一个Matrix的设置中,
所有pre....是倒着向后执行的。
2、post...的执行顺序
- Matrix matrix=new Matrix();
- float[] points=new float[]{10.0f,10.0f};
- matrix.postScale(2.0f, 3.0f);//
- matrix.postTranslate(8.0f,7.0f);//
- matrix.mapPoints(points);
- Log.i("test", points[0]+"");
- Log.i("test", points[1]+"");
结果为点坐标为(28.0,37.0)
可以得出结论,进行变换的顺序是先执行postScale(2.0f,3.0f),在执行的postTranslate(8.0f,7.0f)。这 也是为什么有的人比喻为post...是向前生长的,即对于一个Matrix的设置中,所有post....是顺着向前执行的。
3、当pre和post交替出现的执行顺序
- Matrix matrix=new Matrix();
- float[] points=new float[]{10.0f,10.0f};
- matrix.postScale(2.0f, 3.0f);
- matrix.preRotate(90);
- matrix.mapPoints(points);
- Log.i("test", points[0]+"");
- Log.i("test", points[1]+"");
结果为点坐标为(-20.0,30.0)
将pre...和post顺序换一下
- Matrix matrix=new Matrix();
- float[] points=new float[]{10.0f,10.0f};
- matrix.preRotate(90);
- matrix.postScale(2.0f, 3.0f);
- matrix.mapPoints(points);
- Log.i("test", points[0]+"");
- Log.i("test", points[1]+"");
结果为点坐标依旧为为(-20.0,30.0)
可见,总是pre先执行的。在看下面的:
- Matrix matrix = new Matrix();
- float[] points = new float[] { 10.0f, 10.0f };
- matrix.postScale(2.0f, 3.0f);// 第1步
- matrix.preRotate(90);// 第2步
- matrix.postTranslate(8.0f, 7.0f);// 第3步
- matrix.preScale(1.5f, 2.5f);// 第4步
- matrix.mapPoints(points);
- Log.i("test", points[0] + "");
- Log.i("test", points[1] + "");
结果为点坐标依旧为为(-42.0,52.0)
经过前面的结论和推算,可以发现执行的顺序是 4----2----1---3
在看下面的,增加了setScale的一段代码:
- Matrix matrix = new Matrix();
- float[] points = new float[] { 10.0f, 10.0f };
- matrix.postScale(2.0f, 3.0f);// 第1步
- matrix.preRotate(90);// 第2步
- matrix.setScale(1.4f, 2.6f);// 第3步
- matrix.postTranslate(8.0f, 7.0f);// 第4步
- matrix.preScale(1.5f, 2.5f);// 第5步
- matrix.mapPoints(points);
- Log.i("test", points[0] + "");
- Log.i("test", points[1] + "");
结果为点坐标依旧为为(29.0,72.0)
经过计算,可以发现,在第3步setScale之前的第1、2步根本就没有用了,直接被第3步setScale覆盖,在从第3开始执行的。
顺序为2---1----3----5----4,因为2、1被覆盖了,所以没有效果,相当于直接执行3-----5----4
总结:最后可以得出结论,在对matrix该次变换之前的所有设置中,先检测有没有setScale,如果有,直接跳到setScale那一步开始 执行变换,然后在倒着执行下面所有的pre...变换,在顺着执行所有post....的变换。所以在对Matrix变换设置的时候,一定要注意顺序,不 同的顺序,会有不同的结果。
相关推荐
java精确除法运算报错问题,bigdecimal用除法加上bigdecimal.setscale(数字)即可避免java报错
//加载大炮的炮台效果和图标效果,如果这里的代码与上面的代码前后顺序更改,则会出现炮台效果在水波下面显示。不是没有显示,只是遮挡关系的原因。而看不见 texture=CCTextureCache::sharedTextureCache()->...
QT GraphicsView框架的应用,对自定义RectItem通过控制点AgentItem调整尺寸,Item成组,解组的具体用法,给学习Qt组态软件编写提供很大帮助。 程序需要Qt4.7.4支持,Vs2008环境。
SetScale SetValue GetValue SetName GetName GetType GetParameter The CADOCommand Class CADOCommand AddParameter SetText GetText SetType GetType GetCommand Execute GetRecordsAffected The CJectEngine ...
在chrome控制台执行函数 setScale(0) 可还原屏幕为大小和位置。 添加这个功能的原因,是有些LED屏幕仅能显示后台计算机的左上角区域屏幕。 使用了 localstorage 在任何步骤都会保存数据,不怕浏览器刷新。 按C键打开...
java BigDecimalUtil 保留两位小数 去掉小数位无效0并转换为String,nullToZero data.setScale(2, RoundingMode.HALF_UP);
setScale:缩放变化; setRotation:角度变化; 我们可以用这些方法的组合来实现各种View切换特效; 那是不是说Android3.1之前的版本就没办法使用这些方法呢?当然不是,我们有万能的github,万能的开源项目:...
mFallingView.setScale(progress);//设置碎片的大小,数值越大,碎片越小,默认值是3 mFallingView.setDelay(progress);//设置碎片飘落的速度,数值越大,飘落的越慢,默认值是10 FallingView可以单个使用,也可以...
2、通过缩放比,改变频道列表的Label的颜色和大小 - (void)setScale:(CGFloat)scale { _scale = scale; self.textColor = [UIColor colorWithRed:scale green:0 blue:0 alpha:1]; CGFloat ...
_qwtSlider->setScale( QwtDate::toDouble(starData), QwtDate::toDouble(endData) ); _qwtSlider->setTotalSteps(dayCount); _qwtSlider->setPageSteps(30); double space = QwtDate::toDouble(endData)...
如果图片分辨率超过屏幕,android也会自动的调整到屏幕能放下整张的图片在放大图片的时候,可以用ImageView的SetFrame() 和setScale()方法,可以把图片放大到超过屏幕,原理就是ImageView放大,图片跟着放大。...
java 随机数Math.random()头、尾数字在四舍五入之后得到的几率其实比中间的数少一半,并不...max.subtract(min).multiply(BigDecimal.valueOf(Math.random())).add(min).setScale(0, RoundingMode.HALF_UP).intValue();
react-native-units 一组有用的单元和一个简单的网格实现,用于 React Native 中的响应式布局。 React Native 使用与密度无关的像素或 dp 作为默认单位。 这将调整元素大小,使它们在不同设备上的物理大小大致相同。...
本文实例讲述了PHP使用JPGRAPH制作圆柱图的方法。分享给大家供大家参考,具体如下: 制作圆柱图像的要点 首先,要使用jpgraph库... 下载完毕后将他解压到 ... ...SetScale 设置刻度样式 new BarPlot 创建一个新的BarPlo
本文实例讲述了php图形jpgraph操作。分享给大家供大家参考,具体如下: <?... ... ...$graph->SetScale(textlin); //设置图形的边距 $graph->img->SetMargin(40,180,40,40); //设置图形的背景图片,填充方式
分享给大家供大家参考。具体实现方法如下: <?... ...$data = array(19,23,34,38,45,67,71,78,85,87,90,96);...$graph->SetScale("textlin"); $graph->SetShadow(); //设置阴影 $graph->img->SetMargin
分享给大家供大家参考。具体实现方法如下: <?... ...//将要用于图表创建的数据存放在数组中 $data = array(19,23,34,38,45,67,71,78,85,87,90,...$graph->SetScale("textlin"); //设置刻度样式 $graph->img->SetMargin
相关博客:http://blog.csdn.net/wzg_1987/article/details/8938238
life->setScale(0.6); life->setPosition(ccp(30,winSize.height-23)); addChild(life, 1, 5); // ship life count char lifecount[2]; sprintf(lifecount, "%d",Config::sharedConfig()->getLifeCount()); ...