Android Canvas rotate 和translate 两个方法的研究
转自:http://www.verydemo.com/demo_c131_i3507.html
首先我们来看这样一个需求:显示一个竖向显示的TextView。说白了,就是把我们日常使用的TextView让丫的旋转90度。
怎么样?是不是很多人会说这有什么难得嘛,不就是用canvas让丫的旋转90度嘛。
别急,我们一点点引申。
对于很多没有接触过太多游戏开发的android程序员或者接触应用开发不久的程序员(我这样的)来说,或许都听过canvas这个东西,
也都知道这个东西有一个rotate()方法,也知道这个方法可”好像“以让”画布“旋转。
好的,我们先跟着上面的思路来走一下,看一看。
看下面的代码:
- public class MyTextView extends TextView {
- public MyTextView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- @Override
- protected void onDraw(Canvas canvas) {
- canvas.rotate(-90);
- super.onDraw(canvas);
- }
- }
看起来好像是我们在绘制TextView之前把画布逆时针旋转了90度是么?那么是不是说我们得到的就是一个竖向的TextView了呢?
布局文件很简单:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <com.carrey.demo.myTextView.MyTextView
- android:layout_width="wrap_content"
- android:layout_height="100dip"
- android:text="测试文字"/>
- </LinearLayout>
测试结果如下:
没错,什么都没看见,“似乎”没画出什么东西。
我开始的时候被这个问题困惑了很久,在网上查了很多资料,也没有想明白为什么会这样,因为稍早一些看过一本有点小名气的牛人专家写的
一本关于游戏开发的书里面介绍rotate(float degrees)这个方法的时候说:这个方法默认的旋转画布的旋转中心是屏幕的中心,一直都
按照这个思路来思考,后来才发现书里说的是错的。(这里也没别的意思,但是牛人也会犯错,不能尽信书,要多方面思考尝试)
这里我可以很肯定的告诉大家rotate(float degrees)这个方法的旋转中心是坐标的原点,在这个例子里就是屏幕的左上角了,怎么样是不是明白
过来为什么会什么都没有显示出来了呢?
这里先来插上一句我自己的体会,canvas的这个rotate方法不管是一个参数还是三个参数的那个,从字面上来看旋转的是“画布”,但是我们最好是
理解成旋转的是画布的坐标轴。好的我们继续向下,按照我们上面的那个例子,我们在旋转之前的屏幕坐标系如下:
按照我们之前的结论,rotate(float degrees)这个方法旋转的是画布的坐标轴,-90度是逆时针旋转(90是顺时针旋转),旋转之后的坐标轴状况
如下所示:
这里来做一下解释,“画控件的画布的区域”的意思就是我们在main.xml中添加一个空间的时候不是要设置layout_widths和layout_height这两个属性么?这里的这个
layout_widths和layout_height组成的矩形就是我们的这个“画控件的画布的区域”,当然,这个区域的左上角原点的位置在main.xml中对应的那个位置,就要按照其
所在的ViewGroup来决定了,比如这个控件在LinearLayout里面,那么就看LinearLayout的orientation是vertical?还是horizontal?,如果这个控件在RelativeLayout
里面,那么就看这个控件他在父容器的左边?右边?等等。。。这样就能确定“画控件的画布”的左上角的那个原点在布局文件中的位置了。
“旋转坐标系之后画控件的实际区域”,就是我们旋转后的坐标系的x,y轴正向的交集的区域,不管坐标系怎么转,我们的控件都是画在x,y数值都为正的那个区间里面的,
通过上面的那个图,可以看出坐标系旋转之后,实际画控件的区域并没有画布,所以也就画不出什么来了,因此我们的程序结果就什么都没有画出来了。
这里可能有人会说了,你怎么知道没画出来?这个例子里面的画控件的画布区域的原点和屏幕的原点是重合的,或许我们的控件画在了屏幕区域的外面只是没有看到
罢了。
对这种情况我们做一个验证,将main.xml修改如下:
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <com.carrey.demo.myTextView.MyTextView
- android:layout_width="wrap_content"
- android:layout_height="100dip"
- android:text="测试文字"
- android:layout_alignParentBottom="true"
- />
- </RelativeLayout>
运行结果如下:
怎么样?什么都没画出来,所以我们的结论是正确的,我们自定义的控件没有画在任何一张可以看见的画布上。
接下来问题就是:我们如何实现一个竖直的TextView呢?
我们按照前面的思路来思考:
按照前面我们得到的结论,我们要把控件画到画布上面,就要让我们的坐标系的x,y正向区域在”画控件的画布区域“上。
这里,我们就要用到canvas的translate(float dx,float dy)这个方法了,关于这个方法的作用,我研究的时候看了网上不少资料,发现有一些人的理解
是错误的,我也被引导的走了不少弯路。这个方法的作用就是移动我们画图的坐标系的原点,比如我们现在的原点是(0,0),然后我们调用canvas(-1,-1),
我们的原点x,y坐标就会分别变化-1,变化之后的原点就是(-1,-1)了。
那么回头来看我们上面的例子,我们希望变化我们的坐标系,让”画控件的画布的区域“处在x,y轴的正向区域中,这样我们就能把我们的控件画在画布上了,
示意图如下:
也就是说,我们只要让原点的位置向下移动”画控件的画布的区域“的高度就可以了,在代码中体现就是:
canvas.translate(-getHeight(),0);
这里的getHeight()获得的数值就是我们在main.xml中为我们的控件分配的layout_height有关,要注意的是我们要给layout_height分配一个确定值或者fill_parent
所谓确定值就是100dip这种值,如果我们用wrap_content,返回的getHeight()是很小的,我测试的结果是19,这个高度不能显示很多内容的,用兴趣的朋友可以
试一下。
我们把代码修改如下:
- public class MyTextView extends TextView {
- public MyTextView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- @Override
- protected void onDraw(Canvas canvas) {
- canvas.rotate(-90);
- canvas.translate(-getHeight(), 0);
- super.onDraw(canvas);
- }
- }
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <com.carrey.demo.myTextView.MyTextView
- android:layout_width="wrap_content"
- android:layout_height="100dip"
- android:text="测试文字"
- android:layout_alignParentBottom="true"
- />
- </RelativeLayout>
结果如下:
在左下方显示出了我们想要的竖直TextView,怎么样?是不是很简单?如果有什么问题或者指教,欢迎留言!
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow
Android Canvas rotate 和translate 两个方法的研究相关推荐
- android 图片叠加xml,Android实现图片叠加效果的两种方法
本文实例讲述了Android实现图片叠加效果的两种方法.,具体如下: 效果图: 第一种: 第二种: 第一种是通过canvas画出来的效果: public void first(View v) { // ...
- Android实现圆形图像的两种方法(Glide和Picasso)
Android实现圆形图像的两种方法 先上效果图 Glide Picasso CircleTransform.java(圆形图片工具类) 先上效果图 Glide 在app的build.gradle中引 ...
- android 画布叠加,Android实现图片叠加效果的两种方法
本文实例讲述了Android实现图片叠加效果的两种方法.分享给大家供大家参考,具体如下: 效果图: 第一种: 第二种: 第一种是通过canvas画出来的效果: public void first(Vi ...
- Android4清理代码缓存,Android清除应用缓存的两种方法
第一种 使用ActivityManager中的clearApplicationUserData方法,代码如下: ActivityManager am = (ActivityManager) getSy ...
- Android Canvas rotate() 旋转
Canvas 提供了 rotate() 方法用于旋转当前 Canvas 对象一定角度 rotate ( 旋转 ) void rotate(float degrees) final void rotat ...
- Android中添加背景音乐的两种方法
前些天在尝试自己写一个Android小游戏--flybird 基本功能实现了,就想添加声音,然后上网查了查,大多是一样,可是用到我这,有些却不可以用,所以我还用了两种方法. 下面谈谈这两种方法. 方法 ...
- Android发送短信的两种方法
Android发送短信代码的两种方法 Android发送短信代码的两种方法 有两种方法可以实现发送短信: 其一是使用intent-startActivity,URI数据格式为"smsto:n ...
- android相册如何加背景音乐,Android中添加背景音乐的两种方法
前些天在尝试自己写一个Android小游戏--flybird 基本功能实现了,就想添加声音,然后上网查了查,大多是一样,可是用到我这,有些却不可以用,所以我还用了两种方法. 下面谈谈这两种方法. 方法 ...
- Android设备设置代理的两种方法
本文将介绍两种给给android设备设置网络代理的方法,一种是直接在网络设置中操作,另一种是通过adb指令操作 第一种最常用的通过设置页面操作(此处以夜神模拟器为例讲解,其他设备操作方式基本类似) 操 ...
最新文章
- R语言ggplot2可视化在箱图上添加分组样本个数
- HP—UX更改存储设备名
- 用c语言 简单实现JAVA里面的ArryList 功能,实现内存自动扩展
- 如何绘制漂亮的多序列比对图片
- 关于在真实物理机器上用cloudermanger或ambari搭建大数据集群注意事项总结、经验和感悟心得(图文详解)...
- Mastering Caching in Asp.net
- 通过组策略实现客户端注册证书
- 安装python环境与运行_linux下怎么安装python的运行环境
- getParameter
- pbdom 不能解析gbk_备受家长追捧的公立学校,摇中率不到3%,还要抢着报名?速看大摇号学校全面解析!...
- python | 高效统计语言模型kenlm:新词发现、分词、智能纠错
- 使用C++编程语言保存数据库查询结果的方法
- 用户调用机房收费下机中用到的策略与职责链解析
- 多视几何_计算一副图像上的点在另一福图像上的对应点
- 计算机考研数据结构用哪本书,计算机考研数据结构该用哪本参考书?
- 入门OJ 1256【排队】
- Untitled-0720记录一次机器学习完整项目
- 自动化运维之k8s——Helm、普罗米修斯、EFK日志管理、k8s高可用集群(未完待续)
- codeup21691 买小猫小狗
- MySQL_Windows 下重启MySQL服务
热门文章
- CAD怎么转化成PDF?手机就可以轻松解决
- js获取对象的方法,根据id、根据name、根据标签名、根据类名
- HDU 1859 最小长方形
- 邮储银行的规模有多大?凭什么可以成为第6大国有银行?
- 银行测试(1)-我国的银行类型
- Ubuntu18.04/20.04 上微信中文显示为方块状乱码的解决方案( Deepin-Wechat )
- 关于华为P10(Android 8.0系统)出现的一个莫名奇妙的ANR
- Synch4j使用指南
- 念整数:你的程序要读入一个整数,范围是[-100000,100000]。然后,用汉语拼音将这个整数的每一位输出出来。 如输入1234,则输出: yi er san si
- Qt 之 QLineEdit