Android开发笔记——快速入门(布局与RecycleView组件)

[lab.magiconch.com][福音戰士標題生成器]-1727982825836 标准监督

软件环境:

  • Jetbrains Toolbox
  • Android Sudio 2021.1.1 Bumblebee
  • JDK 17.0.2

[TOC]

请先参考前一篇文章复习一下Kotlin的一些语法。

大部分内容参考了郭霖先生的《第一行代码》,在书的基础上针对目前的实际情况进行实践记录。

线性布局

创建一个ACT,并将xml布局文件修改如下:

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

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button_1" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button2" />

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button3" />

</LinearLayout>

我们在里面添加了三个button,每个的长宽都是:

android:layout_width="wrap_content"
android:layout_height="wrap_content"

并指定了排列方向是:

android:orientation="vertical"

实现效果如下:

2

约束布局

此部分参考了:

作者:四会歌神陈子豪链接:https://www.jianshu.com/p/17ec9bd6ca8a

约束布局ConstraintLayout 是一个ViewGroup,可以在Api9以上的Android系统使用它,它的出现主要是为了解决布局嵌套过多的问题,以灵活的方式定位和调整小部件。从 Android Studio 2.3 起,官方的模板默认使用 ConstraintLayout

RelativeLayout是相对布局,它可以根据各个子组件的相对位置来实现布局,打个比方A、B两个组件,想要使用RelativeLayout来针对B布局,你可以指定B组件在A的右侧,这样就根据相对布局完成了一个组件布局。ConstraintLayout同样也能实现这样的功能,ConstraintLayout使用起来比RelativeLayout更灵活,性能更出色!还有一点就是ConstraintLayout可以按照比例约束控件位置和尺寸,能够更好地适配屏幕大小不同的机型。

ConstraintLayout示例

相对定位

可以看到我们创建了一个布局,其父组件的宽度大小是固定的,长度随文本大小变化而变化:

其中包含了两个组件一个是imageview 还有一个 Textview。

7

我们要通过相对定位来实现二者中心位置对齐:

首先文本框一定是在图片下头的,所以就要把这个属性设置为这样:

app:layout_constraintTop_toBottomOf="@+id/imageView"

constraintTop_toBottomOf这个属性很好理解,第一个constraintTop指的就是这个组建的头位置,toBottomOf就把这个头位置设定到谁的底部。

8

补一张图方便理解,具体还有什么就不再赘述了,详细了解请参考链接,链接写的非常好!。

9

需要注意的是,ConstraintLayout设计出来压根就不是来代替经典如LinearLayout、FrameLayout、GridLayout 等布局,你可以把他看作是RelativeLayout的超级加强版,所以切记不要在典型的线性布局需求中使用ConstraintLayout。经典线性布局的需求意味着子控件之间不需要存在任意依赖关系,任何一个控件拿掉了对整体布局没有任何影响。而你拿着ConstraintLayout对每一个子控件进行依赖,说好比国家拎着一个女人强行让你配对一样。

所以接下来使用组件的时候这两个配合着来用。

RecycleView组件

RecycleView同样也是ListView的增强版,他的设计和使用更加符合逻辑,不再需要更多的优化操作,所以建议抛弃掉ListView,使用RecycleView。

添加依赖

implementation 'androidx.recyclerview:recyclerview:1.2.1'

a-2

在布局中添加RecycleView组件

由于不是系统内置的组件,需要把完整的包名写下来。

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycleView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

让RecycleView组件显示内容

我们需要创建一个布局文件,来规定RecycleView的里面的内容,这里就直接采用上边演示的布局文件,内容很简单,就是一个图片加下边一段文字,接下来我们研究如何将这个布局作为RecycleView的子组件导入到RecycleView之中。

我们首先需要创建一个Adapter类来将数据先转化为子布局的内容再将子布局导入到RecycleView之中。标准写法如下:

class FruitAdapter_Recycle(val  fruitList :List<Fruit>):
    RecyclerView.Adapter<FruitAdapter_Recycle.ViewHolder>()
{
    inner class ViewHolder (view:View):RecyclerView.ViewHolder(view)
    {
        val fruitImage : ImageView = view.findViewById(R.id.imageView)
        val fruitName : TextView = view.findViewById(R.id.textView)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.fruit_item,parent,false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val fruit = fruitList[position]
        holder.fruitImage.setImageResource(fruit.imageId)
        holder.fruitName.text=fruit.name
    }
    override fun getItemCount(): Int = fruitList.size
}

继承了RecyclerView包中的Adapter类,可以看到将泛型指定为FruitAdapter_Recycle.ViewHolder,说明其本就是基于ViewHolder的。这为我们优化省去了不少事情。

inner class ViewHolder (view:View):RecyclerView.ViewHolder(view)
{
    val fruitImage : ImageView = view.findViewById(R.id.imageView)
    val fruitName : TextView = view.findViewById(R.id.textView)
}

内部类ViewHolder使用最RecyclerView的最外层View来作为构造方法的参数,通过导入布局的View会把对应的子项的内容创建好,方便构造对应的ViewHolder。

同时这个类还内置好了其他的方法,我们只需将对应方法重写完成就可以正常使用了。

onCreateViewHolder方法用于创建对应的ViewHolder实例,我们在这个方法中将对应的子布局(fruit_itm)加载进来把构造好的子布局传入到ViewHolder的构造函数当中作为ViewHolder实例返回。

 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder 
{
    val view = LayoutInflater.from(parent.context)
    .inflate(R.layout.fruit_item,parent,false)
    return ViewHolder(view)
 }

onBindViewHolder方法用于对RecycleView中每一个子项进行赋值,在每一个子项进入到屏幕的时候此方法会执行,将对应的数据缓存进来,指定数据的方法很简单通过Position来获取当前的位置然后将数据缓存进去。

  override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val fruit = fruitList[position]
        holder.fruitImage.setImageResource(fruit.imageId)
        holder.fruitName.text=fruit.name
    }

最后getItemCount方法返回Recycle有多少子项。

override fun getItemCount(): Int = fruitList.size

使用Adapter_Recycle载入数据:

载入数据的方法很简单,FruitAdapter_Recycle类的构造函数只需要传入一个List即可,Lsit的数据包含textview要显示的文本和imagebiew现实的图片资源地址:

val fruitList = mutableListOf<Fruit>()
fruitList.add(Fruit("Apple", R.drawable.apple_pic))

每次一个子项滚入到屏幕的时候就会通过onBindViewHolder将数据加载到viewholder里面,然后再显示。

RecycleView的布局与显示

我们在完成数据加载以后,可以意识到一个问就是,没有指定子类的布局,在子项之间应该怎么排序?

RecycleView之中专门有一个成员来管理子类的布局,我们在这就使用线性布局来做演示:

首先创建一个布局管理类:LinearLayoutManager是系统内置的类,可以让需要的组件实现线性布局。

val layoutManager =LinearLayoutManager(this)

当然实现也要实现一点不一样的,Listview是无法实现横向滚动的,咱们就来实现一下,实现方法也很简单,只要把线性布局的方向改为水平即可:

layoutManager.orientation=LinearLayoutManager.HORIZONTAL

最后我们把这个layoutManager传递给recycleview:

binding.recycleView.layoutManager =layoutManager

然后将数据导入:

val adapter = FruitAdapter_Recycle(fruitViewModel.fruitList)
binding.recycleView.adapter=adapter

实现效果:

其中名字较长的是为展现一下约束布局的具体效果而加长的。

img