【Android】include与ViewStub/merge

需求:正常情况下展示原有的文章详情页,当特殊情况--文章被删除时,展示一个"文章不存在"的兜底页。

1⃣️正常页面 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_main"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="30dp"
        android:text="Hello World!" />

</RelativeLayout>

2⃣️引入一个删除页的展示,实际业务中布局会比较复杂,建议新建一个布局文件 view_delete.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">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="文章已删除"
        android:textColor="@color/colorAccent"
        android:textSize="30sp" />

</RelativeLayout>

3⃣️在把view_delete引入到activity_main中时,我们可以使用include方式,或者时ViewStub方式。

(1)如果使用include方式,通过指定layout引入布局,先置为gone

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_main"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="30dp"
        android:text="Hello World!" />

    <include
        android:id="@+id/layout_delete"
        layout="@layout/view_delete"
        android:visibility="gone"/>
    
</RelativeLayout>

当控制两个样式的显隐时,在Activity或Fragment或者什么地方⬇️

class MainActivity : AppCompatActivity() {

    private lateinit var mMainText: TextView
    private lateinit var mEmptyLayout: RelativeLayout

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        mMainText = findViewById(R.id.tv_main)
        mEmptyLayout = findViewById(R.id.layout_delete)

        hideMainActivity()
    }

    private fun hideMainActivity() {
        mMainText.visibility = GONE
        mEmptyLayout.visibility = VISIBLE
    }
}

 

(2)使用ViewStub方式

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_main"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Hello World!"
        android:textSize="30dp" />

    <ViewStub
        android:id="@+id/layout_delete"
        android:layout="@layout/view_delete"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

在逻辑控制的部分⬇️,用inflate()方式或VISIBLE方式都可以

class MainActivity : AppCompatActivity() {

    private lateinit var mMainText: TextView
    private lateinit var mViewStub: ViewStub

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        mMainText = findViewById(R.id.tv_main)
        mViewStub = findViewById(R.id.layout_delete)

        hideMainActivity()
    }

    private fun hideMainActivity() {
        mMainText.visibility = GONE
        mViewStub.inflate()
        //mViewStub.visibility = VISIBLE
    }
}

 

总结一下include与ViewStub的区别

1⃣️引入布局的方式不同

include采用layout="@layout/xxx"的方式

ViewStub采用android:layout="@layout/xxx"的方式(如果写错了,编译不会报错,运行时会发生崩溃)

2⃣️在布局中的实际情况不同

include方式与直接把布局内容写在主文件一样,只是为了把布局分开写 或者 布局复用,在一开始就会把include的内容引用进来;

而ViewStub的内容一开始在布局中是不存在的,只有调用inflate()才会开始加载,⚠️inflate()只能调用一次。

3⃣️布局中必要属性不同

include不用必须指定android:layout_width和android:layout_height,ViewStub必须指定

 

⚠️在include和ViewStub节点中加入id,而不是在被引入文件的跟布局中加id。在该例中,不要在view_delete的跟布局加入id。

ViewStub很适用于引入这种,很少有机会被加载出来的页面。这样在大多数正常的主流程中,完全不用考虑ViewStub,性能不会收到影响。

 

附:发完文,给我推荐了很多merge的使用,就顺便学习了一下,记录一下merge的使用。merge的目的在于减少多余的布局层级,如主布局是RelativeLayout(LinearLayout),引入的文件跟布局也是RelativeLayout(LinearLayout),就很浪费。这时候,可以使用merge来进行处理,merge的布局,取决于引入它的布局的布局方式。

view_delete如下⬇️

<?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">

    <TextView
        android:id="@+id/tv_delete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="文章已删除"
        android:textColor="@color/colorAccent"
        android:textSize="30sp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_delete"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp"
        android:text="看看别的文章吧"
        android:textColor="@color/colorPrimaryDark"
        android:textSize="20dp" />

</merge>

1⃣️当主布局使用RelativeLayout时

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context=".MainActivity">

    <include layout="@layout/view_delete" />

</RelativeLayout>

界面如下图所示

当主布局采用LinearLayout布局时。

<?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"
    tools:context=".MainActivity">

    <include layout="@layout/view_delete" />

</LinearLayout>

界面如下图所示

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值