这是我参与「第四届青训营 」笔记创作活动的的第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、 onCreateViewHolder和getItemCount三个方法,其中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的方法。