日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

Android随笔-include、merge、ViewStub

發(fā)布時(shí)間:2023/12/20 Android 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android随笔-include、merge、ViewStub 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

概述

Android為XML布局提供了多種類型的組件標(biāo)簽供使用,其中include、merge、ViewStub不常用,這三個(gè)標(biāo)簽用于布局優(yōu)化,本文對(duì)這三個(gè)標(biāo)簽進(jìn)行初略講解。

include

include是包含的意思,顧名思義就是布局重用的意思,也就是一塊布局寫好了之后,可以在其他布局中重復(fù)使用。實(shí)際開發(fā)中,使用include標(biāo)簽地方不少,包括標(biāo)題欄、控制面板、進(jìn)度條、統(tǒng)一的按鈕文字等等,凡是共用的布局都可以使用include,大大減少了程序員的工作量,提高了開發(fā)效率。
以標(biāo)題欄為例闡述include的使用。

  • 要自定義標(biāo)題欄titlebar,需要將app主題設(shè)為NoActionBar。
  • <style name="Theme.Content" parent="Theme.MaterialComponents.DayNight.NoActionBar">
  • 創(chuàng)建空白布局。
  • <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:text="Hello World!"android:textColor="@color/black"android:textSize="48dp" /> </LinearLayout>

    因?yàn)槿∠讼到y(tǒng)默認(rèn)的標(biāo)題欄,所以預(yù)覽圖中標(biāo)題部分是沒有的。

    3. 自定義標(biāo)題欄。

    <?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="52dp"android:background="#00BCD4"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_centerVertical="true"android:src="@drawable/ic_baseline_keyboard_arrow_left_24" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="這是標(biāo)題"android:textColor="@color/white"android:textSize="28dp" /> </RelativeLayout>

    自定義標(biāo)題欄中包含返回按鈕和標(biāo)題。
    4. include標(biāo)題欄

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><include layout="@layout/titlebar" /><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:text="Hello World!"android:textColor="@color/black"android:textSize="48dp" /> </LinearLayout>


    使用include標(biāo)簽,需要注意一下幾點(diǎn)。

    • include標(biāo)簽不能作為根布局元素
    } else if (TAG_INCLUDE.equals(name)) {if (parser.getDepth() == 0) {throw new InflateException("<include /> cannot be the root element");}parseInclude(parser, context, parent, attrs);
    • include標(biāo)簽內(nèi)不可以再添加其他元素。
    <includelayout="@layout/titlebar" ><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:text="Hello World!"android:textColor="@color/black"android:textSize="48dp" /></include>

    像上面的寫法雖然不會(huì)報(bào)錯(cuò),但是TextView卻無法展示出來。

    • include只能用在ViewGroup內(nèi)
    if (!(parent instanceof ViewGroup)) {throw new InflateException("<include /> can only be used inside of a ViewGroup");}
    • 若include添加了一些屬性,則會(huì)以添加后的為準(zhǔn),且include里面包含的元素也會(huì)以添加后的屬性為準(zhǔn)。
    // Apply a theme wrapper, if requested. This is sort of a weird// edge case, since developers think the <include> overwrites// values in the AttributeSet of the included View. So, if the// included View has a theme attribute, we'll need to ignore it.final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);final int themeResId = ta.getResourceId(0, 0);final boolean hasThemeOverride = themeResId != 0;if (hasThemeOverride) {context = new ContextThemeWrapper(context, themeResId);}ta.recycle(); <includeandroid:layout_width="100dp"android:layout_height="wrap_content"layout="@layout/titlebar" ></include>

    此時(shí)頁(yè)面效果就會(huì)發(fā)生改變。

    • 若include中有設(shè)置了id,include包含的視圖中也設(shè)置了id,則不能通過include自己的id獲取include里面的組件
    <includeandroid:id="@+id/include_title"layout="@layout/titlebar" ></include>

    titlebar.xml中布局如下。

    <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/rl_title"android:layout_width="match_parent"android:layout_height="52dp"android:background="#00BCD4"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_centerVertical="true"android:src="@drawable/ic_baseline_keyboard_arrow_left_24" /><TextViewandroid:id="@+id/tv_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="這是標(biāo)題"android:textColor="@color/white"android:textSize="28dp" /></RelativeLayout>

    此時(shí)通過rl_title尋找tv_title會(huì)出現(xiàn)空指針。

    RelativeLayout titleBar = findViewById(R.id.rl_title);TextView title = titleBar.findViewById(R.id.tv_title);

    結(jié)果會(huì)出現(xiàn)空指針異常。

    Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.widget.RelativeLayout.findViewById(int)' on a null object referenceat com.example.content.MainActivity.onCreate(MainActivity.java:22)

    include標(biāo)簽復(fù)用其他布局時(shí),可以視為在布局中又寫了一遍,所以獲取復(fù)用布局里面的元素直接使用findViewById即可。

    TextView title = findViewById(R.id.tv_title);

    無需借助復(fù)用布局的再一次findViewById。

    merge

    merge翻譯過來的意思是合并、融入、融合、兼并的意思,merge標(biāo)簽也就是起這樣的作用,用于減少布局層級(jí),防止頁(yè)面過渡繪制,減少繪制時(shí)間,提高性能。

    不使用merge

    普通布局。

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><include layout="@layout/titlebar"/><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:text="Hello World!"android:textColor="@color/black"android:textSize="48dp" /><include layout="@layout/normal_item"/></LinearLayout>

    其中normal_item沒有使用merge。

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="24dp"android:textColor="@color/black"android:text="第一個(gè)普通測(cè)試文本"/><TextViewandroid:layout_marginTop="50dp"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="24dp"android:textColor="@color/black"android:text="第二個(gè)普通測(cè)試文本"/></LinearLayout>

    結(jié)果布局中的樹如下:

    一共有兩級(jí)組件。

    使用merge

    使用merge就是將上訴normal_item中LinearLayout改成merge。

    <?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="24dp"android:textColor="@color/black"android:text="第一個(gè)merge測(cè)試文本"/><TextViewandroid:layout_marginTop="50dp"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="24dp"android:textColor="@color/black"android:text="第二個(gè)merge測(cè)試文本"/></merge>

    組件樹如下:

    結(jié)果發(fā)現(xiàn)使用了merge后,merge里面的組件和父容器里面的組件是同一層級(jí),而沒有使用merge是兩級(jí),所以merge主要功能是用來減少布局層級(jí)。
    使用merge也需要注意幾點(diǎn)。

    • merge是一個(gè)標(biāo)簽而不是一個(gè)view,所以在merge上不需要設(shè)置任何屬性
    <merge xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent">

    像上面的寫法其實(shí)是沒有任何效果的,merge里面的組件是根據(jù)使用merge的父容器來的。

    • merge必須是根節(jié)點(diǎn)元素
    <?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="24dp"android:textColor="@color/black"android:text="第一個(gè)merge測(cè)試文本"/><TextViewandroid:layout_marginTop="50dp"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="24dp"android:textColor="@color/black"android:text="第二個(gè)merge測(cè)試文本"/></merge>

    否則代碼編譯的時(shí)候會(huì)報(bào)錯(cuò)。

    } else if (TAG_MERGE.equals(name)) {throw new InflateException("<merge /> must be the root element");} else {
    • merge必須要有父容器
    if (TAG_MERGE.equals(name)) {if (root == null || !attachToRoot) {throw new InflateException("<merge /> can be used only with a valid "+ "ViewGroup root and attachToRoot=true");}rInflate(parser, root, inflaterContext, attrs, false);

    ViewStub

    A ViewStub is an invisible, zero-sized View that can be used to lazily inflate layout resources at runtime. When a ViewStub is made visible, or when inflate() is invoked, the layout resource is inflated. The ViewStub then replaces itself in its parent with the inflated View or Views. Therefore, the ViewStub exists in the view hierarchy until setVisibility(int) or inflate() is invoked. The inflated View is added to the ViewStub’s parent with the ViewStub’s layout parameters. Similarly, you can define/override the inflate View’s id by using the ViewStub’s inflatedId property.

    簡(jiǎn)單來講,ViewStub默認(rèn)是一個(gè)不可見,且寬高都為0的,只有在運(yùn)行時(shí)才會(huì)加載(懶加載)的組件。

    public ViewStub(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context);final TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.ViewStub, defStyleAttr, defStyleRes);saveAttributeDataForStyleable(context, R.styleable.ViewStub, attrs, a, defStyleAttr,defStyleRes);mInflatedId = a.getResourceId(R.styleable.ViewStub_inflatedId, NO_ID);mLayoutResource = a.getResourceId(R.styleable.ViewStub_layout, 0);mID = a.getResourceId(R.styleable.ViewStub_id, NO_ID);a.recycle();setVisibility(GONE);setWillNotDraw(true);}...@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension(0, 0);}

    ViewStub默認(rèn)顯示為GONE,寬高都為0,此時(shí)也不會(huì)繪制。需要顯示的時(shí)候,需要調(diào)用setVisibility()或者Inflate()才可以加載布局。

    使用
    <ViewStubandroid:id="@+id/vs_test"android:layout_width="200dp"android:layout_height="200dp"android:inflatedId="@+id/vs_inflate"android:layout="@layout/viewstub_item" />

    其中viewstub_item:

    <?xml version="1.0" encoding="utf-8"?> <ListView xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/lv_test"android:layout_width="match_parent"android:layout_height="match_parent"> </ListView>

    通過inflatedId就可以獲取viewstub_item里面的ListView 。

    ViewStub viewStub = findViewById(R.id.vs_test);// 加載viewStub.setVisibility(View.VISIBLE);// 通過inflatedId獲取viewstub_item里面的listViewListView listView = findViewById(R.id.vs_inflate);

    當(dāng)inflatedId不為NO_ID,也就是設(shè)置了id的時(shí)候,此時(shí)ViewStub的inflatedId就成為了根元素的id,此時(shí)可以直接通過findViewById獲取ViewStub 里面的元素。
    如果沒有設(shè)置inflatedId時(shí),可以直接通過findViewById(R.id.lv_test)獲取ViewStub里面的ListView。也可以通過inflate()直接獲取ViewStub里面的ListView。

    ViewStub viewStub = findViewById(R.id.vs_test);// 獲取ListViewListView inflate = (ListView) viewStub.inflate();if (inflate == null) {// 未加載} else {// 已加載}

    注意:

    • 可以通過判斷ViewStub的可見性(Visibility)判斷是否已加載。
    • 如果通過inflate(),則需要通過對(duì)inflate獲取對(duì)象進(jìn)行判空來判斷是否加載。
    • 如果設(shè)置了inflatedId,則需要通過inflatedId查找目標(biāo)父容器。

    總結(jié)

    以上是生活随笔為你收集整理的Android随笔-include、merge、ViewStub的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。