先准备好一个新闻实体类
package com.zb.fragmentbestpractice /** * title:表示新闻的实体类 * content:表示新闻的内容 */ class News(val title: String, val content: String) { }
新建布局文件news_content_frag.xml,作为新闻布局的内容
<?xml version="1.0" encoding="utf-8"?> <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="#000000" /> <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="#000000" /> </RelativeLayout>
class NewsContentFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.news_content_frag, container, false) } /** * 该方法用于将新闻的标题和内容显示在我们刚刚定义的界面上, * 当调用了refresh方法时,需要将我们刚才隐藏的新闻内容布局设置成为可见 */ fun refresh(title: String, content: String) { //将布局设置成可见 contentLayout.visibility = View.VISIBLE //设置新闻标题内容 newsTitle.text = title //设置新闻内容 newsContent.text = content } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <fragment android:id="@+id/newsContentFrag" android:name="com.zb.fragmentbestpractice.NewsContentFragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
class NewsContentActivity : AppCompatActivity() { companion object { fun actionStart(context: Context, title: String, content: String) { val intent = Intent(context, NewsContentActivity::class.java).apply { putExtra("news title", title) putExtra("news content", content) } context.startActivity(intent) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_news_content) val title = intent.getStringExtra("news title")//获取传入的新闻标题 val content = intent.getStringExtra("news content")//获取传入的新闻内容 if (title != null && content!= null) { val fragment = newsContentFrag as NewsContentFragment fragment.refresh(title, content) //刷新NewsContentFragment 界面 } } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/newsTitleRecyclerView" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
该布局比较简单,里面只有一个用于显示新闻列表的RecyclerView,既然要用到RecyclerView就要编写子项的布局,新建news_item.xml作为RecyclerView子项的布局
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/newsTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:maxLines="1" android:ellipsize="end" android:textSize="18sp" android:paddingLeft="10dp" android:paddingRight="10dp" android:paddingTop="15dp" android:paddingBottom="15dp"> </TextView>
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.newsContent.newsContentLayout) != null } }
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/newsTitleLayout" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/newsTitleFrag" android:name="com.zb.fragmentbestpractice.NewsTitleFragment" android:layout_width="match_parent" android:layout_height="match_parent" </FrameLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <fragment android:id="@+id/newsTitleFrag" android:name="com.zb.fragmentbestpractice.NewsTitleFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> <FrameLayout android:id="@+id/newsContentLayout" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="3"> <fragment android:id="@+id/newsContentFrag" android:name="com.zb.fragmentbestpractice.NewsContentFragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout> </LinearLayout>
package com.zb.fragmentbestpractice import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.activity_news_content.* import kotlinx.android.synthetic.main.news_item.view.* import kotlinx.android.synthetic.main.news_title_frag.* /** * 用于展示新闻列表 */ 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 val layoutManager = LinearLayoutManager(activity) newsTitleRecyclerView.layoutManager = layoutManager val adapter = NewsAdapter(getNews()) newsTitleRecyclerView.adapter = adapter } private fun getNews(): List<News> { val newsList = ArrayList<News>() for (i in 1..50) { val news = News("This is news title $i", getRandomLengthString("This is news content $i.")) newsList.add(news) } return newsList } private fun getRandomLengthString(str: String): String { val n = (1..20).random() val builder = StringBuilder() repeat(n) { builder.append(str) } return builder.toString() } /** * 内部类,用来作为RecyclerView的适配器 */ inner class NewsAdapter(val newsList: List<News>) : RecyclerView.Adapter<NewsAdapter.ViewHolder>() { inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val newsTitle: TextView = view.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 { //在newsList当中先获取news实例 val news = newsList[holder.adapterPosition] //根据isTwoPane判断是单页模式还是双页模式 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(): Int { return newsList.size } } }