So I am trying to create a simple Note App, where the user gives data, gets stored in a database, and is displayed using a recycler view. Up until now, I can confirm that data is being stored in my database, and that data is also being retrieved from it and being initialized to a variable in the adapter class, but for some reason, the Adapter's OnCreateViewHolder(), OnBindViewHolder() and getItemCount() functions are not being called even after notifying the adapter of the change in data. This is my MainActivity and Adapter class.
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: NoteViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val noteAdapter = NotesRVAdapter(this)
notesRV.adapter = noteAdapter
notesRV.layoutManager = LinearLayoutManager(this)
viewModel = ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory.getInstance(application)).get(NoteViewModel::class.java)
//access getAllNotes from NoteViewModel class from created instance
viewModel.getAllNotes.observe(
this,
Observer { list ->
list?.let {
Log.d("TAG","Observing")
NotesRVAdapter(this).updateList(it as ArrayList<NoteEntity>)
// Toast.makeText(this,"$it",Toast.LENGTH_LONG).show()
}
},
)
}
fun createNote(view: View) {
val intent = Intent(this,SecondActivity::class.java) // for creating a note
startActivity(intent)
}
}
Adapter Class
class NotesRVAdapter(private val context: Context) : RecyclerView.Adapter<NotesRVAdapter.NotesVH>() {
private var noteItem = ArrayList<NoteEntity>()
inner class NotesVH(noteView: View): RecyclerView.ViewHolder(noteView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NotesVH {
val view = LayoutInflater.from(parent.context).inflate(R.layout.note_item,parent,false)
return NotesVH(view)
}
override fun onBindViewHolder(holder: NotesVH, position: Int) {
holder.itemView.Heading.text = noteItem[position].heading
holder.itemView.Description.text = noteItem[position].text
holder.itemView.Priority.text = noteItem[position].priority.toString()
}
override fun getItemCount(): Int {
return noteItem.size
}
fun updateList(list: ArrayList<NoteEntity>){
noteItem.clear()
noteItem.addAll(list)
// Toast.makeText(context,"${noteItem[0].text}",Toast.LENGTH_LONG).show()
notifyDataSetChanged()
}
}
The updateList function is getting called in mainactivity and the list is being passed in the noteitem and the toast also works, but that's it. All the override functions seem to be not working as I tried running a Log statement in them, but there was no entry for any Log in the Logcat.
I don't think there's a problem in the XML file as I could see the preview using the tools statement, but if someone needs to check it, here it is:
note_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:paddingHorizontal="30dp"
android:paddingVertical="30dp"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="#+id/Heading"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintRight_toLeftOf="#id/Priority"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text = "Note Heading"
android:textSize="35sp"
android:textStyle="bold"
android:textColor="#color/black"
/>
<TextView
android:id="#+id/Description"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#id/Heading"
app:layout_constraintRight_toLeftOf="#id/Priority"
tools:text="Description"
android:textSize="25sp"
android:textColor="#color/black"
/>
<TextView
android:id="#+id/Priority"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="1"
android:textSize="60sp"
android:textColor="#color/black"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
main_activity.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"
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/notesRV"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="0dp"
android:layout_height="0dp"
tools:listitem="#layout/note_item"
/>
<ImageView
android:id="#+id/createNote"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginBottom="80dp"
android:layout_marginRight="40dp"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="#drawable/ic_baseline_add_24"
android:onClick="createNote"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
I would appreciate it if someone could help me with this issue. Thanks!
you are creating a new adapter instance here which is not attached to your recyclerview
NotesRVAdapter(this).updateList(it as ArrayList<NoteEntity>)
change it to the one attached to your recyclerview and that will be
noteAdapter.updateList(it as ArrayList<NoteEntity>)
Related
I am trying to build a layout in which there is a recyclerview where each item has three edittexts horizontally aligned. I want to add the next item when a button is pressed.
This the design I am trying to build
This is the Adapter class for the recycler view
class AddProjectAdapter(private val itemsList : ArrayList<ItemDetails>) : RecyclerView.Adapter<AddProjectAdapter.AddProjectViewHolder>() {
inner class AddProjectViewHolder(private val binding : AddProjectItemViewBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(item : ItemDetails){
binding.item = item
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddProjectViewHolder{
return AddProjectViewHolder(AddProjectItemViewBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
override fun onBindViewHolder(holder: AddProjectViewHolder, position: Int) {
holder.bind(itemsList[position])
}
override fun getItemCount(): Int = itemsList.size
}
Layout file for the item add_project_item_view.xml
`
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="item"
type="com.example.hero.models.ItemDetails" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.card.MaterialCardView
android:id="#+id/item_name_cardview"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:flow_horizontalBias="3"
app:cardBackgroundColor="#color/light_background"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="#id/g_v_1"
android:layout_marginRight="5dp">
<EditText
android:id="#+id/item_name_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Item Name"
android:text="#={item.itemName}"
android:textColor="#color/t_dark"
android:fontFamily="#font/metropolislight"
android:textSize="14dp"
android:textColorHint="#color/t_dark"
android:background="#null"
android:padding="10dp" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="#+id/rate_unit_cardview"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:flow_horizontalBias="2"
android:layout_marginRight="5dp"
app:cardBackgroundColor="#color/light_background"
app:layout_constraintStart_toEndOf="#id/g_v_1"
app:layout_constraintEnd_toEndOf="#id/g_v_2">
<EditText
android:id="#+id/rate_unit_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Rate/Unit"
android:text="#={item.rate}"
android:textColorHint="#color/t_dark"
android:textColor="#color/t_dark"
android:fontFamily="#font/metropolislight"
android:textSize="14dp"
android:padding="10dp"
android:background="#null" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="#+id/unit_cardview"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:flow_horizontalBias="2"
app:cardBackgroundColor="#color/light_background"
app:layout_constraintStart_toEndOf="#id/g_v_2"
app:layout_constraintEnd_toEndOf="parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/unit_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:background="#null"
android:fontFamily="#font/metropolislight"
android:hint="Unit"
android:padding="10dp"
android:text="#={item.unit}"
android:textColor="#color/t_dark"
android:textColorHint="#color/t_dark"
android:textSize="14dp" />
<ImageView
android:id="#+id/drop_down_imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:src="#drawable/dropdown"
android:layout_centerVertical="true" />
</RelativeLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.constraintlayout.widget.Guideline
android:id="#+id/g_v_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.4" />
<androidx.constraintlayout.widget.Guideline
android:id="#+id/g_v_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.8" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
`
//code of the activity in which the recycler view is present
private val itemsList : ArrayList<ItemDetails> = ArrayList()
private lateinit var addProjectAdapter: AddProjectAdapter
private lateinit var binding: ActivityAddProjectBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAddProjectBinding.inflate(layoutInflater)
setContentView(binding.root)
setAdapter()
setListner()
}
private fun setAdapter(){
addProjectAdapter = AddProjectAdapter(itemsList)
binding.itemDetailsRecyclerview.apply {
layoutManager = LinearLayoutManager(this#AddProject)
adapter = addProjectAdapter
}
}
override fun onClick(v : View?) {
when(v?.id){
binding.addItemButton.id -> {
itemsList.add(ItemDetails())
addProjectAdapter.notifyItemInserted(itemsList.size-1)
}
}
}
private fun setListner(){
binding.addItemButton.setOnClickListener(this)
}
data class ItemDetails(
var itemName : String = "",
var rate : String = "",
var unit : String = "")
And my recyclerview id is item_details_recyclerview.
Output for the above code
When I click the add button the item added is not visible but the add button moves down.
Can someone help me out with this issue? And also if you could provide some better approach it would be great.
Thanks in advance.
Change height of ConstraintLayout from add_project_item_view.xml
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
to this
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I'm trying to get a popup to show up when I press a button. I wanted to make sure it even shows up before working on the details but the app just crashes when i press it. The commented block is what I originally intended the button to do (just adding an item to the recyclerview) but I decided I wanted to do something a bit different. It only had the problem of crashing when I started adding the popup window stuff. The app still runs fine even if I remove the popup window stuff and leave the commented block commented out. So I don't know if the listadapter class is relevant but ill just include it.
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var listAdapter: ListAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
listAdapter = ListAdapter(mutableListOf())
recyclerView.adapter = listAdapter
recyclerView.layoutManager = LinearLayoutManager(this)
btn_add.setOnClickListener {
/*
//get text from textbox
val itemText = et_reminder.text.toString()
if (itemText.isNotEmpty()){
//create item with text
val item = Item (itemText)
//add to list
listAdapter.addItem((item))
//clear textbox
et_reminder.text.clear()
}*/
val view : View = LayoutInflater.from(applicationContext).inflate (R.layout.popup_s,null)
val popup: PopupWindow = PopupWindow(view, 250, 250,true)
popup.showAtLocation(view, Gravity.NO_GRAVITY, 0,0)
}
}
}
ListAdapter.kt
class ListAdapter(
private val items: MutableList<Item>
): RecyclerView.Adapter<ListAdapter.ListViewHolder>()
{
class ListViewHolder(itemView: View):RecyclerView.ViewHolder(itemView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
val itemView: View =
LayoutInflater.from(parent.context).inflate (R.layout.list_item, parent, false)
return ListViewHolder(itemView)
}
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
val curr_item = items [position]
holder.itemView.apply {
tv_reminder.text = curr_item.text;
cb_check.isChecked = curr_item.checked
cb_check.setOnCheckedChangeListener { _, isChecked ->
//changing status of checked
curr_item.checked = isChecked
for (i in items.indices.reversed()) {
if (items[i].checked) {
items.removeAt(i)
notifyItemRemoved(i)
}
}
}
}
}
override fun getItemCount(): Int {
return items.size
}
fun addItem (new_item: Item){
items.add (new_item)
notifyItemInserted(items.size - 1)
}
}
activity_main.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"
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/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#color/basically_black"
app:layout_constraintBottom_toTopOf="#+id/et_reminder"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="#+id/et_reminder"
android:layout_width="0dp"
android:layout_height="45dp"
android:hint="Reminder"
android:textSize="20sp"
android:textColorHint="#color/white_purple"
android:textColor="#color/white_purple"
android:background="#color/basically_black"
android:paddingStart="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/btn_add"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/recyclerView"/>
<Button
android:id="#+id/btn_add"
android:layout_width="45dp"
android:layout_height="wrap_content"
android:text="+"
android:textSize="20sp"
android:background="#color/basically_black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
list_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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="55dp"
android:paddingStart="10dp">
<TextView
android:id="#+id/tv_reminder"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingTop="0dp"
android:text="temp"
android:textColor="#color/white_purple"
android:textSize="20sp"
android:maxLines="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/cb_check"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<CheckBox
android:id="#+id/cb_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
popup_s.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="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<EditText
android:id="#+id/et_r"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Reminder"
android:textColor="#color/white_purple"
android:textColorHint="#color/gray"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0">
</EditText>
</androidx.constraintlayout.widget.ConstraintLayout>
I think that happen because you are trying to pass applicationContext it will give you Unable to add window -- token null is not valid; is your activity running?
try to pass the current activity context instead cause PopupWindow can only be attached to an Activity
val view : View = LayoutInflater.from(this).inflate (R.layout.popup_s,null)
val popup = PopupWindow(view, 250, 250,true)
popup.showAtLocation(view, Gravity.NO_GRAVITY, 0,0)
Heyy, it's the first time i use android studio and i want to display the content of a class in a card view dynamically on my page. For exemple I have a class Book that contains the Book title and a little description and i initialise 3 instances of books.. I want 3 cards in my page containing the books titles and description. How can this be done ? Thankz
You should create a recycleview.
They are the steps }
First. Import the dependecy
dependencies {
implementation 'androidx.recyclerview:recyclerview:1.0.0'
}
Second. Add RecyclerView in xml
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
Third. Create the adapter view
<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:padding="4dp">
<ImageView android:id="#+id/foto"
android:layout_width="?android:attr/listPreferredItemHeight"
android:layout_height="?android:attr/listPreferredItemHeight"
android:contentDescription="fotografía"
android:src="#drawable/bar"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
<TextView android:id="#+id/nombre"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Nombres del lugar"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:maxLines="1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="#+id/foto"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView android:id="#+id/direccion"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center"
android:maxLines="1"
android:text="dirección del lugar"
app:layout_constraintTop_toBottomOf="#id/nombre"
app:layout_constraintStart_toEndOf="#+id/foto"
app:layout_constraintEnd_toEndOf="parent"/>
<RatingBar android:id="#+id/valoracion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/ratingBarStyleSmall"
android:isIndicator="true"
android:rating="3"
app:layout_constraintTop_toBottomOf="#id/direccion"
app:layout_constraintLeft_toRightOf="#+id/foto"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Fourth. Create the adpater's class
class AdaptadorLugares(private val lugares: RepositorioLugares) :
RecyclerView.Adapter<AdaptadorLugares.ViewHolder>() {
class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
fun personaliza(lugar: Lugar) = with(itemView){
nombre.text = lugar.nombre
direccion.text = lugar.direccion
foto.setImageResource(when (lugar.tipoLugar) {
TipoLugar.RESTAURANTE -> R.drawable.restaurante
TipoLugar.BAR -> R.drawable.bar
TipoLugar.COPAS -> R.drawable.copas
TipoLugar.ESPECTACULO -> R.drawable.espectaculos
TipoLugar.HOTEL -> R.drawable.hotel
TipoLugar.COMPRAS -> R.drawable.compras
TipoLugar.EDUCACION -> R.drawable.educacion
TipoLugar.DEPORTE -> R.drawable.deporte
TipoLugar.NATURALEZA -> R.drawable.naturaleza
TipoLugar.GASOLINERA -> R.drawable.gasolinera
TipoLugar.OTROS -> R.drawable.otros
})
foto.setScaleType(ImageView.ScaleType.FIT_END)
valoracion.rating = lugar.valoracion
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
ViewHolder {
val v = LayoutInflater.from(parent.context)
.inflate(R.layout.elemento_lista, parent, false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, posicion: Int) {
val lugar = lugares.elemento(posicion)
holder.personaliza(lugar)
}
override fun getItemCount() = lugares.tamanyo()
}
Finally call the adapter in activity's main
You can check the oficial documentation in google
https://developer.android.com/guide/topics/ui/layout/recyclerview
Example code
http://www.androidcurso.com/index.php/691
Using LiveData<PagedList> to display a recycler view that hits a Room database. When I do a search on screen, the number of items returned is less, however, there seems to be a lot of extra white space between the recycler view and the other buttons. The recycler view itself shrinks, and then moves down on the screen.
Here is the way it looks before the data is refreshed (before I do a search):
Here is after:
Here is my adapter for the recyclerView:
class WorkPackagesRecyclerAdapter(
private val onWorkPackageClickListener: OnClickWorkPackage
) : PagedListAdapter<Workpackage,
WorkPackagesRecyclerAdapter.WorkPackagesViewHolder>(
REPO_COMPARATOR
) {
interface OnClickWorkPackage {
fun clickWorkPackage(workPackageId: String)
}
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): WorkPackagesViewHolder {
val inflater = LayoutInflater.from(viewGroup.context)
val binding = inflate<ItemWorkPackageBinding>(
inflater,
R.layout.item_work_package,
viewGroup,
false
)
return WorkPackagesViewHolder(binding, viewGroup.context)
}
override fun onBindViewHolder(holder: WorkPackagesViewHolder, position: Int)
{
getItem(position)?.let {
holder.bind(it)
}
}
inner class WorkPackagesViewHolder(
internal var binding: ItemWorkPackageBinding,
internal val context: Context
) : RecyclerView.ViewHolder(binding.root), KoinComponent {
fun bind(data: Workpackage) {
val itemWorkPackagesViewModel: ItemWorkPackagesViewModel by inject{ parametersOf(data)}
this.binding.listItem.setOnClickListener {
onWorkPackageClickListener.clickWorkPackage(data.id)
}
this.binding.viewmodel = itemWorkPackagesViewModel
this.binding.executePendingBindings()
}
}
companion object {
private val REPO_COMPARATOR =
object : DiffUtil.ItemCallback<Workpackage>() {
override fun areItemsTheSame(
oldItem: Workpackage,
newItem: Workpackage
): Boolean =
oldItem.id == newItem.id
override fun areContentsTheSame(
oldItem: Workpackage,
newItem: Workpackage
): Boolean =
oldItem == newItem
}
}
Here is how I set up the PagedList:
val searchQuery: MutableLiveData<SearchAndSort> = MutableLiveData(
SearchAndSort("",
WorkpackagesRepository.Companion.SortedBy.WorkPackageNumber,
AscendDescend.ASC))
var workPackagesList = Transformations.switchMap(searchQuery) { searchQuery ->
val factory = workPackageStorageDao.searchWorkpackages(
searchQuery.searchText,
searchQuery.sortBy.type + " " + searchQuery.ascendDescend.text
)
val pagedListBuilder = LivePagedListBuilder<Int, Workpackage>(factory, pagingLimit)
pagedListBuilder.build()
}
Here is where I am observing the adapter:
workPackagesViewModel.workPackagesList.observe(this, Observer { wpList ->
wpList ?: return#Observer
adapter = WorkPackagesRecyclerAdapter(this)
adapter.submitList(wpList)
binding.workPackagesRecyclerView.adapter = adapter
adapter.notifyDataSetChanged()
})
Here is the layout of the recycler view
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="com.bechtel.pf.ui.workpackages.WorkPackagesViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="727dp"
tools:layout_editor_absoluteY="1dp">
<EditText
android:id="#+id/search_bar_edit_text"
android:layout_width="match_parent"
android:layout_height="55dp"
android:layout_marginTop="#dimen/work_package_margin"
android:hint="#string/work_packages_search_hint"
app:layout_constraintBottom_toBottomOf="#id/guideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<ImageButton
android:id="#+id/search_bar_magnifying_glass"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginTop="#dimen/work_package_margin"
android:background="#drawable/icons_search"
app:layout_constraintBottom_toBottomOf="#id/guideline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
app:layout_constraintGuide_begin="#dimen/work_package_search_guideline_start"
/>
<com.google.android.material.button.MaterialButton
android:id="#+id/btnSortBy"
android:layout_width="0dp"
android:layout_height="45dp"
android:layout_marginTop="5dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:backgroundTint="#color/colorPrimary"
app:layout_constraintEnd_toStartOf="#+id/btnAscendDescend"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/guideline"
app:layout_constraintHorizontal_chainStyle="spread"
android:text="#string/work_packages_sort"
/>
<com.google.android.material.button.MaterialButton
android:id="#+id/btnAscendDescend"
android:layout_width="0dp"
android:layout_height="45dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="10dp"
android:backgroundTint="#color/colorPrimary"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintEnd_toStartOf="#+id/btnFilterBy"
app:layout_constraintStart_toEndOf="#+id/btnSortBy"
app:layout_constraintTop_toBottomOf="#+id/guideline"
app:layout_constraintHorizontal_chainStyle="spread"
android:text="#string/work_packages_ascend"
android:onClick="#{() -> viewModel.ascendingDescending()}"
/>
<com.google.android.material.button.MaterialButton
android:id="#+id/btnFilterBy"
android:layout_width="0dp"
android:layout_height="45dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="10dp"
android:backgroundTint="#color/colorPrimary"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/btnAscendDescend"
app:layout_constraintTop_toBottomOf="#+id/guideline"
android:text="#string/work_packages_filter"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/workPackagesRecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:layout_marginTop="75dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/btnFilterBy">
</androidx.recyclerview.widget.RecyclerView>
</androidx.constraintlayout.widget.ConstraintLayout>
Anyone ever seen anything like this before? I've also made sure that I am using layout_height = wrap_content in my recyclerview layout and item.xml files.
Screenshot inspector:
OK, it looks like I had set the recyclerview layout_constraintBottom_toBottomOf was set to 'parent' and since the total height of the recyclerview shrunk when the number of items shrunk, it was moving the view to the bottom of the screen. I also could get rid of the top margin attribute and the recycler view stayed below the buttons. So now I have:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/workPackagesRecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/btnFilterBy"/>
And it all looks good!
activity_main.xml code:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="sampleex_recycleview.himanshu.recycleview.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/RecViewId"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Data List for RecyclerView in main activity, list_row.xml code:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#color/cardview_shadow_end_color"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="375dp"
android:layout_height="140dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="4dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imageViewPhoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginStart="13dp"
android:padding="25dp"
app:srcCompat="#mipmap/ic_launcher_round" />
<TextView
android:id="#+id/AgeTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_below="#+id/NameTextView"
android:layout_marginTop="14dp"
android:layout_toRightOf="#id/imageViewPhoto"
android:hint="age"
android:padding="5dp" />
<TextView
android:id="#+id/NameTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/imageViewPhoto"
android:layout_marginTop="22dp"
android:layout_toEndOf="#+id/imageViewPhoto"
android:hint="name"
android:padding="5dp" />
</RelativeLayout>
</android.support.v7.widget.CardView>
Main Activity code here :
class MainActivity : AppCompatActivity() {
private var adapter : PersonListAdapter? = null
private var layoutManager : RecyclerView.LayoutManager? = null
private var personList : ArrayList<Person>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
personList = ArrayList<Person>()
layoutManager = LinearLayoutManager(this)
adapter = PersonListAdapter(personList!!, this)
//set up recycle view
RecViewId.layoutManager = layoutManager
RecViewId.adapter = adapter
// loading data
for(i in 1..15){
var person = Person()
person.name = "Person " + i
person.age = 21 + i
}
adapter!!.notifyDataSetChanged()
}
}
Adapter Class' code (exists in package name 'Data') :
// adapter class for the inflating layout for list in the recycler view and parsing data into the feild components of the layout
class PersonListAdapter(private var list : ArrayList<Person>, var context: Context) :
RecyclerView.Adapter<PersonListAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.list_row, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
holder?.bindItem(list[position])
}
override fun getItemCount(): Int {
return list.size
}
class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView) {
fun bindItem(person: Person){
var Name : TextView = itemView.findViewById(R.id.NameTextView) as TextView
var Age : TextView = itemView.findViewById(R.id.AgeTextView) as TextView
Name.text = person.name
Age.text = person.age.toString()
}
}
}
Person Class' code (exists in different package name 'Model'):
// class for the layout of the data to be shown in the data list in the Recycler view in the main activity
class Person{
var name : String? = null
var age : Int? = null
}
Your just creating person object. Those objects need to be added to the personList.
for(i in 1..15){
var person = Person()
person.name = "Person " + i
person.age = 21 + i
personList.add(person) // Add person object to the list
}
Also you aren't correctly initializing the RecyclerView in the above code.
//set up recycle view
val recView = findViewById<RecyclerView>(R.id.RecViewId)
recView.layoutManager = layoutManager
recView.adapter = adapter
Let's try this code:
<android.support.v7.widget.RecyclerView
android:id="#+id/RecViewId"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
and set fixed size for RecyclerView