自定义View(一)、基础概念和知识点

自定义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)获取的topleft为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的左上角位置,得到如下结果:

我们可以看到getXgetY 的值趋近于零(手指点击最左上角得到的结果应该是0,0)
getRawXgetRawY 的值对比上面的结果,肯定不是相对于父类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第一篇,后续会一步步探索,也会通过一些实战来巩固,整理也是学习过程,文章内容会尽量整的详细一些,感谢你的阅读,如果文中有错误之处,接受批评和指点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值