自定義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第一篇,後續會一步步探索,也會通過一些實戰來鞏固,整理也是學習過程,文章內容會盡量整的詳細一些,感謝你的閱讀,如果文中有錯誤之處,接受批評和指點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章