DrawerLayout和RecycleView | 青训营笔记

106 阅读3分钟

青训营背景.webp 这是我参与「第四届青训营 」笔记创作活动的的第3天
[第四届青训营笔记创作活动]

前言:什么是滑动菜单和RecycleView

滑动菜单可以说是Material Design中最常见的效果之一,许多Google自家的应用都具有滑动菜单的功能。借助google提供的各种工具,我们可以很轻松的实现看起来非常炫酷的功能。

RecycleView是一个google推出的新增组件,比原来旧版的ListView具有更高的效率和更好的扩展性。

一、DrawerLayout

Google的AndroidX库中提供了一个DrawerLayout控件,借助这个控件我们可以很方便的实现滑动菜单,DrawerLayout是一个布局,它允许放置两个子控件,第一个子控件是主屏幕显示的内容,第二个子控件是滑动菜单中显示的内容

<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/version_drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.movie.MovieActivity">

    <!--主屏幕内容-->
   .......
   .......

    <!--滑动菜单内容-->
    <LinearLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="end"
        android:background="@color/white"
        android:clickable="true"
        android:focusable="true"
        android:orientation="vertical">

        ......
        ......

        <com.scwang.smart.refresh.layout.SmartRefreshLayout
            android:id="@+id/refresh_version"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/versionRecycleView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="10dp" />
        </com.scwang.smart.refresh.layout.SmartRefreshLayout>

    </LinearLayout>


</androidx.drawerlayout.widget.DrawerLayout>

在上面的代码里使用了DrawerLayout作为最外层的布局,里面放置了两个子控件,一个是用来展示详细内容的主页面,一个是用来选择选项的滑动菜单。在滑动菜单中嵌入了一个RecycleView来做为显示选项的控件。其中android:layout_gravity="end"这个属性表示滑动菜单在页面结束位置,如果手机是从左到右则放置在右边,反之在左边。

二、为滑动菜单设置点击事件

为了让滑动菜单便于使用,我们可以在在页面中设置一个向导来提示用户点击来打开菜单,并通过设置控件的View对象来打开和关闭滑动菜单,在下面的代码中我使用了ViewBinding来获取滑动菜单的控件实例,并且通过openDrawer方法来打开滑动菜单,openDrawer只有一个参数,填入你需要打开的位置,如果刚刚设置为android:layout_gravity="end"则选择GravityCompat.END属性,如果是start则选择GravityCompat.START,其他属性在GravityCompat类中有一一对应的常量。

class MovieActivity : AppCompatActivity() {
    val viewModel by lazy { ViewModelProvider(this).get(MovieViewModel::class.java) }
    private lateinit var binding: ActivityMovieBinding
    private lateinit var movieAdapter: MovieAdapter
    private lateinit var versionAdapter: VersionAdapter

    companion object {
        fun actionStart(context: Context, type: Int, version: Int? = null) {
            val intent = Intent(context, MovieActivity::class.java).apply {
                putExtra("type", type)
                putExtra("version", version)
            }
            context.startActivity(intent)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMovieBinding.inflate(layoutInflater)
        setContentView(binding.root)

       ......
       ......
       
        binding.topLayout.forwardButton.setOnClickListener {
            //为drawerLayout设置一个打开的向导按钮
            binding.versionDrawerLayout.openDrawer(GravityCompat.END)
        }

       .....
       .....
    }

    override fun onDestroy() {
        super.onDestroy()
    }
}

三、RecycleView的使用

在使用RecycleView之前需要在Gradle中加入AndroidX的RecycleView依赖

dependencies {
    .....
    .....
    implementation 'androidx.recyclerview:recyclerview:1.2.1'
    .....
    .....
}

在布局文件中使用RecycleView的方式在上面DrawerLayout中已经有展示。需要注意的是使用第三方库的控件时需要填入完整的包名

放置好RecycleView之后,我们还需要有一个内容使用的布局,用于展示RecycleView中的元素。

<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="140dp"
    android:layout_margin="12dp"
    app:cardCornerRadius="4dp">

   ......
   ......


</com.google.android.material.card.MaterialCardView>

这里我使用了一个MaterialCardView用做了一个卡片来作为RecycleView中元素的布局

然后需要配置一个适配器来指定RecycleView持有的控件实例和设设置如何绑定数据

class MovieAdapter(private val activity: Activity, private val movieList: List<MovieEntity>) :
    RecyclerView.Adapter<MovieAdapter.ViewHolder>() {

    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        ......
        ......
    }

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

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val movie = movieList[position]
        .......
        .......
    }

    override fun getItemCount() = movieList.size

}

在Adapter中需要指定该Adapter持有的ViewHolder类,然后重写onBindViewHolder onCreateViewHoldergetItemCount三个方法,其中onCreateViewHolder中用来创建viewHolder, onCreateViewHolder中写入数据需要显示时ui交互逻辑,getItemCount放回RecyleView中元素的大小。在内部类 ViewHolder中定义需要获取到的控件实例,主义传入的view可以获得RecycleView其祖先布局和该布局的子控件。

有了Adapter之后就需要在需要绑定的Activity或Fragment中设置RecycleView的配置

//设置recycleView
val layoutManager = LinearLayoutManager(this)
binding.bottomLayout.videoRecyclerView.layoutManager = layoutManager
movieAdapter = MovieAdapter(this, viewModel.movieList)
binding.bottomLayout.videoRecyclerView.adapter = movieAdapter

通过设置RecycleView的layoutManager可以指定滚动控件的布局方式,通过xxxAdapter()来获取一个Adapter实例,并且赋值给RecycleView的adapter属性。之后通过改变RecycleView绑定的list对象中的数据,然后调用movieAdapter.notifyDataSetChanged()方法就可以实现刷新RecycleView的方法。

image.png