Fragment实践-简易版新闻应用|青训营笔记

128 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第5天
今天来实现一下Fragment的实践内容 本笔记参考自《第一行代码》
在进行实践之前,先来回顾一下Fragment的基础知识

  • Fragment:是一种可以嵌入在Activity当中的UI片段,可以被看作是“迷你版”的activity,可以和Activity进行交互操作
  • Fragment的生命周期(类比Activity):
  1. 运行状态
  2. 暂停状态
  3. 停止状态
  4. 销毁状态

Fragment总是依附于Activity而存在,当一个Fragment所关联的Activity处于运行、暂停、停止、销毁状态时,Fragment也处于相同的状态。

Activity中的回调方法,Fragment中基本上也有,不过Fragment还提供了一些附加的回调方法:

  • onAttach():当Fragment和Activity建立关联时调用。
  • onCreateView():为Fragment创建视图(加载布局)时调用。
  • onActivityCreated():确保与Fragment相关联的Activity已经创建完毕时调用。
  • onDestroyView():当与Fragment关联的视图被移除时调用。
  • onetach():当Fragment和Activity解除关联时调用。

image.png

实践部分-一个简单的新闻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中填充数据

实现效果如下: image.png