Android从入门到放弃——常用布局

今天讲一些比较常用的布局控件,还有一些不常用的就不做介绍了。

  • LinearLayout
  • RelativeLayout
  • FrameLayout
  • ConstraintLayout

LinearLayout

线性布局,可以设置横向和纵向,效果就是挨着往下排。看看效果:

xml代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp">

    <TextView
        android:text="线性布局,垂直方向"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView
        android:text="线性布局,垂直方向"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

水平方向:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:padding="10dp">

    <TextView
        android:text="线性布局,垂直方向"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView
        android:layout_marginStart="20dp"
        android:text="线性布局,垂直方向"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

可以看到控制方向的属性为:android:orientation="horizontal"和android:orientation="vertical"

LinearLayout还是比较简单,另外需要介绍的一个属性是:权重 android:weightSum,意思是当前的布局分成多少份。

每个子控件通过使用android:layout_weight来设置自身占多少。


xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:weightSum="5">

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:background="@android:color/darker_gray"
        android:text="权重:占2/5" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:background="@android:color/holo_red_light"
        android:text="权重:占3/5" />

</LinearLayout>

上面的代码将布局分成了5份,第一个TextView占2份,第二个TextView占3份。

LinearLayout的weightSum其实也可以不设置,总份数就是每个子控件占比的总和。

RelativeLayout

相对布局,这种布局对比LinearLayout更加的灵活一点,LinearLayout只能按照一个方向顺序的排下去。介绍RelativeLayout就必须了解与它相关的属性:

下面再来看看例子:

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:orientation="vertical">

    <TextView
        android:id="@+id/acMainTvOne"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:text="相对父控件开始位置" />

    <TextView
        android:id="@+id/acMainTvTwo"
        android:layout_marginTop="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/acMainTvOne"
        android:text="在指定控件下方" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_toRightOf="@id/acMainTvOne"
        android:text="在指定控件右边" />

    <TextView
        android:layout_centerInParent="true"
        android:text="父控件水平和垂直都居中"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</RelativeLayout>

FrameLayout

该布局的所有元素都默认在左上角,一层一层的网上叠加。

xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/acMainTvOne"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="第一个TextView" />

    <TextView
        android:id="@+id/acMainTvTwo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="FrameLayout 第二个TextView" />

</FrameLayout>

但是我们还是可以通过android:layout_gravity属性来指定位置

xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/acMainTvOne"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="第一个TextView" />

    <TextView
        android:id="@+id/acMainTvTwo"
        android:layout_width="wrap_content"
        android:layout_gravity="right"
        android:layout_height="wrap_content"
        android:text="FrameLayout 第二个TextView" />

</FrameLayout>

layout_gravity的相关取值可以查看这里:https://blog.csdn.net/zgy441008825/article/details/106558947有比较详细的描述。

ConstraintLayout

约束布局,更加高级和灵活的RelativeLayout。是后面才推出的一种新布局,所以在使用之前要先引入包:

implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

大家可以查看一下官方的文档:https://developer.android.google.cn/reference/android/support/constraint/ConstraintLayout

其实现在网上有很多关于约束布局的优秀文章,我这里列一些大家可以参考一下:

https://blog.csdn.net/qq_33721320/article/details/93859756

https://www.jianshu.com/p/17ec9bd6ca8a

https://www.jianshu.com/p/fa2dc62a0f70

这里就讲一下我们为什么要使用约束布局,其实就是它能解决什么问题?

在实际项目中我们界面布局一般都是非常复杂的,单独使用之前的某一种布局很难实现效果,我们就需要通过各种不同的布局来组合、嵌套来实现,这就带来另外一个问题,我们的界面太复杂,启动activity的时候系统解析xml文件太耗时导致启动界面变慢。约束布局就是为此而生的。

下面我们来看看我们使用普通的布局文件来做一个界面和约束布局的界面效果。

我们简单做一个音乐播放界面

差不多这样的效果

xml:

<?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:background="#114B7D"
    android:orientation="vertical"
    android:padding="10dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:weightSum="4">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@drawable/ic_baseline_favorite_24" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@drawable/ic_download" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@drawable/ic_msg" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@drawable/ic_baseline_more_horiz_24" />
    </LinearLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp">

        <TextView
            android:id="@+id/acMainTvTimeStart"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentStart="true"
            android:text="00:00"
            android:textColor="@android:color/white" />


        <View
            android:id="@+id/progressBar"
            android:layout_width="wrap_content"
            android:layout_height="5dp"
            android:layout_centerVertical="true"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:layout_toStartOf="@id/acMainTvTimeEnd"
            android:layout_toEndOf="@id/acMainTvTimeStart"
            android:background="@drawable/drawable_progress" />

        <TextView
            android:id="@+id/acMainTvTimeEnd"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:text="00:00"
            android:textColor="@android:color/white" />

    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp">

        <ImageView
            android:id="@+id/acMainImgMode"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentStart="true"
            android:layout_centerVertical="true"
            android:src="@drawable/ic_baseline_repeat_24" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toStartOf="@id/acMainImgStart"
            android:src="@drawable/ic_last" />

        <ImageView
            android:id="@+id/acMainImgStart"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:src="@drawable/ic_baseline_play_circle_filled_24" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toEndOf="@id/acMainImgStart"
            android:src="@drawable/ic_next" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:layout_centerVertical="true"
            android:src="@drawable/ic_baseline_playlist_play_24" />
    </RelativeLayout>

</LinearLayout>

 

布局的内容比较多,最外层是一个LinearLayout,垂直方向的布局,里面主要嵌套了3个布局,第一个也是LinearLayout,水平方向,4个图标平均分配。第二个和第三个都是相对布局。

 借助android studio的界面分析工具我们可以来看看界面的层次

可以看到整个层次的嵌套还是非常多的。如果我们使用约束布局,可以做到我们自己内部的布局只用一层来完成。

xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#114B7D"
    android:orientation="vertical"
    android:padding="10dp"
    tools:ignore="MissingConstraints">


    <ImageView
        android:id="@+id/acMainImgFavorite"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:src="@drawable/ic_baseline_favorite_24"
        app:layout_constraintEnd_toStartOf="@id/acMainImgDownload"
        app:layout_constraintStart_toStartOf="parent" />

    <ImageView
        android:id="@+id/acMainImgDownload"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:src="@drawable/ic_download"
        app:layout_constraintEnd_toStartOf="@+id/acMainImgMsg"
        app:layout_constraintStart_toEndOf="@id/acMainImgFavorite" />

    <ImageView
        android:id="@+id/acMainImgMsg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:src="@drawable/ic_msg"
        app:layout_constraintEnd_toStartOf="@+id/acMainImgMore"
        app:layout_constraintStart_toEndOf="@+id/acMainImgDownload" />

    <ImageView
        android:id="@+id/acMainImgMore"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:src="@drawable/ic_baseline_more_horiz_24"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/acMainImgMsg" />

    <TextView
        android:id="@+id/acMainTvTimeStart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_marginTop="10dp"
        android:text="00:00"
        android:textColor="@android:color/white"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/acMainImgFavorite" />

    <View
        android:id="@+id/progressBar"
        android:layout_width="0dp"
        android:layout_height="5dp"
        android:layout_centerVertical="true"
        android:layout_marginStart="10dp"
        android:layout_marginEnd="10dp"
        android:layout_toStartOf="@id/acMainTvTimeEnd"
        android:layout_toEndOf="@id/acMainTvTimeStart"
        android:background="@drawable/drawable_progress"
        app:layout_constraintBottom_toBottomOf="@+id/acMainTvTimeStart"
        app:layout_constraintEnd_toStartOf="@+id/acMainTvTimeEnd"
        app:layout_constraintStart_toEndOf="@+id/acMainTvTimeStart"
        app:layout_constraintTop_toTopOf="@+id/acMainTvTimeStart" />

    <TextView
        android:id="@+id/acMainTvTimeEnd"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:text="00:00"
        android:textColor="@android:color/white"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@+id/acMainTvTimeStart" />


    <ImageView
        android:id="@+id/acMainImgMode"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"
        android:src="@drawable/ic_baseline_repeat_24"
        app:layout_constraintBottom_toBottomOf="@+id/acMainImgStart"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/acMainImgStart" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toStartOf="@id/acMainImgStart"
        android:src="@drawable/ic_last"
        app:layout_constraintBottom_toBottomOf="@+id/acMainImgStart"
        app:layout_constraintEnd_toStartOf="@+id/acMainImgStart"
        app:layout_constraintTop_toTopOf="@+id/acMainImgStart" />

    <ImageView
        android:id="@+id/acMainImgStart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginTop="10dp"
        android:src="@drawable/ic_baseline_play_circle_filled_24"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/acMainTvTimeStart" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toEndOf="@id/acMainImgStart"
        android:src="@drawable/ic_next"
        app:layout_constraintBottom_toBottomOf="@+id/acMainImgStart"
        app:layout_constraintStart_toEndOf="@+id/acMainImgStart"
        app:layout_constraintTop_toTopOf="@+id/acMainImgStart" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_centerVertical="true"
        android:src="@drawable/ic_baseline_playlist_play_24"
        app:layout_constraintBottom_toBottomOf="@+id/acMainImgStart"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@+id/acMainImgStart" />

</androidx.constraintlayout.widget.ConstraintLayout>

可以看到我们整个内容都只是在一个布局中完成,这样可以有效的减少嵌套从而提升界面加载速度。

另外再介绍2个我们在xml中会经常使用的关键字,他们并不是控件或者布局:

  • include :在xml中使用,作用是直接将制定的布局原封不动的插入到指定位置。layout:<include layout="@layout/activity_main"/>
  • merge:它是作为根节点出现,一般我们自定义ViewGroup加载的布局文件使用。比如我们刚刚的播放控件,我们创建一个类,继承自ConstraintLayout,我们再在代码里面使用layoutInflater加载当前的布局,如果不适用merge作为根节点,那么加载出来的界面会多一层布局。merge会消除一层嵌套,不过需要注意的是我们在做布局的时候还是应该使用我们需要的布局作为根节点,因为merge会消除所有的属性,指定的属性都不起作用,在做完布局之后再改成merge。另外一个需要注意的就是我们自定义的ViewGroup继承类要和xml里面的相匹配。什么意思呢?比如我们刚刚的xml根节点是约束布局,那么我们就必须继承ConstraintLayout,如果是之前的布局我们使用的是LinearLayout,并且是垂直方向的,那么我们就必须继承LinearLayout,并且在代码里面设置垂直方向。

好了,今天的布局就讲这些了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值