自定义View(一)、基础概念和知识点
接下来一段时间我们将整理一系列自定义View文章,由浅到难,磨刀不误砍柴工,在真正开始之前,我们还是对自定义View的知识点有一定的了解和补充。
一、坐标系
为什么坐标系要提出来讲,因为在Android中和我们传统的坐标系有一定的区别,我们需要做区分。
- 数学坐标系:
右为X轴的正方向,上为Y轴的正方向,同理,数学坐标系中角度也是逆时针为正方向,如下图:
- 屏幕坐标系
Android中屏幕的坐标系定义是以左上角为起点,右边为X轴正方向,下方为Y轴正方向,如下图:
对应的角度方向,也是顺时针为正方向
贴上一个屏幕,大概就是下面这样
二、View的坐标系
View的坐标系统是相对于父控件而言的
通常有以下几个方法,
getTop()
获取View左上角距父View顶部的距离
getLeft()
获取View左上角距父View左侧的距离
getBottom()
获取View右下角距父View顶部的距离
getRight()
获取View右下角距父View左侧的距离
怎么理解呢,我们直接通过Demo来验证,先写一个布局文件如下:
activity_ui_custom_location.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<LinearLayout
android:id="@+id/ll_view"
android:layout_width="300dp"
android:layout_height="300dp"
android:background="@color/colorAccent">
<View
android:id="@+id/view"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@color/colorPrimary" />
</LinearLayout>
</RelativeLayout>
上面的xml布局文件预览如下:
通过上面的xml文件我们可以分析出来,B(View)视图的父View是A(LinearLayout),而A(LinearLayout)的父布局又是C(RelativeLayout)
我们现在分别来获取A和B的坐标位置:
View mView = findViewById(R.id.view);
LinearLayout mLlView = findViewById(R.id.ll_view);
mView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int viewLeft = mView.getLeft();
int viewTop = mView.getTop();
int viewRight = mView.getRight();
int viewBottom = mView.getBottom();
LogUtil.d(TAG + "--view viewLeft=" + viewLeft);
LogUtil.d(TAG + "--view viewTop=" + viewTop);
LogUtil.d(TAG + "--view viewRight=" + viewRight);
LogUtil.d(TAG + "--view viewBottom=" + viewBottom);
}
});
mLlView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mLlView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int llViewLeft = mLlView.getLeft();
int llViewTop = mLlView.getTop();
int llViewRight = mLlView.getRight();
int llViewBottom = mLlView.getBottom();
LogUtil.d(TAG + "--view llViewLeft=" + llViewLeft);
LogUtil.d(TAG + "--view llViewTop=" + llViewTop);
LogUtil.d(TAG + "--view llViewRight=" + llViewRight);
LogUtil.d(TAG + "--view llViewBottom=" + llViewBottom);
}
});
结果:
我们看到B(View)获取的top
和left
为0,由此可以推断出View获取的坐标位置是基于父布局来的,因为B的左上角刚好是其父类的左上角,所以获取数据为0。如果我们B居中,如下:
再次获取坐标位置结果如下:
分析结果能得出如下结论:
三.MotionEvent中 get 和 getRaw 的区别
我们同样先通过Demo来得出结论,我们直接拿上面的demo进行演示,
mView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
float getX = event.getX();
float getRawX = event.getRawX();
float getY = event.getY();
float getRawY = event.getRawY();
LogUtil.d(TAG + "--setOnTouchListener getX=" + getX + ",getRawX=" + getRawX);
LogUtil.d(TAG + "--setOnTouchListener getY=" + getY + ",getRawY=" + getRawY);
return false;
}
});
我们尽量的点击视图B的左上角位置,得到如下结果:
我们可以看到
getX
、getY
的值趋近于零(手指点击最左上角得到的结果应该是0,0)
getRawX
、getRawY
的值对比上面的结果,肯定不是相对于父类A的,而是相对于屏幕的坐标位置。
基于以上结果,大致得出以下结论:
实际坐标出发点是同一点,为了区分黄线分别右移和下移了一点,图比较粗糙,清楚就好。
四、Android中角度和弧度
在后续的自定义View中,一些复杂的图形需要各种数学上的计算,简单举个例子,我们在自定义圆形进度条或者自定义一个钟表的时候,就涉及到角度和弧度的概念,所以我们提前对Android中的角度和弧度有一个认识。
首先看看,角度和弧度在圆上如何表示:
角度
弧度
由上面两个图可以得出角度和弧度的定义:
名称 | 定义 |
---|---|
角度 | 两条射线从圆心向圆周射出,形成一个夹角和夹角正对的一段弧。当这段弧长正好等于圆周长的360分之一时,两条射线的夹角的大小为1度. |
弧度 | 两条射线从圆心向圆周射出,形成一个夹角和夹角正对的一段弧。当这段弧长正好等于圆的半径时,两条射线的夹角大小为1弧度. |
为什么对角的描述有角度和弧度两种,因为二者进制不同,角度是60进制,而弧度是十进制,在自定义View计算的时候可以要根据不同的数值进行转换。
4.1、角度和弧度的换算方式
圆一周角度为360°,弧度为2π
所以 360° = 2π --------------------------> 180° = π
- 1° = π/180
- 1弧度 = 180/π
五、颜色
5.1、简单颜色介绍
Android中支持的颜色模式
颜色模式 | 备注 |
---|---|
ARGB8888 | 四通道高精度(32位) |
ARGB4444 | 四通道低精度(16位) |
RGB565 | 屏幕默认模式(16位) |
Alpha8 | 仅有透明通道(8位) |
字母表示通道类型,数值表示该类型用多少位二进制来表示
如ARGB8888表示有四个通道,每个对应的通道用8位二进制表示
RGB565表示三个通道,每个对应通道分别使用5、6、5位二进制表示
注意:我们常用的是ARGB8888和ARGB4444,而在所有的安卓设备屏幕上默认的模式都是RGB565,请留意这一点
以ARGB8888为例介绍颜色定义:
类型 | 解释 | 0(0x00) | 255(0xff) |
---|---|---|---|
A(Alpha) | 透明度 | 透明 | 不透明 |
R(Red) | 红色 | 无色 | 红色 |
G(Green) | 绿色 | 无色 | 绿色 |
B(Blue) | 蓝色 | 无色 | 蓝色 |
-
其中 A R G B 的取值范围均为0(0000 0000)- 255(1111 1111)
-
A 从0x00到0xff表示从透明到不透明。
-
RGB 从0x00到0xff表示颜色从浅到深。
我们在代码中颜色设置就可以如下定义:
总结
简单介绍了一下自定义view一些基础概念和知识点,本文感谢
自定义View,这是自定义view第一篇,后续会一步步探索,也会通过一些实战来巩固,整理也是学习过程,文章内容会尽量整的详细一些,感谢你的阅读,如果文中有错误之处,接受批评和指点。