第一行代码第三版——第四章:UI 开发的点点滴滴

软件也要拼脸蛋,UI 开发的点点滴滴

该如何编写程序界面

在过去,Android 应用程序的界面主要是通过编写 XML 的方式来实现的。写 XML 的好处是,我们不仅能够了解界面背后的实现原理,而且编写出来的界面还可以具备很好的屏幕适配性。等你完全掌握了使用 XML 来编写界面的方法之后,不管是进行高复杂度的界面实现,还是分析和修改当前现有的界面,对你来说都将是手到擒来。

不过最近几年,Google 又推出了一个全新的界面布局:ConstraintLayout。和以往传统的布局不同,ConstraintLayout 不是非常适合通过编写 XML 的方式来开发界面,而是更加适合在可视化编辑器中使用拖放控件的方式来进行操作,并且 Android Studio 中也提供了非常完备的可视化编辑器。

虽然现在 Google 官方更加推荐使用 ConstraintLayout 来开发程序界面,但由于 ConstraintLayout 的特殊性,很难展示如何通过可视化编辑器来对界面进行动态操作。因此本书中我们仍然采用编写 XML 的传统方式来开发程序界面,并且这也是我认为你必须掌握的基本技能。

讲了这么多理论的东西,也是时候学习一下到底如何编写程序界面了,我们就从 Android 中几种常见的控件开始吧。

常用控件的使用方法

Android 给我们提供了大量的 UI 控件,合理地使用这些控件就可以非常轻松地编写出相当不错的界面,下面我们就挑选几种常用的控件,详细介绍一下它们的使用方法。

首先新建一个 UIWidgetTest 项目。简单起见,我们还是允许 Android Studio 自动创建 Activity,Activity 名和布局名都使用默认值。

TextView

TextView 的基本用法很简单,这里就不讲解了。这里我们来讲解一个类 SpannableString, SpannableString 其实和 Sring 一样,Textview 可以直接通过设置 SpannableString 来显示文本,只是 SpannableString 可以显示更多的样式风格,我们来看这样一个效果,给一段文本设置下划线,只有下划线的地方可以点击,这样一个效果只用 TextView 是无法实现的,但是用 SpannableString 就很简单了。

第一行代码第三版——第四章:UI 开发的点点滴滴_第1张图片

我们来实现一下这个效果,布局代码很简单,如下所示:

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

    <TextView
        android:id="@+id/tv_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="15sp" />
LinearLayout>

MainActivity.kt 的代码如下所示:

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

        setSpecialEffect()
    }

    private fun setSpecialEffect() {
   
        tv_1.text = "已阅读并同意 "

        val clickString = SpannableString("软件许可及服务协议")
        clickString.setSpan(object : ClickableSpan() {
   
            override fun onClick(widget: View) {
   
                Toast.makeText(this@MainActivity, "点击了下划线部分内容", Toast.LENGTH_SHORT).show()
            }

            override fun updateDrawState(ds: TextPaint) {
   
                super.updateDrawState(ds)
                // 设置颜色
                ds.color = resources.getColor(R.color.purple_200, null) 
            }
        }, 0, clickString.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)

        tv_1.append(clickString)
        // 设置点击效果
        tv_1.highlightColor = Color.TRANSPARENT
        // 开始响应点击事件
        tv_1.movementMethod = LinkMovementMethod.getInstance() 
    }
}

我们来运行程序看一下效果:

第一行代码第三版——第四章:UI 开发的点点滴滴_第2张图片

当然 SpannableString 的可以设置的效果还有很多,有兴趣的可以去查看资料。

Button

同样,Button 的基本用法很简单,我们也不讲,我们来讲如何给 Button 设置一个点击效果,我们先来看看具体是怎么个效果,如下所示,点击按钮的时候,有一个反馈:

第一行代码第三版——第四章:UI 开发的点点滴滴_第3张图片

我们来实现一下这个效果,要想实现这个效果我们只需要在 drawable 下写一个背景选择器 selector 就可以了,具体代码如下:


<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape>
            <solid android:color="@color/purple_200_alpha"/>
        shape>
    item>
    <item>
        <shape>
            <solid android:color="@color/purple_200"/>
        shape>

    item>
selector>

然后在布局文件中设置 background 就可以实现点击效果了,具体代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:gravity="center"
    android:orientation="vertical">

    <Button
        style="?android:attr/borderlessButtonStyle"
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:background="@drawable/button_bg"
        android:text="登录"
        android:textSize="18sp" />
        
LinearLayout>

我们来运行一下看一下效果:

第一行代码第三版——第四章:UI 开发的点点滴滴_第4张图片

EditText

EditText 是程序用于和用户进行交互的另一个重要控件,它允许用户在控件里输入和编辑内容,并可以在程序中对这些内容进行处理。EditText 的应用场景应该算是非常普遍了,发短信、发微博、聊 QQ 等等,在进行这些操作时,你不得不使用到 EditText。那我们来看一看如何在界面上加入 EditText 吧,如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:orientation="vertical">

    <EditText
        android:id="@+id/et_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="type something here"
        android:textColorHint="@color/purple_200" />
    
LinearLayout>

看到这里,估计你已经总结出 Android 控件的使用规律了。用法都很相似,给控件定义一个 id,指定控件的宽度和高度,然后再适当加入些控件特有的属性就差不多了,所以使用 XML 来编写界面其实一点都不难。现在运行一下程序,EditText 就已经在界面上显示出来了,并且我们是可以在里面输入内容的。

ImageView

ImageView 是用于在界面上展示图片的一个控件,它可以让我们的程序界面变得更加丰富多彩。图片通常是放在以 drawable 开头的目录下的,并且要带上具体的分辨率。现在最主流的手机屏幕分辨率大多是 xxhdpi 的,所以我们在 res 目录下再新建一个 drawable-xxhdpi 目录,然后将事先准备好的图片复制到该目录当中就可以使用 ImageView 控件来将它们显示在界面上。

常用的控件肯定不止上面这几种,但是用起来都比较简单,所以这里就不讲了。

最常用和最难用的控件: ListView

ListView 在过去绝对可以称得上是 Android 中最常用的控件之一,几乎所有的应用程序都会用到它。由于手机屏幕空间比较有限,能够一次性在屏幕上显示的内容并不多,当我们的程序中有大量的数据需要展示的时候,就可以借助 ListView 来实现。ListView 允许用户通过手指上下滑动的方式将屏幕外的数据滚动到屏幕内,同时屏幕上原有的数据会滚动出屏幕。你其实每天都在使用这个控件,比如查看 QQ 聊天记录,翻阅微博最新消息,等等。不过比起前面介绍的几种控件,ListView 的用法相对复杂了很多,因此我们就单独来对 ListView 进行非常详细的讲解。

ListView 的简单用法

首先新建一个 ListViewTest 项目,并让 Android Studio 自动帮我们创建好 Activity。然后修改 activity_main.xml 中的代码,如下所示:


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

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

LinearLayout>

在布局中加入 ListView 控件还算非常简单,先为 ListView 指定一个 id,然后将宽度和高度都设置为 match_parent,这样 ListView 就占满了整个布局的空间。

接下来修改 MainActivity 中的代码,如下所示:

class MainActivity : AppCompatActivity() {
   

    private val data = listOf("Apple", "Banana", "Orange", "Watermelon",
            "Pear", "Grape", "Pineapple", "Strawberry", "Cherry", "Mango",
            "Apple", "Banana", "Orange", "Watermelon", "Pear", "Grape",
            "Pineapple", "Strawberry", "Cherry", "Mango")

    override fun onCreate(savedInstanceState: Bundle?) {
   
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data)
        listView.adapter = adapter
    }

}

既然 ListView 是用于展示大量数据的,那我们就应该先将数据提供好。这些数据可以从网上下载,也可以从数据库中读取,应该视具体的应用程序场景而定。这里我们就简单使用一个 data 集合来进行测试,里面包含了很多水果的名称,初始化集合的方式使用的是 listOf() 函数。

不过,集合中的数据是无法直接传递给 ListView 的,我们还需要借助适配器来完成。Android 中提供了很多适配器的实现类,其中我认为最好用的就是 ArrayAdapter。它可以通过泛型来指定要适配的数据类型,然后在构造函数中把要适配的数据传入。ArrayAdapter 有多个构造函数的重载,你应该根据实际情况选择最合适的一种。由于我们这里提供的数据都是字符串,因此将 ArrayAdapter 的泛型指定为 String,然后在 ArrayAdapter 的构造函数中依次传入 Activity 的实例、ListView 子项布局的 id,以及数据源。注意,我们使用了 android.R.layout.simple_list_item_1 作为 ListView 子项布局的 id,这是一个 Android 内置的布局文件,里面只有一个 TextView,可用于简单地显示一段文本。这样适配器对象就构建好了。

最后,还需要调用 ListView 的 setAdapter() 方法,将构建好的适配器对象传递进去,这样 ListView 和数据之间的关联就建立完成了。

现在运行一下程序,效果如下图所示,

你可能感兴趣的:(第一行代码第三版,android,kotlin)