如何在Kotlin中使用RecyclerView [英] How to use RecyclerView in kotlin
问题描述
以前,我曾问过分片调用API ,现在我有了我的应用程序中返回的数据我想知道如何在此片段中制作RecyclerView
?
Previously I have asked about calling API in fragments and now that I have my data returning in my app I would like to know how to make RecyclerView
in this fragments?
基本上,这就是我最终要实现的目标
Basically this is what i'm looking for to achieve at the end
HomeFragment.kt
class HomeFragment : Fragment() {
private lateinit var homeViewModel: HomeViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
homeViewModel = ViewModelProviders.of(this).get(HomeViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_home, container, false)
val textView: TextView = root.findViewById(R.id.text_home)
//calling the API
callAPIDemo(textView)
// homeViewModel.text.observe(this, Observer {
// textView.text = it
// })
return root
}
fun callAPIDemo(textView: TextView) {
// Instantiate the RequestQueue.
val queue = Volley.newRequestQueue(activity)
val url = "https://example.com/api/listings"
// Request a string response from the provided URL.
val stringRequest = StringRequest(
Request.Method.GET, url,
Response.Listener<String> { response ->
// Display the first 500 characters of the response string.
textView.text = "Response is: ${response.substring(0, 500)}"
},
Response.ErrorListener { textView.text = "Something is wrong!" })
// Add the request to the RequestQueue.
queue.add(stringRequest)
}
}
fragment_home.xml
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text_home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
这就是我目前的全部.
请注意,我是新手,非常感谢您提供一些详细的解释.
Please note that I'm newbie in this, giving help with little bit of detailed explanation is much appreciated.
更新
这是我到目前为止创建的内容
Update
Here is what I've created so far
HomeFragment.kt
class HomeFragment : Fragment() {
private lateinit var homeViewModel: HomeViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
homeViewModel = ViewModelProviders.of(this).get(HomeViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_home, container, false)
val textView: TextView = root.findViewById(R.id.recycler)
//calling the API
//callAPIDemo(textView)
val adapter = RecyclerAdapter(callAPIDemo(textView))
recycler.adapter = adapter
return root
}
fun callAPIDemo(textView: TextView) {
// Instantiate the RequestQueue.
val queue = Volley.newRequestQueue(activity)
val url = "https://example.com/api/listings"
// Request a string response from the provided URL.
val stringRequest = StringRequest(
Request.Method.GET, url,
Response.Listener<String> { response ->
// Display the response.
textView.text = "Response is: ${response.substring(0)}"
},
Response.ErrorListener { textView.text = "Something is wrong!" })
// Add the request to the RequestQueue.
queue.add(stringRequest)
}
}
ListingAdapter.kt
此类为红色,返回错误
参数必须具有类型注释
Parameters must have type annotation
class RecyclerAdapter(List) :
RecyclerView.Adapter<RecyclerAdapter.RecyclerViewHolder>() {
//Binding data for each tile
override fun onBindViewHolder(holder: RecyclerViewHolder, position: Int) {
}
//Creation of view holder for each tile
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerViewHolder {
val inflater = LayoutInflater.from(parent.context)
context = parent.context //this context is red
return RecyclerViewHolder(inflater, parent)
}
//View Holder for each item in recycler
inner class RecyclerViewHolder(inflater: LayoutInflater, parent: ViewGroup) :
RecyclerView.ViewHolder(inflater.inflate(R.layout.listings_layout, parent, false)) {
}
override fun getItemCount(): Int {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
listings_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_margin="3dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageViewImage"
android:layout_width="match_parent"
android:layout_height="195dp"
android:background="@color/colorPrimary"
android:contentDescription="@string/Image"
android:scaleType="matrix" />
<TextView
android:id="@+id/textViewTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/MakeUp"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<TextView
android:id="@+id/textViewSlug"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/MakeUp"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
最后是我的fragment_home.xml
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:id="@+id/recycler" />
推荐答案
首先,您需要创建一个布局,以使列表中单行的外观(考虑到我们正在创建水平列表)
First You will need to create a layout for how a single row in your list will look(considering we are creating horizontal listing)
在项目中导航到res>布局文件夹,在布局文件夹中创建一个布局资源文件(花式名称,但这只是一个XML文件)
navigate to res > layout folder in your project, in layout folder create a Layout Resource File (fancy name, but it's just a XML file)
例如:-
layout_demo_item.xml
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<ImageView
android:id="@+id/a_image"
android:layout_width="80dp"
android:layout_height="80dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="@+id/a_image"
app:layout_constraintStart_toEndOf="@+id/a_image"
app:layout_constraintTop_toTopOf="@+id/a_image" />
<TextView
android:id="@+id/text_random"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="@+id/text_title"
app:layout_constraintStart_toEndOf="@+id/text_title"
app:layout_constraintTop_toTopOf="@+id/text_title" />
</androidx.constraintlayout.widget.ConstraintLayout>
第二,您需要一个适配器.
Second you need an Adapter.
适配器会从您那里获取一个数据列表/数组,根据列表的大小呈现行数,并根据列表上的位置将数据分配给每一行
An Adapter will take a list/array of data from you, render number of rows based on size of list and assign the data to each row based on position on list
例如:-
您有一个包含6个名称的数组,然后适配器将基于layout_demo_item.xml
创建6个相同的行,并分配数据,例如将数组中的第0个位置数据分配给列表的第一个元素
You have an array of 6 names, then the adapter will create 6 identical row based on layout_demo_item.xml
and assign data like 0th position data in array will be assigned to first element of list
MyAdapter.kt
class MyAdapter(var dataList: MutableList<DataModelObject>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
// inflating a layout in simple word is way of using a xml layout inside a class.
// if you look this is the same thing that your fragment doing inside onCreateView and storing that into "root" variable, we just did that in "view"
// we passed "view" to MyViewHolder and returned an object of MyViewHolder class(this object actually a single row without data)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_demo_item, parent, false)
return MyViewHolder(view)
}
//the returned object of MyViewHolder class will come here and also with the position on which it gonna show,
// now based on this position we can get the value from our list and finally set it to the corresponding view that we have here in variable "holder"
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.textView.text = dataList.get(position).title
holder.textViewRandom.text = dataList.get(position).randomText
//hardcoding the image, just for simplicity, you can set this also from data list same as above
holder.aImage.setImageResource(R.mipmap.ic_launcher)
//here is the image setup by using glide
//Glide.with(holder.aImage.context).load(dataList.get(position).image).into(holder.aImage)
}
// this method telling adapter to how many total rows will be rendered based on count, so we returning the size of list that we passing
override fun getItemCount(): Int {
return dataList.size
}
// while creating the object in onCreateViewHolder, we received "view" here, and as you can see in your fragment,
// we can do find views by id on it same as we doing in fragment
// so your MyViewHolder now hold the reference of the actual views, on which you will set data
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var textView: TextView
var textViewRandom: TextView
var aImage: ImageView
init {
textViewRandom = itemView.findViewById(R.id.text_random)
textView = itemView.findViewById(R.id.text_title)
aImage = itemView.findViewById(R.id.a_image)
}
}
}
这是我们用作模型类的数据类(与Java
中的POJO
类相同,但仅在Kotlin
中)
here is the data class that we using as our model class(same as a POJO
class in Java
but it's just in Kotlin
)
data class DataModelObject(var randomText:String,var title :String) {
}
我们已经设置了创建recyclerView
的所有内容,因此现在我们将像
We have all things set to create a recyclerView
, so now we will define recyclerView
in Fragment like
fragment_home.xml
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text_home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view_home"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_home" />
</androidx.constraintlayout.widget.ConstraintLayout>
最后,在kotlin类中设置了recyclerView
Finally Inside kotlin class setting up a recyclerView
HomeFragment.kt
(我不包含此片段中不相关的方法和变量,请考虑一下)
(i'm not including the irrelevant methods and variable that you have in this fragment, please consider them)
class HomeFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val root = inflater.inflate(R.layout.fragment_home, container, false)
val textView: TextView = root.findViewById(R.id.text_home)
val recyclerView: RecyclerView = root.findViewById(R.id.recycler_view_home)
callAPIDemo(textView)
setUpRecyclerView(recyclerView);
return root
}
private fun setUpRecyclerView(recyclerView: RecyclerView) {
// first our data list that can come from API/Database
// for now i'm just manually creating the list in getDummyData()
val list: MutableList<DataModelObject> = getDummyData()
// created an adapter object by passing the list object
var myAdapter = MyAdapter(list)
//it's a layoutManager, that we use to tell recyclerview in which fashion we want to show list,
// default is vertical even if you don't pass it and just pass the activity , and we don't want to reversing it so false
// by customizing it you can create Grids,vertical and horizontal lists, even card swipe like tinder
val linearLayoutManager = LinearLayoutManager(activity,LinearLayoutManager.VERTICAL,false)
// just set the above layout manager on RecyclerView
recyclerView.layoutManager = linearLayoutManager
//and give it a adapter for data
recyclerView.adapter = myAdapter
}
private fun getDummyData(): MutableList<DataModelObject> {
val list: MutableList<DataModelObject> = mutableListOf(
DataModelObject("dfgdfg", "title 1"),
DataModelObject("tyuityui", "title 2"),
DataModelObject("yuti", "title 3"),
DataModelObject("uY9NOrc-=s180-rw", "title 4"),
DataModelObject("logo_color_272x92dp.png", "title 5"),
DataModelObject("NOVtP26EKH", "title 6"),
DataModelObject("googlelogo_color", "title 7"),
DataModelObject("sNOVtP26EKHePkwBg-PkuY9NOrc-", "title 8")
)
return list
}
}
这篇关于如何在Kotlin中使用RecyclerView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!