我有一个新闻应用程序,我在其中使用 Retrofit 从 API 获取数据。我已经用 cardView 和 Recycler 视图显示了新闻。现在我想实施下一步,如果用户点击卡片,整个新闻应该显示在新活动中。但是要实现这一点,我不知道如何做到这一点。在这里,我提供了我的 MainActivity 、适配器类和用于改造的接口。我正在寻找实施下一步的帮助。
MainActivity.kt
class MainActivity : AppCompatActivity() {
lateinit var adapter: NewsAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
getNews()
}
private fun getNews() {
val news :Call<News> = NewsSeversis.newsIntence.getHeadlines("in",1)
news.enqueue(object :Callback<News>{
override fun onResponse(call: Call<News>, response: Response<News>) {
//here response is a News response
val news:News?=response.body()
if (news!=null){
Log.d("response",news.toString())
adapter= NewsAdapter(news.articles)
newsList.adapter=adapter
newsList.layoutManager=LinearLayoutManager(this@MainActivity)
}
}
override fun onFailure(call: Call<News>, t: Throwable) {
Log.d("response","error occur",t)
}
})
}
}
回收者视图的适配器类
class NewsAdapter (val artical: List<Artical>):RecyclerView.Adapter<NewsAdapter.articalViewHolder>(){
inner class articalViewHolder(itemView: View):RecyclerView.ViewHolder(itemView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): articalViewHolder {
val view:View=LayoutInflater.from(parent.context).inflate(R.layout.item_layout,parent,false)
return articalViewHolder(view)
}
override fun onBindViewHolder(holder: articalViewHolder, position: Int) {
val articals:Artical=artical[position]
holder.itemView.apply {
newsTitle.text=articals.title
newsDescription.text=articals.description
Glide.with(context).load(articals.urlToImage).into(newsImage)
}
}
override fun getItemCount(): Int {
return artical.size
}
}
接口类
const val BASE_URL="https://newsapi.org/"
const val API_KEY="b461fea21cc242458825d1be951ebe1c"
interface NewsInterface{
@GET("v2/top-headlines?apiKey=$API_KEY")//@GET is to tell the it is a get request
fun getHeadlines(@Query("country")country:String, @Query("page") page:Int) : Call<News>
}
object NewsSeversis {
val newsIntence:NewsInterface
init {
val retrofit=Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
newsIntence=retrofit.create(NewsInterface::class.java)
}
}
每个卡片视图的布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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="wrap_content"
android:layout_margin="16dp"
app:cardUseCompatPadding="true"
app:cardCornerRadius="8dp"
app:cardElevation="4dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#F1F1F1"
android:padding="16dp">
<ImageView
android:id="@+id/newsImage"
android:layout_width="match_parent"
android:layout_height="180dp"
android:scaleType="centerCrop"
android:src="@drawable/ic_launcher_background"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/newsTitle"
style="@style/TextAppearance.AppCompat.Headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:maxLines="2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="8dp"
android:text="Title"
app:layout_constraintTop_toBottomOf="@+id/newsImage" />
<TextView
android:id="@+id/newsDescription"
style="@style/TextAppearance.AppCompat.Body1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:maxLines="2"
android:text="Description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/newsTitle" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
主要活动布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/newsList"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
除此之外,我还有一个带有构造函数的 Artical 和一个新闻类,以及一个用于显示该活动的全部新闻的全新活动
新闻课
ata class News(
val totalResults:Int,
val articles:List<Artical>
)
艺术课
data class Artical(
val author:String,
val title:String,
val description:String,
val url:String,
val urlToImage:String)
要确定单击了哪个项目,我们需要一个接口,可以从中获取从 Adapter 到 Activity 的回调,因此在 Adapter 中创建一个接口类。 (在你的情况下,你可以在 NewsAdapter 的最后第二行创建它)
interface AdapterCallback {
fun onClick(artical: Artical?)
}
然后我们需要在Adapter的Constructor中取一个这个接口的对象
class NewsAdapter (val artical: List<Artical>, callback: AdapterCallback): ...
然后我们必须在点击视图时使用回调对象。 (在你的情况下,在适配器类的 onBindViewHolder 中执行以下操作)
holder.itemView.setOnClickListener {
callback.onClick(articals)
}
现在我们需要在我们的 Activity 中监听这个回调,所以我们需要通过以下方式在 Activity 中创建对象
private val adapterCallback: AdapterCallback =
object : AdapterCallback {
override fun onClick(artical: Artical?) {
// Code here to navigate to desired Activity by passing required data in the intent (Example below)
val intent = Intent(this, DestinationActivity::class.java)
intent.putExtra("news_artical", artical)
startActivity(intent)
}
}
现在我们的 Activity 中有 AdapterCallback 对象,我们需要将它传递给 Adapter
adapter = NewsAdapter(news.articles, adapterCallback)
注意:需要做Artical Class Parcelable
@Parcelize
data class Artical(
val author: String,
val title: String,
val description: String,
val url: String,
val urlToImage: String
): Parcelable
以下是从适配器获取项目点击活动回调的步骤。
在您的
NewsAdapter
课程中使用 HigherOrder Function
获得项目点击的回调。
1。首先更新 NewsAdapter
class NewsAdapter (
val artical: List<Artical>,
private val onItemClicked: (Artical) -> Unit
):RecyclerView.Adapter<NewsAdapter.articalViewHolder>(){
// your existing code
override fun onBindViewHolder(holder: articalViewHolder, position: Int) {
val articals:Artical=artical[position]
holder.itemView.apply {
newsTitle.text=articals.title
newsDescription.text=articals.description
Glide.with(context).load(articals.urlToImage).into(newsImage)
// ADD THIS LINE
setOnClickListener { onItemClicked.invoke(articals) }
}
}
2。现在更新
MainActivity
中的代码,您正在创建NewsAdapter
的对象。
// EXISTING CODE
adapter= NewsAdapter(news.articles){artical->
// CODE TO LAUNCH THE NEW ACTIVITY
}
// EXISTING CODE
如有任何疑问,请随时询问。