简易版的新闻应用

一个简易版的新闻应用

  • 先准备好一个新闻实体类
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>
  • 新闻布局主要分为两个部分:头部部分显示新闻标题,正文部分显示内容,中间使用一条水平方向的细线进行隔开,除此之外还有一条竖直防线的细线,它的作用是在双页模式下将左侧新闻列表和右侧新闻的内容进行分隔开.
  • 我们还需要将新闻内容的布局设置成为不可见,因为在双页模式下,如果还没有选中新闻列表中的任何一条新闻,是不应该显示新闻内容布局的.
  • 接下来新建一个NewsContentFragment类
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
    }
}
  • 在onCreatView()方法中加载了我们刚刚创建的布局
  • 这样就把新闻内容的Fragment和布局创建好了,但是它们都是在双页模式当中使用的,如果想在单页模式中使用,我们还需要创建一个Activity
  • 创建一个NewsContentActivity
<?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>
  • 在这个地方发挥了代码的复用性,直接在布局中引入了NewsContentFragment.这样相当于把news_content_frag布局的内容自动加了进来
  • 修改NewsContentActivity中的代码
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 界面
        }
    }
}
  • onCreate()方法当中,我们通过Intent获取到了传入的新闻标题和新闻内容,然后获取NewsContentFragment实例,接着调用它的refres()方法,将新闻标题和内容传入,就可以把这些数据显示出来了
  • 接下来创建一个用于显示新闻列表的布局,新建news_title_frag.xml
<?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>
  • 子项布局也比较简单,只有一个TextView
  • 其中android:padding表示给空间周围加上补白,这样不至于让文本内容,紧靠在边缘上
  • android:ellipsize用于设定当文本内容超出控件宽度时的缩略方式,这里指定成为end表示在尾部进行省略
  • 新闻列表和子布局都创建好了,现在需要一个用于展示新闻列表的地方,这里新建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.newsContent.newsContentLayout) != null
    }
}
  • 其中的onActivityCreated()方法通过在Activity中能否找到一个id为newsContentLayout的View,来判断当前是双页模式还是单页模式
  • 因此我们需要让这个id为newsContentLayout的View旨在双页模式当中才会出现.
  • 使用限定符实现id为newsContentLayout的View只在双页模式当中才能出现.
  • 修改activity_main.xml中的代码
<?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>
  • 上述代码表示只会在单页模式下加载一个新闻标题的Fragment
  • 然后新建一个layout-sw600dp文件夹,在这个文件夹下面创建一个activity_main.xml文件,代码如下
<?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>
  • 可以看出在双页模式下面,同时引入了两个fragment,并将新闻内容的fragment放在了Fragment的布局下面,这个Fragment布局id为newsContentFrag
  • 因此只要能够找到这个布局的id就说明是双页模式,反之来说就是单页模式.
  • 接下来就是在NewsTitleFragment中通过RecyclerView将新闻列表展示出来
  • 在NewsTitleFragment中新建一个内部类NewsAdapter,来作为RecyclerView的适配器
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
        }
    }
}
  • 最后一步收尾工作,向RecyclerView当中添加数据
  • 修改NewsTitleFragment中的代码
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,作为AI语言模型,我无法提供完整的安卓应用程序。下面是一个简单的示例,可用于开始编写新闻应用程序: 1. 在Android Studio中创建一个新项目,并选择Kotlin作为主要语言。 2. 在项目中创建一个RecyclerView,用于显示新闻列表。 3. 创建一个新闻数据模型类,包括标题、描述、图片等信息。例如: ``` data class News(val title: String, val description: String, val image: Int) ``` 4. 创建一个新闻适配器类,用于将新闻数据绑定到RecyclerView中的项。例如: ``` class NewsAdapter(private val newsList: List<News>) : RecyclerView.Adapter<NewsAdapter.ViewHolder>() { class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val titleTextView: TextView = view.findViewById(R.id.title_text_view) val descriptionTextView: TextView = view.findViewById(R.id.description_text_view) val imageView: ImageView = view.findViewById(R.id.image_view) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.news_item, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val news = newsList[position] holder.titleTextView.text = news.title holder.descriptionTextView.text = news.description holder.imageView.setImageResource(news.image) } override fun getItemCount() = newsList.size } ``` 5. 在MainActivity中初始化新闻数据,并将其传递给适配器。例如: ``` class MainActivity : AppCompatActivity() { private lateinit var newsRecyclerView: RecyclerView private lateinit var newsAdapter: NewsAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) newsRecyclerView = findViewById(R.id.news_recycler_view) newsAdapter = NewsAdapter(getNewsList()) newsRecyclerView.adapter = newsAdapter newsRecyclerView.layoutManager = LinearLayoutManager(this) } private fun getNewsList(): List<News> { return listOf( News("新闻标题1", "新闻描述1", R.drawable.news_image1), News("新闻标题2", "新闻描述2", R.drawable.news_image2), News("新闻标题3", "新闻描述3", R.drawable.news_image3), // 添加更多新闻... ) } } ``` 6. 在布局文件中添加RecyclerView和新闻项布局。例如: ``` <androidx.recyclerview.widget.RecyclerView android:id="@+id/news_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent"/> <LinearLayout android:id="@+id/news_item" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <ImageView android:id="@+id/image_view" android:layout_width="match_parent" android:layout_height="200dp" android:scaleType="centerCrop"/> <TextView android:id="@+id/title_text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="18sp" android:textStyle="bold" android:padding="8dp"/> <TextView android:id="@+id/description_text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="14sp" android:padding="8dp"/> </LinearLayout> ``` 这只是一个简单的示例,你可以根据自己的需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值