«

安卓速通(其实是期末复习~)(第三章【ListView有点难搞】)

ZealSinger 发布于 阅读:179 期末复习


Android常见的界面控件⭐️

在安卓应用程序中,都是通过界面控件与用户交互。整个第三章都是考点重点,尤其是前面的简单控件,后面的列表控件和自定义控件感觉因为难度问题占比会少一点

简单控件的使用

TextView控件

TextView控件即文本控件,主要用于显示文本信息,可以在XML布局文件中添加属性的方式控制TextView控件的样式,TextView控件常见属性如下

属性名称 属性描述
android:layout_width 设置控件的宽度
android:layout_height 设置控件的高度
android:id 设置控件的唯一标识
android:background 设置控件背景(颜色or图片)
android:layou_margin 设置当前控件和边界/周围控件/布局的距离
android:padding 设置当前控件和控件中内容之间的距离
android:text 设置控件的内容
android:textSize 设置控件文本字体大小 推荐单位sp
android:textColor 设置控件文本字体颜色
android:gravity 设置控件文本内容的位置,例如设置center标识居中展示
android:maxLength 设置控件文本最大长度,超过该长度的内容不予显示
android:lines 设置控件文本行数,超出此行数的文本不予显示
android:ellipsize 设置当文本内容超出控件规定范围的时候的显示方式,属性值一般为start/middl/end 分别代表在文本头部/中间/尾部显示省略号....
android:drawableTop 设置图片资源在文本的上方,图片资源可以通过@drawable/文件名引用 同理drawableBottom ; drawableRight ; drawableLeft
android:lineSpacingExtra 设置控件文本的行间距
android:textStyle 设置控件文本样式。例如bold粗体 , italic斜体,normal正常
<?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"
   xmlns:tools="http://schemas.android.com/tools"
   tools:context=".MainActivity">

   <TextView
       android:id="@+id/textView"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:textSize="20sp"
       android:textStyle="bold"
       android:maxLength="2"
       android:text="粗体啊啊" />

   <TextView
       android:layout_marginTop="100dp"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:textColor="@color/black"
       android:textSize="40sp"
       android:textStyle="italic"
       android:ellipsize="end"
       android:maxLines="1"
       android:text="斜体且超出了范围啊啊啊啊啊啊啊啊" />

   <TextView
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_marginTop="300dp"
       android:lineSpacingExtra="10dp"
       android:text="正常文字有10dp的行距啊啊啊啊"
       android:textSize="35sp" />

   <TextView
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_marginTop="450dp"
       android:text="正常文字但是没有行距啊啊啊啊"
       android:textSize="35sp" />
</RelativeLayout>

image-20250514155521597

需要注意的是,TextView组件也可以通过Java/Kotlin代码的形式进行创建和饿属性赋值

EditText控件

简单而言就是可编辑文本框控件,属于TextView的子类,支持通用属性和TextView的属性,以及自己特有的属性

属性名称 属性描述
android:hint 控件中文本内容为空的时候默认显示的内容
android:textColorHint 控件中文本内容为空的时候默认显示的内容的颜色
android:password 控件内容按照密码展示,即文本内容只会展示"."
android:phoneNumber 控件内容只能输入数字
android:minLines 控件内容最小行数
android:scrollHorizontally 控件文本内容超出EditText宽度的情况下是否出现横拉条
android:editable 是否可编辑
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="match_parent"
   android:layout_height="match_parent">
   <EditText
       android:layout_width="200dp"
       android:layout_height="50dp"
       android:background="@color/teal_200"
       android:hint="可以输入任何内容"
       android:textColorHint="@color/purple_500"
       />

   <EditText
       android:layout_marginTop="50dp"
       android:layout_width="200dp"
       android:layout_height="50dp"
       android:background="@color/teal_200"
       android:maxLines="1"
       android:hint="只能输入数字且滑块"
       android:phoneNumber="true"
       android:scrollHorizontally="true"
       android:textColorHint="@color/purple_500"
       />

   <EditText
       android:layout_marginTop="50dp"
       android:layout_width="200dp"
       android:layout_height="50dp"
       android:background="@color/teal_200"
       android:hint="密码保护"
       android:password="true"
       android:textColorHint="@color/purple_500"
       />

</LinearLayout>

image-20250514170935194

Button控件点击事件的绑定

Button控件即按钮控件,继承自TextView,既可以显示文本,又可以显示图片,又可以处理点击事件,当按钮控件被点击的时候,被按下与弹起的背景会有一个动态的切换效果,这个就是按钮控件默认的一个点击效果,但是实际上,所有的控件都可以设置点击事件,只是Button更多一点,所以我们对于Button控件主要学习的也就是事件绑定,实现事件绑定有三种方法分别是Button控件配置onClick属性 ; 绑定监听 ; Activity实现监听接口

配置onClick事件

Button控件通过onClick属性的属性值来设置事件点击事件,代码如下

<Button android:onClick="...."  
......
/>

其中....对应的就是事件名称,我们可以在Activity中定义对应的方法函数逻辑来实现对应的事件逻辑,需要注意的是,Activity中的方法/函数名必须和onClick中设置的属性值 .... 是一样的名字,就能保证跳转到对应的事件中

image-20250514174738221

绑定监听

即在Button中不设置onClick属性,而是通过对于Button对象设置监听器和回调函数,从而当按钮被点击的时候进行逻辑回调,这个是比较推荐的方式,因为如今android:onClick属性已经快被Android弃用

对应的MainActivity代码

class MainActivity : ComponentActivity(),OnClickListener {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       enableEdgeToEdge()
       setContent {
           KtAndroisTheme {
               Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                   Greeting(
                       name = "Android",
                       modifier = Modifier.padding(innerPadding)
                  )
              }
          }
      }
  }

   fun clickFun(view: View) {
       // Toast类似于print打印 可以在安卓程序的最顶层展示内容 暂且知道有这个东西和使用 后面会讲
       Toast.makeText(this, "按钮被点击了!", Toast.LENGTH_SHORT).show()
  }

   override fun onClick(v: View?) {
       when(v?.id){
           R.id.button->{
               v.findViewById<Button>(R.id.button).setText("已经被点击了")
          }
      }
  }
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
   Column(modifier = modifier) {
       // 新增 XML 布局
       AndroidView(
           factory = { context ->
               // 加载 XML 布局
               val view = View.inflate(context, R.layout.relativelayouttext, null)
               // createRelativeLayout(context)
               val button= view.findViewById<Button>(R.id.button)
               button.setOnClickListener {
                   Toast.makeText(context, "按钮被点击了!", Toast.LENGTH_SHORT).show()
              }
               view
          },
           modifier = Modifier.padding(20.dp)
      )
  }
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
   KtAndroisTheme {
       Greeting("Android")
  }
}

image-20250514175757031

Activity实现onClickListenter接口

对应MainActivity代码

class MainActivity : ComponentActivity(),OnClickListener {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       enableEdgeToEdge()
       setContent {
           KtAndroisTheme {
               Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                   Greeting(
                       name = "Android",
                       modifier = Modifier.padding(innerPadding)
                  )
              }
          }
      }
  }

   override fun onClick(v: View?) {
       when(v?.id){
           R.id.button->{
               v.findViewById<Button>(R.id.button).setText("已经被点击了")
          }
      }
  }
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
   Column(modifier = modifier) {
       // 新增 XML 布局
       AndroidView(
           factory = { context ->
               // 加载 XML 布局
               val view = View.inflate(context, R.layout.relativelayouttext, null)
               // createRelativeLayout(context)
               val button= view.findViewById<Button>(R.id.button)
               button.setOnClickListener(view.context as MainActivity)
               view
          },
           modifier = Modifier.padding(20.dp)
      )
  }
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
   KtAndroisTheme {
       Greeting("Android")
  }
}

image-20250514181305427

ImageView控件

ImageView即图片控件继承自View控件,主要用于加载各种图片资源,常用属性如下

属性名称 属性描述
android:layout_width 设置控件宽度
android:layout_height 设置控件高度
android:id 设置控件唯一标识
android:background 设置控件背景
android:layout_margin 设置控件和周围控件/布局边界的距离
android:src 设置控件要显示的图片资源路径
android:scaleType 将图片资源缩放或者移动,以适应控件的宽高
android:tint 将图片渲染成指定颜色
<?xml version="1.0" encoding="utf-8"?>
<!--最外层布局采用RelativeLayout相对布局-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent">

   <!--
android:scaleType="fitStart" 让图片和布局顶部进行对齐
没有这个属性的话 默认是居中的

android:background="@color/purple_200"
即将没有图片的地方填充为指定颜色

还有一个没用到的android:tint 其实就是将图片用某个颜色完全填充覆盖
--->
   <ImageView
       android:layout_width="400dp"
       android:layout_height="400dp"
       android:background="@color/purple_200"
       android:src="@drawable/cmd2"
       android:scaleType="fitStart"  
       />

</RelativeLayout>

image-20250514182506537

RadioButton控件

RaioButton控件是单选控件,是Button控件的子类,常常与RadioGroup组合使用,RadioGroup继承自LinearLayout,所以可以通过android:orientation 属性决定每个选项是竖着排列or水平排列。每个单选按钮都具备 “选中” 和 “未选中” 两个状态,android:checked属性决定是否选中状态 true则为选中

一个RadioGroup代表一个单选组合框(或者理解一个单选题目),包含多个RadioButton(理解为选项),一个RadioGroup中一定只会有一个RadioButton处于选中状态,组合使用格式一般如下

<?xml version="1.0" encoding="utf-8"?>
<!--最外层布局采用RelativeLayout相对布局-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent">

   <RadioGroup
       android:layout_width="200dp"
       android:layout_height="200dp">

       <RadioButton
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="选项一"
           android:textSize="20sp"
           />

       <RadioButton
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="选项二"
           android:textSize="20sp"
           />
   </RadioGroup>

   <RadioGroup
       android:layout_width="200dp"
       android:layout_height="200dp"
       android:layout_marginTop="100dp"
       android:orientation="horizontal"
       >

       <RadioButton
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="A"
           android:textSize="20sp"
           />

       <RadioButton
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="B"
           android:textSize="20sp"
           />
   </RadioGroup>

</RelativeLayout>

样式属性上不是很多要讲的,可以看一下因为是继承了LinearLayout所以选项一和选项二是竖直排序而AB是水平排序

image-20250514201537996

RadioButton是Button的子类,所以其能绑定事件,这个也是其最重要的一点点,RadioGroup通过setOnCheckedChageListener()方法进行绑定事件

package com.example.ktandrois

import android.content.Context
import android.os.Bundle
import android.view.View
import android.view.View.OnClickListener
import android.widget.Button
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.RelativeLayout
import android.widget.TextView
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.ktandrois.ui.theme.KtAndroisTheme
import androidx.compose.foundation.layout.Column
import androidx.compose.ui.viewinterop.AndroidView

class MainActivity : ComponentActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       enableEdgeToEdge()
       setContent {
           KtAndroisTheme {
               Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                   Greeting(
                       name = "Android",
                       modifier = Modifier.padding(innerPadding)
                  )
              }
          }
      }
  }
   // 处理 RadioGroup 选择事件 根据选择的checkId进行打印展示
   private fun listenerHandler(checkedId: Int) {
       val message = when (checkedId) {
           R.id.g1b1 -> "您在 g1 选择了选项一"
           R.id.g1b2 -> "您在 g1 选择了选项二"
           R.id.g2b1 -> "您在 g2 选择了 A"
           R.id.g2b2 -> "您在 g2 选择了 B"
           else -> return
      }
       Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
  }

   // 统一监听器,当发生选择事件 就会获取RadioGroup的groupId和对应的选项的id
   private val checkedChangeListener = RadioGroup.OnCheckedChangeListener{
       group, checkedId -> listenerHandler(checkedId)
  }
   fun getCheckedChangeListener():RadioGroup. OnCheckedChangeListener{
       return checkedChangeListener
  }
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
   Column(modifier = modifier) {
       // 新增 XML 布局
       AndroidView(
           factory = { context ->
               // 加载 XML 布局
               val view = View.inflate(context, R.layout.relativelayouttext, null)
               // createRelativeLayout(context)
               var group1 = view.findViewById<RadioGroup>(R.id.g1)
               var group2 = view.findViewById<RadioGroup>(R.id.g2)
               var activity = context as MainActivity
                      // activity.getCheckedChangeListener()通过这个方法统一获得上面定义的 checkedChangeListener 这个监听器
               group1.setOnCheckedChangeListener(activity.getCheckedChangeListener())
               group2.setOnCheckedChangeListener(activity.getCheckedChangeListener())
               view
          },
           modifier = Modifier.padding(20.dp)
      )
  }
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
   KtAndroisTheme {
       Greeting("Android")
  }
}

image-20250514204503315

checkBox控件

CheckBox控件表示复选框,是Button控件的子类,用于实现多选功能,每个选项都具备 选中和未选中 两种状态, 状态都是通过 android:checked属性指定的,true则为选中true则为选中

对于CheckBox的选择事件,也是通过OnCheckedChangeListener方法进行监听,通过setCheckedChangeListener进行绑定

需要注意的是checkBox就是多选中的单个选项,不存在checkGroup这种包含性的父标签

如下 实现多选的动态展示代码

package com.example.ktandrois

import android.content.Context
import android.os.Bundle
import android.view.View
import android.view.View.OnClickListener
import android.widget.Button
import android.widget.CheckBox
import android.widget.CompoundButton
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.RelativeLayout
import android.widget.TextView
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.ktandrois.ui.theme.KtAndroisTheme
import androidx.compose.foundation.layout.Column
import androidx.compose.ui.viewinterop.AndroidView
import org.w3c.dom.Text

class MainActivity : ComponentActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       enableEdgeToEdge()
       setContent {
           KtAndroisTheme {
               Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                   Greeting(
                       name = "Android",
                       modifier = Modifier.padding(innerPadding)
                  )
              }
          }
      }
  }

   private val likeList:MutableSet<String> = mutableSetOf()

   private fun handler(buttonView: View,isChecked: Boolean){
       var checkBox = buttonView as CheckBox
       var boxContent = checkBox.text.toString()
       var hobbyText = this.findViewById<TextView>(R.id.hobbyText)
       if(isChecked){  // 为true则说明被选中 加入到likeList中
           likeList.add(boxContent)
           hobbyText.setText("你选择的是:${likeList}")
      }else{
           likeList.remove(boxContent)
           hobbyText.setText("你选择的是:${likeList}")
      }
  }

   private val checkedChangeListener = CompoundButton.OnCheckedChangeListener{
       buttonView, isChecked -> handler(buttonView,isChecked) // buttoView就是对应的每个checkBox isChecked就是该checkBox是否被选
  }

   fun getListener(): CompoundButton. OnCheckedChangeListener{
       return checkedChangeListener
  }
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
   Column(modifier = modifier) {
       // 新增 XML 布局
       AndroidView(
           factory = { context ->
               // 加载 XML 布局
               val view = View.inflate(context, R.layout.relativelayouttext, null)
               val activity = context as MainActivity
               // createRelativeLayout(context)
               view.findViewById<CheckBox>(R.id.lq).setOnCheckedChangeListener(activity.getListener())
               view.findViewById<CheckBox>(R.id.ymq).setOnCheckedChangeListener(activity.getListener())
               view.findViewById<CheckBox>(R.id.ppq).setOnCheckedChangeListener(activity.getListener())
               view
          },
           modifier = Modifier.padding(20.dp)
      )
  }
}


@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
   KtAndroisTheme {
       Greeting("Android")
  }
}

image-20250514211819792

Toast类

Toast类是安卓提供的轻量级提醒机制,可以在整个程序界面的最上层展示用于提醒用户,我们上面的代码中其实有使用过了已经

其函数原型为

Toast.makeText(Context,String Text,Time).show()

列表控件ListView

列表控件ListView主要是能以列的形式展示数据,并且能根据屏幕高度自适应的显示,在安卓开发中常用

其常用属性为

属性名称 属性描述
android:listSelector 当条目被点击后,改变条目的背景颜色
android:divider 设置分割线的颜色
android:dividerHeight 设置分割线高度
android:scrollbars 是否显示滚动条
android:fadingEdge 去掉上边和下边的黑色阴影

如图可以看到 在默认状态下 ListView就展示出了他的特点,多条目

image-20250514213602552

适配器

如上所示,ListView有很多条目,我们会需要将我们的数据添加到ListView中会需要用到数据适配器Adpater,数据适配器作为数据和视图之间的桥梁,类似一个转化器,将复杂的数据转化为用户可以接受的方式呈现,安卓配备了多个对ListView的数据适配器

RecycleView控件

RecycleView控件的作用是在有限的空间内展示大量数据 安卓5.0之后才出现的新特性,有点类似于ListView控件

RecyclerView可以通过LayoutManager类实现横向,竖向的列表效果,瀑布流效果和GridView效果,比ListView强大 ;

在数据适配器上使用的是RecyclerView.Adapter适配器,该适配器在BaseAdapter适配器上将getView方法进行了拆分为了onCreateViewHolder和onBindViewHolder两个方法,强制使用ViewHolder类,规范性更强

RecycleView控件复用 Item对象的工作由空间自己实现而ListView的复用Item工作由开发者优化实现

RecycleView可以给Item对象添加动画效果而ListView不可以

(书上说了这些之后就是直接案例了 所以直接过 也不多说了,感觉唯一可能的考点就是RecycleView和listView的区别

自定义控件

我们知道控件本质上是View类对象,所以实际上自定义控件就是继承View类从而实现拓展,满足自定义需求

实现一个类一般就要重写父类的方法,一般需要重写的就是onMeasure()方法 , onDraw()方法 和 onLayout()方法

Android Kotlin 期末复习 编程



收到3条评论
avatar
大帅哥 1 个月前
大佬快更新
回复
commentator
ZealSinger 1 个月前
@大帅哥:666
回复
avatar
大帅哥 1 个月前
大佬快更新
回复