这是我参与「第四届青训营 」笔记创作活动的第5天
今天来实现一下Fragment的实践内容
本笔记参考自《第一行代码》
在进行实践之前,先来回顾一下Fragment的基础知识
Fragment:是一种可以嵌入在Activity当中的UI片段,可以被看作是“迷你版”的activity,可以和Activity进行交互操作- Fragment的生命周期(类比Activity):
- 运行状态
- 暂停状态
- 停止状态
- 销毁状态
Fragment总是依附于Activity而存在,当一个Fragment所关联的Activity处于运行、暂停、停止、销毁状态时,Fragment也处于相同的状态。
Activity中的回调方法,Fragment中基本上也有,不过Fragment还提供了一些附加的回调方法:
- onAttach():当Fragment和Activity建立关联时调用。
- onCreateView():为Fragment创建视图(加载布局)时调用。
- onActivityCreated():确保与Fragment相关联的Activity已经创建完毕时调用。
- onDestroyView():当与Fragment关联的视图被移除时调用。
- onetach():当Fragment和Activity解除关联时调用。
实践部分-一个简单的新闻app
主要步骤如下:(此处只讲述双页展示部分)
graph TD
简易版新闻应用-->添加RecycleView的依赖库和新建类news
添加RecycleView的依赖库和新建类news--> 新建布局文件news_content_frag,xml
新建布局文件news_content_frag,xml-->将新闻内容布局设置为不可见
新建布局文件news_content_frag,xml-->新建一个NewsContentFragment类
新建一个NewsContentFragment类-->创建一个用于显示新闻列表的布局
创建一个用于显示新闻列表的布局-->新建news_item.xml作为RecyclerView子项的布局
创建一个用于显示新闻列表的布局-->新建NewsTitleFragment作为展示新闻列表的Fragment
新建NewsTitleFragment作为展示新闻列表的Fragment-->在NewsTitleFragment中新建一个内部类NewsAdapter来作为RecyclerView的适配器
在NewsTitleFragment中新建一个内部类NewsAdapter来作为RecyclerView的适配器-->向RecyclerView中填充数据
在app/build.gradle当中添加RecycleView的依赖库和新建类news之后,新建布局文件news_content_frag,xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/contentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="invisible" >
<TextView
android:id="@+id/newsTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="10dp"
android:textSize="20sp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#000" />
<TextView
android:id="@+id/newsContent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="15dp"
android:textSize="18sp" />
</LinearLayout>
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:background="#000" />
</RelativeLayout>
新闻内容的布局主要可以分为两个部分:头部部分显示新闻标题,正文部分显示新闻内容,中 间使用一条水平方向的细线分隔开。除此之外,这里还使用了一条垂直方向的细线,它的作用 是在双页模式时将左侧的新闻列表和右侧的新闻内容分隔开。细线是利用View来实现的,将View的宽或高设置为1 dp,再通过background属性给细线设置一下颜色就可以了,这里我们 把细线设置成黑色
将新闻内容的布局设置为不可见,因为如果如果还没有选中新闻列表中的任何一条新闻,是不应该显示新闻内容布局的。
接下来新建一个NewsContentFragment类,继承自Fragment
class NewsContentFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.news_content_frag, container, false)
}
fun refresh(title: String, content: String) {
contentLayout.visibility = View.VISIBLE
newsTitle.text = title // 刷新新闻的标题
newsContent.text = content // 刷新新闻的内容
}
}
- 创建一个用于显示新闻列表的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/newsTitleRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
-
新建news_item.xml作为RecyclerView子项 的布局
-
新建NewsTitleFragment作为展示新闻列表的Fragment
class NewsTitleFragment : Fragment() {
private var isTwoPane = false
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.news_title_frag, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
isTwoPane = activity?.findViewById<View>(R.id.newsContentLayout) != null
}
}
- 重要的一步在NewsTitleFragment中通过RecyclerView将新闻列表展示出来,我们在NewsTitleFragment 中新建一个内部类NewsAdapter来作为RecyclerView的适配器
class NewsTitleFragment : Fragment() {
private var isTwoPane = false
...
inner class NewsAdapter(val newsList: List<News>) :
RecyclerView.Adapter<NewsAdapter.ViewHolder>() {
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val newsTitle: TextView = view.findViewById(R.id.newsTitle)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.news_item, parent, false)
val holder = ViewHolder(view)
holder.itemView.setOnClickListener {
val news = newsList[holder.adapterPosition]
if (isTwoPane) {
// 如果是双页模式,则刷新NewsContentFragment中的内容
val fragment = newsContentFrag as NewsContentFragment
fragment.refresh(news.title, news.content)
} else {
// 如果是单页模式,则直接启动NewsContentActivity
NewsContentActivity.actionStart(parent.context, news.title,
news.content)
}
}
return holder
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val news = newsList[position]
holder.newsTitle.text = news.title
}
override fun getItemCount() = newsList.size
}
}
- 收尾工作:向RecyclerView中填充数据
实现效果如下: