Data fetched from Firestore not showing in RecyclerView? (Kotlin) - android

It is a note taking app. I am using Cloud Firestore to store data. Data got added into database but recycler view is not showing anything. Below are the code snippets.
My Data Model Class:
class Notes {
var id:String?= null
var title: String? = null
var description: String? = null
var created: Timestamp? =null
constructor() {}
constructor(id:String,title: String?, description:String?,created:Timestamp?) {
this.id=id
this.title = title
this.description=description
this.created=created
}
}
AddNotesActivity
class AddNoteActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_note)
btn_add_note.setOnClickListener{
val noteTitle = note_title.text.toString()
val noteDescription =note_description.text.toString()
if(noteTitle.isNotEmpty() && noteDescription.isNotEmpty()){
addNotes(noteTitle,noteDescription)
Toast.makeText(this,"note added successfully",Toast.LENGTH_SHORT).show()
onBackPressed()
}
}
}
private fun addNotes(title:String, description:String){
val currentUserId = FirebaseAuth.getInstance().currentUser!!.uid
var note = Notes(currentUserId,title,description, Timestamp(Date()))
FirebaseFirestore.getInstance().collection("notes").add(note).addOnSuccessListener {
Log.i("AddNoteActivity","Note added")
}
}
}
NotesActivity(showing recyclerview):
class NotesActivity : AppCompatActivity() {
lateinit var notesAdapter: NotesAdapter
lateinit var recyclerView: RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_notes)
recyclerView = findViewById(R.id.rv_notes)
setUpRecyclerView()
floating_btn.setOnClickListener {
startActivity(Intent(this, AddNoteActivity::class.java))
}
}
private fun setUpRecyclerView() {
val query:Query= FirebaseFirestore.getInstance().collection("notes").whereEqualTo("id",FirebaseAuth.getInstance().currentUser!!.uid)
val options:FirestoreRecyclerOptions<Notes> = FirestoreRecyclerOptions.Builder<Notes>().setQuery(query,Notes::class.java).build()
notesAdapter = NotesAdapter(options)
recyclerView.adapter = notesAdapter
notesAdapter!!.startListening()
}
}
Adapter class:
class NotesAdapter(options:FirestoreRecyclerOptions<Notes>):FirestoreRecyclerAdapter<Notes,NotesAdapter.MyViewHolder>(options) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NotesAdapter.MyViewHolder {
val itemView= LayoutInflater.from(parent.context).inflate(R.layout.each_note_view,parent,false)
return MyViewHolder(itemView)
}
override fun onBindViewHolder(holder: MyViewHolder, p1: Int, NotesModel: Notes) {
holder.title.text = NotesModel.title
holder.description.text= NotesModel.description
val date=DateFormat.getDateInstance(DateFormat.MEDIUM).format(NotesModel.created)
holder.date.text = date.toString()
}
class MyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
val title : TextView = itemView.title_text
val description: TextView =itemView.description_text
val date : TextView =itemView.date_created
}
}
But when getting data from querysnapshot, logcat is showing perfect data from firestore database:
val query = FirebaseFirestore.getInstance().collection("notes").whereEqualTo("id", FirebaseAuth.getInstance().currentUser!!.uid).get().addOnSuccessListener {
val doc = it.documents
for (i in doc) {
Log.i("NotesActivity", i.data.toString())
}
}
Logcat: {created=Timestamp(seconds=1611116973, nanoseconds=14000000),
description=day, id=wLxCTMLGZpaWNs1b8Uhf3HoRUgz2, title=go}
I spend two days on this, but not getting any solution. I would be thankful if anybody can solve the issue.
Below is XML file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_notes"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="7"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/floating_btn"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_marginEnd="8dp"
android:backgroundTint="#color/light_blue"
android:src="#drawable/floating_btn"/>

Related

I can't view my data from api in recyclerview

I can't view my data from api in recyclerview. Can you help me what is the problem?
MyCode:
Adapter:
class NewsAdapter(private val data: List<AllData>) :
RecyclerView.Adapter<NewsAdapter.MyViewHolder>() {
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val title = view.findViewById<TextView>(R.id.news_info)
val imageView = view.findViewById<ImageView>(R.id.news_img)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.main_activity_cardview_card_menu, parent, false)
return MyViewHolder(view)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val news:AllData=data[position]
holder.title.text = news.haberler[position].title
Glide.with(holder.imageView.context).load(news.haberler[position].imageUrl).into(holder.imageView)
}
override fun getItemCount(): Int {
return data.size
}
}
activity_main.xml
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/news_recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/view" />
MainActivity:
class MainActivity : AppCompatActivity() {
private val itemList = ArrayList<MenuCardModel>()
private lateinit var menuCardAdapter: MenuCardAdapter
private lateinit var newsAdapter: NewsAdapter
val data = ArrayList<AllData>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
loadNews()
}
private fun loadNews() {
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(ApiInterface::class.java)
val call = service.getNews()
call.enqueue(object :Callback<AllData>{
override fun onResponse(
call: Call<AllData>,
response: Response<AllData>
) {
response.body()?.let {
data.add(it)
newsAdapter = NewsAdapter(data)
news_recyclerView.adapter = newsAdapter
}
}
override fun onFailure(call: Call<AllData>, t: Throwable) {
t.printStackTrace()
}
})
}
}
Model :
data class Haberler(
val content: String,
val id: Int,
val imageUrl: String,
val orderNo: Int,
val parentId: Any,
val title: String,
val videoUrl: String
)
AllData :
data class AllData(
val haberler: List<Haberler>,
val istatistik: Istatistik,
val konferans: Konferans,
val kvkk: String,
val liveChat: String,
val pratikBilgiler: List<PratikBilgiler>,
val sgkTv: List<SgkTv>,
val sss: List<Ss>,
val state: Boolean,
val subjects: List<Subject>
)
Hello, I can't view my data from api in recyclerview. Can you help me what is the problem?
Hello, I can't view my data from api in recyclerview. Can you help me what is the problem?
Hello, I can't view my data from api in recyclerview. Can you help me what is the problem?
It looks like you forgot to set layout manager to your recyclerview before you set adapter
There are two ways you can set layout manager
First way by xml
<androidx.recyclerview.widget.RecyclerView
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
...
/>
second way is by code
newsAdapter = NewsAdapter(data)
news_recyclerView.layoutManager = LinearLayoutManager(context) // line which you forgot
news_recyclerView.adapter = newsAdapter
for more understanding about layout managers , you can refer below links
https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.LayoutManager
Just add layoutManager this line in RecyclerView as follow:
<androidx.recyclerview.widget.RecyclerView
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
...
/>
You are missing layout manager for recycler view

How does Data binding bind data?

I'm trying to figure out how Data Binding works with RecyclerView.
I've got Sound objects that have names. I bind these objects to ViewHolders and somehow, these names are displayed on the items of my RecyclerView list.
Here is the code (not mine, I took it from a book)
Layout File:
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="ru.vsevolod.zimin.beatbox.SoundViewModel"/>
</data>
<Button
android:layout_height="120dp"
android:text="#{viewModel.title}"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:layout_width="match_parent"
tools:text="Sound Button"/>
</layout>
MainActivity:
class MainActivity : AppCompatActivity() {
private lateinit var beatBox: BeatBox
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
beatBox = BeatBox(assets)
beatBox.loadSounds()
val binding: ActivityMainBinding =
DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.recyclerViewie.apply {
layoutManager = LinearLayoutManager(this#MainActivity)
adapter = SoundAdapter()
}
}
private inner class SoundHolder (val binding: ListItemSoundBinding):
RecyclerView.ViewHolder(binding.root) {
init {
binding.viewModel = SoundViewModel()
}
fun bind(sound: Sound) {
binding.viewModel?.sound = sound
}
}
private inner class SoundAdapter: RecyclerView.Adapter<SoundHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SoundHolder {
val binding = DataBindingUtil.inflate<ListItemSoundBinding> (layoutInflater,
R.layout.list_item_sound, parent, false)
return SoundHolder(binding)
}
override fun onBindViewHolder(holder: SoundHolder, position: Int) {
val sound = beatBox.sounds[position]
holder.bind(sound)
}
override fun getItemCount(): Int {
return beatBox.sounds.size
}
}
}
BeatBox (creates and contains the list of Sound objects that are going to be bound to the ViewHolders):
private const val SOUNDS_FOLDER = "sample_sounds"
class BeatBox(private val assets: AssetManager) {
val sounds: List<Sound>
init {
sounds = loadSounds()
}
fun loadSounds(): List<Sound> {
val soundNames: Array<String>
try {
soundNames = assets.list(SOUNDS_FOLDER)!!
}catch(e: Exception){
Log.e(TAG, "Couldn't list assets",e)
return emptyList()
}
val sounds = mutableListOf<Sound>()
soundNames.forEach {
val sound = Sound(it)
sounds.add(sound)
}
return sounds
}
}
Sound (class for Sound objects):
class Sound(val name: String)
SoundViewModel:
class SoundViewModel: BaseObservable() {
var sound: Sound? = null
set(sound) {
field = sound
notifyChange()
}
#get : Bindable
var title: String? = null
get() = sound?.name
}
What I fail to understand is how exactly the titles of the Sound objects are hooked up to the ViewHolders. I also noticed that when I remove the getter from SoundViewModel like that:
Before:
#get : Bindable
var title: String? = null
get() = sound?.name
After:
#get : Bindable
var title = sound?.name
...the titles are no longer bound and I end up with a nameless list.
Could you please explain how this happens?
Thank you in advance!

ANDROID How do i bind my mutableLiveData through an adapter to my Recyclerview

First of all sorry for my bad English.
I'm trying to receive Data from my self-written Python Backend(REST-API) in my Android APP.
ApiService.kt:
private const val Base_URL = "http://192.168.178.93:5000/api/"
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
private val retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(Base_URL)
.build()
interface TodoApiService{
#GET("todo")
suspend fun getToDo(): List<ToDo>
}
object ToDoApi{
val retrofitService : TodoApiService by lazy {
retrofit.create(TodoApiService::class.java)
}
}
MainActivityViewModel.kt:
class MainActivityViewModel : ViewModel() {
of the most recent request
private val _status = MutableLiveData<String>()
val status: LiveData<String> = _status
private val _toDo = MutableLiveData<List<ToDo>>()
val toDo: LiveData<List<ToDo>> = _toDo
init {
getToDo()
}
private fun getToDo() {
viewModelScope.launch{
try {
_toDo.value = ToDoApi.retrofitService.getToDo()
_status.value = "Success $_toDo"
}catch (e: Exception){
_status.value = "Failure ${e.message}"
}
}
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/recycler_view"
tools:listitem="#layout/todo_item"/>
</FrameLayout>
todo_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="#+id/text_view_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1"/>
</RelativeLayout>
</androidx.cardview.widget.CardView>
TodoAdapter.kt
class TodoAdapter(private val context: Context, private val Items: List<ToDo>):RecyclerView. Adapter<TodoAdapter.TodoViewHolder>(){
class TodoViewHolder(private val view: View) : RecyclerView.ViewHolder(view){
val textView: TextView = view.findViewById(R.id.text_view_name)
}
override fun getItemCount() = Items.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder {
val adapterLayout = LayoutInflater.from(parent.context)
.inflate(R.layout.todo_item, parent, false)
return TodoViewHolder(adapterLayout)
}
override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
val ToDo = Items.get(position)
holder.textView.text = context.resources.getString(ToDo.Id.toInt())
}
}
MainActivity.kt:
class MainActivity : AppCompatActivity() {
private val viewModel = MainActivityViewModel()
private lateinit var binding: ActivityMainBinding
private lateinit var linearLayoutManager: LinearLayoutManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
linearLayoutManager = LinearLayoutManager(this)
binding.recyclerView.layoutManager = linearLayoutManager
binding.recyclerView.adapter = TodoAdapter(this, viewModel.toDo.value)
}
}
I know that I need an adapter to connect my LiveData to my recyclerView. But I'm not able to implement it right. Android studio tells me I cant use my MutableLiveData<List> for my Adapter that just only needs a normal List(Required: List Found: List?. I cant Cast cause the data could be null.
Your use of LiveData is incorrect. You use it as a simple variable, passing its current value (which is null) to the adapter.
LiveData is intended for data stream and need to be observed.
I like to add a setter for the data on the Adapter class:
fun setData(data: List<ToDo>) {
Items = data
notifyDataSetChanged()
}
And in the Activity, observe the ViewModel's live data and update the adapter when new data arrives:
class MainActivity : AppCompatActivity() {
private lateinit var adapter: TodoAdapter
override fun onCreate(savedInstanceState: Bundle?) {
...
adapter = TodoAdapter(this)
viewModel.todo.observe(this, { todos ->
adapter.setData(todos)
}
}
...
}
Now when you set value to your LiveData in the ViewModel, the adapter will be notified.
This is because you are sending a possible nullable list from the activity to the Adapter. You must do something like this:
binding.recyclerView.adapter = TodoAdapter(this, viewModel.toDo?.value ?: listOf())

Firestore collection data not displaying in recycler view but it is accessed correctly

As described in the title, I have a firestore collection with two documents which I want to show in my recycler View. I can see in logs that data is accessed correctly and my recycler view adapter size also shows correct number but recycler view does not show up. I thought it might be due to me using view binding but I doubt that is the issue. I am out of ideas, any help is appreciated!
This is my RecyclerView adapter:
open class BoardItemsAdapter(private val context: Context, private val list: ArrayList<Board>): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var boardItemClickListener: BoardItemClickInterface? = null;
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val binding = ItemBoardBinding.inflate(LayoutInflater.from(parent.context),parent,false);
return MyViewHolder(binding);
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val model = list[position];
if(holder is MyViewHolder){
Glide.with(context)
.load(model.image)
.centerCrop()
.placeholder(R.drawable.ic_board_place_holder)
.into(holder.binding.ivBoardImageItemBoard);
holder.binding.tvNameItemBoard.text = model.name;
holder.binding.tvCreatedByItemBoard.text = "Created by: ${model.createdBy}";
holder.itemView.setOnClickListener {
if(boardItemClickListener != null){
boardItemClickListener!!.onClick(position, model);
}
}
}
}
override fun getItemCount(): Int {
return list.size;
}
inner class MyViewHolder(val binding:ItemBoardBinding):RecyclerView.ViewHolder(binding.root){
}
}
A snippet of FirestoreClass
fun getBoardsList(activity: MainActivity){
mFirestore.collection(Constants.BOARDS)
.whereArrayContains(Constants.ASSIGNED_TO,getCurrentUserID())
.get()
.addOnSuccessListener {
document ->
Log.i(activity.javaClass.simpleName, document.documents.toString()); //logs correct data
val boardList: ArrayList<Board> = ArrayList();
for(i in document.documents){
val board = i.toObject(Board::class.java)!!;
board.documentID = i.id;
boardList.add(board)
}
activity.populateBoardsListToUI(boardList);
}.addOnFailureListener {
e ->
activity.hideProgressDialog();
Log.e(activity.javaClass.simpleName,"Error while creatng a board",e);
}
}
A snippet of MainActivity:
fun populateBoardsListToUI(boardsList: ArrayList<Board>){
mainContentBinding = MainContentBinding.inflate(layoutInflater);
hideProgressDialog();
if(boardsList.size > 0){
mainContentBinding.rvBoards.visibility = View.VISIBLE;
mainContentBinding.tvNoBoardsAvailable.visibility = View.GONE;
mainContentBinding.rvBoards.layoutManager = LinearLayoutManager(this);
mainContentBinding.rvBoards.setHasFixedSize(true);
val adapter = BoardItemsAdapter(this#MainActivity, boardsList);
mainContentBinding.rvBoards.adapter = adapter;
Log.i("POPUI","Board adapter size: ${adapter.itemCount}");
}
else{
mainContentBinding.rvBoards.visibility = View.GONE;
mainContentBinding.tvNoBoardsAvailable.visibility = View.VISIBLE;
}
}
MainContent.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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/ic_background"
android:gravity="center"
android:orientation="vertical"
android:padding="#dimen/main_screen_content_padding"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".activities.MainActivity">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:elevation="#dimen/card_view_elevation"
app:cardCornerRadius="#dimen/card_view_corner_radius"
>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_boards"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
/>
<TextView
android:id="#+id/tv_no_boards_available"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/no_boards_available"
android:gravity="center"
android:textColor="#color/secondary_text_color"
android:textSize="#dimen/no_boards_available_text_size"
/>
</androidx.cardview.widget.CardView>
</LinearLayout>
Board class
import android.os.Parcel
import android.os.Parcelable
import kotlinx.parcelize.Parceler
import kotlinx.parcelize.Parcelize
#Parcelize
data class Board(
val name: String = "",
val image : String = "",
val createdBy: String = "",
val assignedTo: ArrayList<String> = ArrayList(),
var documentID: String = ""
): Parcelable{
constructor(parcel: Parcel): this(
parcel.readString()!!,
parcel.readString()!!,
parcel.readString()!!,
parcel.createStringArrayList()!!,
parcel.readString()!!
)
override fun describeContents() = 0
companion object : Parceler<Board> {
override fun Board.write(dest: Parcel, flags: Int) = with(dest) {
writeString(name);
writeString(image);
writeString(createdBy);
writeStringList(assignedTo);
writeString(documentID);
}
override fun create(parcel: Parcel): Board = TODO()
}
}
Database screenshot
Database screenshot

Android Spinner : spinner arrow displayed and blinking when scrolling

I am developing an Android application in Kotlin and I implemented a RecyclerView.
Each item of this RecyclerView contains one of the 3 combinations below:
a TextView + a TextView
a TextView + a Button
a TextView + a Spinner
In this activity, I have initialized my parameter list and I can add parameters of one of the 3 types mentioned above by clicking on the TEST button.
My problem is a UI problem: when there are a lot of parameters containing Spinners such that you have to scroll to see them, an arrow of a spinner is displayed at the very top of the RecyckerView (or at the very bottom sometimes). This spinner arrow starts flashing when I scroll and finally stops after a few seconds. Please note that I can't click on this arrow. I don't understand my mistake, can you help me?
Here is a link to a Youtube video recording of the behavior I have described that will help you better understand it.
Here is my view when I am on top of my RecyclerView:
This is my view when I scrolled down in the RecyclerView and there are parameters containing Spinners that are only visible when scrolling up again.
Here is my CustomAdapter class:
class CustomAdapter(private var parameterList: List<Parameter>) :
RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
sealed class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
class TextViewHolder(itemView: View) : ViewHolder(itemView) {
val textViewName: TextView = itemView.findViewById(R.id.parameterName)
val textViewValue: TextView = itemView.findViewById(R.id.parameterValue)
}
class ButtonViewHolder(itemView: View) : ViewHolder(itemView) {
var textViewName: TextView = itemView.findViewById(R.id.parameterName)
val buttonViewValue: Button = itemView.findViewById(R.id.parameterButton)
}
class SpinnerViewHolder(itemView: View) : ViewHolder(itemView) {
val textViewName: TextView = itemView.findViewById(R.id.parameterName)
val spinnerViewValue: Spinner = itemView.findViewById(R.id.parameterSpinner)
}
}
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
return when (viewType) {
0 -> {
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.parameter_text, viewGroup, false)
ViewHolder.TextViewHolder(view)
}
1 -> {
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.parameter_button, viewGroup, false)
ViewHolder.ButtonViewHolder(view)
}
2 -> {
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.parameter_spinner, viewGroup, false)
ViewHolder.SpinnerViewHolder(view)
}
else -> throw IllegalArgumentException("Invalid view type")
}
}
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
when (viewHolder) {
is ViewHolder.TextViewHolder -> {
viewHolder.textViewName.text = parameterList[position].parameterName
viewHolder.textViewValue.text = parameterList[position].parameterValue as CharSequence?
}
is ViewHolder.ButtonViewHolder -> {
viewHolder.textViewName.text = parameterList[position].parameterName
viewHolder.buttonViewValue.text = parameterList[position].parameterValue as CharSequence?
}
is ViewHolder.SpinnerViewHolder -> {
viewHolder.textViewName.text = parameterList[position].parameterName
viewHolder.spinnerViewValue.adapter = parameterList[position].parameterValue as SpinnerAdapter?
}
}
}
override fun getItemViewType(position: Int) : Int {
return parameterList[position].parameterType
}
override fun getItemCount() = parameterList.size
fun addNewList(newList: List<Parameter>){
parameterList = newList;
notifyDataSetChanged();
}
}
Each of the different types of parameters inherited from the class Parameter:
open class Parameter(open var parameterName: String? = "", open var parameterType: Int = 0, open var parameterValue: Any) {
}
ParameterText class:
class ParameterText(override var parameterName: String?, override var parameterValue: Any = "") : Parameter(parameterName, parameterValue = parameterValue!!) {
override var parameterType: Int = 0
}
ParameterButton class:
class ParameterButton(override var parameterName: String?, override var parameterValue: Any = "") : Parameter(parameterName, parameterValue = parameterValue!!) {
override var parameterType: Int = 1
}
ParameterSpinner class:
class ParameterSpinner(override var parameterName: String?, override var parameterValue: Any) : Parameter(parameterName, parameterValue = parameterValue) {
override var parameterType: Int = 2
}
Here is my NFCActivity:
class NFCActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_nfc)
buttonTest.setOnClickListener() {
parametersList = parametersList + ParameterSpinner(
"Led", ArrayAdapter(
this,
android.R.layout.simple_spinner_item, resources.getStringArray(R.array.LedState)
)
)
(rv_parameters2.adapter as CustomAdapter).addNewList(parametersList)
}
rv_parameters2.layoutManager = LinearLayoutManager(this)
rv_parameters2.adapter = CustomAdapter(parametersList)
}
private var parametersList : List<Parameter> = listOf<Parameter> (
ParameterText("Temperature", "24°C"),
ParameterText("Temperature", "24°C")
)
companion object {
fun getStartIntent(context: Context): Intent {
return Intent(context, NFCActivity::class.java)
}
}
}
NFCActivity's layout:
<?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=".view.ble.NFCActivity">
<Button
android:id="#+id/buttonTest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TEST"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_parameters2"
tools:listitem="#layout/parameter_text"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="#id/buttonTest"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

Categories

Resources