侧边栏

安卓入门之视图与布局

发布于 | 分类于 客户端/Android

想去了解一下React NativeWeex,转念一想我特么去学Native干嘛?然后现在准备先学习安卓了,在折腾了相关的环境配置并成功跑完Hello World之后,开始试着用前端的思维来理解和学习安卓。下面是关于安卓中样式布局的整理。

就目前我接触到的东西来看,安卓布局跟网页布局有不少相似之处。现在web前端正在往组件化方向发展,像Vue等框架都实现了Component系统;而安卓内置了大量的View类,代表着不同的视图(“组件”)。

对于View视图这个称谓我到现在都耿耿于怀,明明组件(或者控件)更合适嘛~然而安卓__四大组件__已经提前把"组件"的称为给拿去了,既然如此,像复选框之类的还是入乡随俗叫做视图吧。

XML布局

XML布局文件用于定义应用程序的用户界面,布局文件使用 .xml 作为后缀名,例如 activity_main.xml、fragment_login.xml。

下面列举了XML布局中的一些核心知识点,可以使用这些知识来创建和设计Android应用程序的用户界面。掌握XML布局的概念和用法,能够更好地理解和调整应用程序的界面布局。

根元素

XML布局文件的根元素通常是一个布局容器,用于包含其他视图元素。常见的根元素包括LinearLayout、RelativeLayout、ConstraintLayout等。您可以选择适合您界面需求的布局容器。

xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
    tools:context=".MainActivity">
    <!-- ... -->
</androidx.coordinatorlayout.widget.CoordinatorLayout>

视图元素

视图元素代表应用程序界面的各个组件,Android布局文件都由视图元素组成,如按钮、文本框、图像视图等。您可以在布局文件中添加和配置这些视图元素,并定义它们的属性和样式。

下面展示了一个TextViewButton两个视图元素

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

    <TextView
        android:id="@+id/textview_first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_first_fragment"
        app:layout_constraintBottom_toTopOf="@id/button_first"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button_first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/next"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textview_first" />
</androidx.constraintlayout.widget.ConstraintLayout>

布局属性

布局属性用于控制视图元素在布局容器中的样式,如宽度、高度、背景颜色、位置、字体大小等。常见的布局属性包括layout_width、layout_height、layout_margin、layout_gravity、top、bottom、left、right、center_vertical、center_horizontal等。

可以使用这些属性来指定视图元素的尺寸、边距和对齐方式等。

引用资源

在布局文件中,您可以使用@符号引用资源,如字符串、颜色、尺寸等。这使得您可以在布局中使用资源值,并在需要时进行更改和维护。例如,@string/my_string引用字符串资源。

也可以 使用 XML 声明来引用其他布局文件或资源文件,例如在 activity_main.xml 中使用 image 标签引用了 image.png。

复杂布局

  • 布局嵌套:可以在布局文件中嵌套其他布局容器,以实现复杂的布局结构。通过嵌套布局,您可以创建层次化的界面,并更好地组织和管理视图元素。
  • 动态布局:可以使用 ViewPager、RecyclerView 等控件实现动态布局。
  • 自定义视图:可以自定义视图元素,继承 View 类并重写 onMeasure()、onDraw() 方法来实现自己的布局效果。

ID和引用

每个视图元素可以分配一个唯一的ID,以便在代码中引用和操作它们。您可以使用android:id属性为视图元素指定一个ID值,并在代码中使用findViewById()方法来获取对应的视图对象。

样式和主题

样式和主题用于定义和应用视图元素的外观和样式。您可以使用style属性为视图元素指定样式,或使用theme属性为整个应用程序或活动指定主题。

视图

所有在屏幕中可以看见的都是视图。View是一个超类,所有视图都是从它派生出去的,这里转一个图,理清视图之间的关系。 view继承

基础视图

安卓内置了大量的视图控件,在Android Studio中的布局Design中可以通过拖拽的方式拜访控件(为什么我立马就联想到了Dreamwaver~)。好吧,还是老老实实背属性吧,根据经验,这种可视化的布局真的是个坑,不过用来快速写标签还是不错的。

常用的视图控件有:

  • TextView,用于放置文本标签,类似于span(这个类似貌似没有任何意义)
  • Button,默认按钮,类似于button
  • EditText,文本输入框,类似于input[type=text]
  • ImageView,图片,类似于img
  • RadioButton,单选框,类似于radio
  • Checkbox,复选框,类似于checkbox
  • Menu,菜单,这个貌似是个新东西

大部分基础视图控件都可以类比为HTML中的各种标签,每个控件都有通用的属性 ,也可能会有自身独特的属性(跟Web中也很相似)。由于现在赶时间,因此都是对着文档写demo的,附官方文档。PS:安卓中好像没有网页上那么严重依赖元素嵌套进行布局,所以UI这块不必过于担心。

除了基础视图控件,还有一些高级控件(使用起来要繁琐一些),在今后的学习中慢慢补充了。

列表视图(List View)

列表视图是一种很常见的视图,用于展示相同布局的数据列表,可以类比为网页中的ul,ol等,但是实现列表视图要麻烦一些:

  • 列表视图只是一个容器,需要额外定义列表内部每个条目的布局,可以类比为li
  • 列表视图需要用数据去填充,数据需要通过适配器ArrayAdapter转换才能传递给ListView

因此,实现列表视图的工作主要就是上面两步。

定义布局 由于数据只是准备了最简单的字符串数组,因此一个TextView就够了

xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dp"
    android:textSize="16sp" >
</TextView>

数据适配 在实际的项目中,对应的列表数据一般会复杂一点,因此适配器一般是需要自定义的,不过这里的单条数据只是一个字符串,因此食用内置的ArrayAdapter就可以了

java
private String[] COUNTRIES = new String[] { "1", "2", "3", "4", "5"};

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // mylist布局上存在一个ListView容器,其id为list_view
        setContentView(R.layout.mylist);

        // 数据适配,listitem就是列表条目的布局
        ArrayAdapter<String> adpt = new ArrayAdapter<String>(this, R.layout.listitem, COUNTRIES);
        // 为ListView设置适配器
        ListView lv = (ListView) findViewById(R.id.list_view);
        lv.setAdapter(adpt);
    }

貌似内置了一个ListActivity类,可以将上面的操作进行简化,这里就不展开了。此外,在很多时候内置的适配器并不能满足我们的需求(一个条目可能会展示相当多的信息),因此需要自定义适配器,这里有不少坑我打算开另外一篇文章了,先挖个坑。

网格视图(Grid View)

以二维的、滚动的网格显示它的子视图(view)元素

布局

在web端有浮动布局,定位布局,表格布局,网格布局,flex布局等,在安卓上也有类似的概念,并且在实现上比网页要简单得多(或者说“死板”很多)。

线性布局(Linear Layout)

线性布局是一个以线性方向显示它的子视图元素的布局,可以类比网页中的flex来理解(我现在十分怀疑flex布局是不是参考这个线性布局的。)

需要掌握的几个布局属性是

  • orientation: horizontal | vertical,指定布局的方向,跟flex-direction类似
  • layout_weight: number,指定视图的尺寸权重值,跟flex-growflex-shrink属性类似,默认为0
  • layout_gravity: top | center | bottom,指定控件在布局中的对齐方式(该属性受布局方向的影响),跟justify-content类似

安卓的布局中,屏幕适配是一个很大的问题,因此在布局中最好使用自适应而非固定的尺寸,线性布局是最常用的布局。

相对布局(Relative Layout)

相对布局是一个以相对位置显示它的子视图元素的布局,所谓的相对位置既可以是相对于父元素的位置(上下左右),也可以是相对于兄弟视图的位置(各种对齐)。可以参考网页中的position:relative相对定位来理解,区别在于参照物不同

  • 在网页中,相对定位是相对于自身原本在文档流中的位置
  • 在安卓中,相对定位需要显示指定参照对象,然后设置对应偏移属性

需要掌握的几个布局属性是

  • layout_alignParentLeft/Top/Right/Bottom: true | false,是否靠近父元素对应的边,如果在两个相反的方向上都设置为真,则会拉长对应控件的尺寸
  • layout_centerInParent/Horizontal/Vertical: true | false,在对应方向上居中,这个比网页要简单得多
  • layout_above/below/toRightOf/toLeftOf: @id/siblingViewId,相对定位于兄弟元素对应方位
  • layout_alignLeft/Right/Top/Bottom: @id/siblingViewId,让两个控件对应边对齐

这样的话如果参照控件的位置发生改变,那是不是所有后续元素的布局都会改变呢?

表格布局(Table Layout)

使用行和列标识一个元素的位置,跟网页中的表格基本类似,跟web中早已被抛弃的表格布局类似,安卓中的表格布局也不是很常用。

需要掌握的几个布局属性:

  • shinkColumns: true | false设置表格是否收缩
  • <TableRow></TableRow>定义行
  • layout_column/span,定义控件的列数索引,以及该空间可以占的列宽(几列)

其他布局

帧布局(Frame Layout) 最简单的布局,没有任何定位方式,所有的控件都摆放在左上角

绝对布局(Absolute Layout) 以坐标的方式来定位在屏幕上位置,直接设置View的坐标,感觉跟position:fixed应该挺像的,这个布局现在官方已经不推荐使用。

标签布局(Table Layout) 是一个ViewGroup以标签的方式显示它的子视图(view)元素,就像在Firefox中的一个窗口中显示多个网页一样。

布局复用

安卓本身就提供了组件化开发的思想,因此有不少可以减少布局文件上代码重复问题的方法。

引入布局

可以在一个layout中引入另外一个layout,回想在ThinkPHP中引入公共模板的方式,预先定义一个模板片段,然后在对应的页面中使用<include />标签引入,在安卓中同样可以

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

自定义控件

通过继承View类或者某个控件子类,我们可以自定义相关的控件

java
public class TitleLayout extends LinearLayout {
    public TitleLayout(Context context, AttributeSet attrs){
        super(context, attrs);
        // R.layout.title 是对应的布局清单
        LayoutInflater.from(context).inflate(R.layout.title, this);
    }
}

然后在对应的layout中引入就可以了,需要注意的是这里需要指明控件的完整类名和包名

xml
<com.example.admin.myapplication.TitleLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
</com.example.admin.myapplication.TitleLayout>

这跟上面直接引入布局的效果是相同的,但是为什么还要使用自定义控件呢?因为,自定义控件可以封装相同的事件处理函数及相关逻辑,在布局被大量复用的情况下比单单引入布局然后再每个活动中去注册相关的事件要省事多了。

布局编辑器

Android Studio 提供了一个可视化的 XML 布局编辑器,可以方便地创建和编辑 Android 应用程序中的布局文件。

以下是使用 Android Studio 的 XML 布局编辑器的步骤:

  • 打开 Android Studio,并创建一个新的 Android 项目。
  • 在项目结构中选择“app/layout”文件夹,然后在里面创建一个新的布局文件。例如,可以创建一个名为“activity_main.xml”的布局文件。
  • 在 Android Studio 中打开该布局文件,可以看到一个可视化的界面,其中包含了各种视图元素和属性。
  • 在布局文件中添加视图元素,例如文本框、按钮、图片等。可以使用拖拽的方式将视图元素从工具箱中拖到画布上,也可以手动输入视图元素的 ID、名称、类型等属性。
  • 设置视图元素的位置和大小,可以使用约束条件来控制视图元素的位置和大小。例如,可以使用“top”和“bottom”属性来设置视图元素的位置关系,使用“width”和“height”属性来设置视图元素的大小。
  • 保存布局文件并运行应用程序,可以在 Android Studio 中预览应用程序的布局效果。
  • 如果需要自定义布局文件,可以在布局文件中添加自定义视图元素或修改现有视图元素的属性。
  • 在 Android Studio 中生成 R 文件并将其编译为本地代码,以便在应用程序中使用布局文件。

可以找一些官方教学视频配置使用,效率更高

小结

关于安卓布局这块暂时就整理到这里,由于只是这两天大致过了一遍,难免有很多遗漏和理解错误的地方,后面再回来补充吧。

总之,先快速了解安卓整体结构再继续深入。另外,我还专门在github开了一个项目记录相关的demo

你要请我喝一杯奶茶?

版权声明:自由转载-非商用-保持署名和原文链接。

本站文章均为本人原创,参考文章我都会在文中进行声明,也请您转载时附上署名。