Implement binding into RecycleView Adapter Android Kotlin - android

So hello, I have a little problem here.
I can't implement my binding properly into adapter for RecycleView. I need it to display my products in cart as you can see in the code below. I am a beginner with adapter, so please help me.
CartItemsListAdapter.kt *here is where I want to implement binding*
class CartItemsListAdapter(
private val context: Context,
private var list: ArrayList<CartItem>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
RecyclerView.ViewHolder {
return MyViewHolder(
LayoutInflater.from(context).inflate(
R.layout.item_cart_layout,
parent,
false
)
)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val model = list[position]
if (holder is MyViewHolder) {
Glide.with(context)
.load(model.image)
.placeholder(R.drawable.ic_launcher)
.into(/*binding.ivCartItemImage*/)
//binding.tvCartItemPrice.text = model.price
//binding.tvCartItemTitle.text = model.title
}
}
override fun getItemCount(): Int {
return list.size
}
private class MyViewHolder(view: View) : RecyclerView.ViewHolder(view)
}
activity_cart_list.xml *xml file for reference and from where I want to take those bindings*
<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=".ui.activities.CartListActivity">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar_cart_list_activity"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="?attr/colorSecondary">
<ImageView
android:id="#+id/arrow_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/ic_arrow_left"
android:hapticFeedbackEnabled="true"
android:layout_marginTop="16sp"
android:padding="24dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_gravity="top"
android:contentDescription="#string/back_button" />
<com.example.trieskask.utils.OswaldBold
android:id="#+id/tv_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="My cart"
android:textSize="26sp"
android:elevation="3dp"
android:textStyle="bold" />
</androidx.appcompat.widget.Toolbar>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_cart_items_list"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="10dp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="#id/ll_checkout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/toolbar_cart_list_activity" />
<com.example.trieskask.utils.OswaldRegular
android:id="#+id/tv_no_cart_item_found"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="No cart item found!"
android:textAlignment="center"
app:layout_constraintBottom_toTopOf="#id/ll_checkout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/toolbar_cart_list_activity" />
<LinearLayout
android:id="#+id/ll_checkout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorSecondary"
android:elevation="4dp"
android:orientation="vertical"
android:padding="16dp"
android:visibility="gone"
tools:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.example.trieskask.utils.OswaldLight
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Subtotal:" />
<com.example.trieskask.utils.OswaldLight
android:id="#+id/tv_sub_total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
tools:text="$100" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.example.trieskask.utils.OswaldLight
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Shipping charge:" />
<com.example.trieskask.utils.OswaldLight
android:id="#+id/tv_shipping_charge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
tools:text="$10" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.example.trieskask.utils.OswaldBold
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Total Amount" />
<com.example.trieskask.utils.OswaldBold
android:id="#+id/tv_total_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
tools:text="$110" />
</LinearLayout>
<com.example.trieskask.utils.OswaldButton
android:id="#+id/btn_checkout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="16dp"
android:layout_marginTop="30dp"
android:layout_marginEnd="16dp"
android:background="#drawable/btn_ripple_effect"
android:foreground="?attr/selectableItemBackground"
android:gravity="center"
android:text="Checkoutt"
android:textColor="#android:color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Thanks for any kind of help

You can refactor your MyViewHolder class to require an ActivityCartListBinding as a constructor argument. Then your onCreateViewHolder function will look like:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ActivityCartListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return MyViewHolder(binding)
}
And finally your onBindViewHolder:
override fun onBindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int
) {
val model = list[position]
if (holder is MyViewHolder) {
Glide.with(context)
.load(model.image)
.placeholder(R.drawable.ic_launcher)
.into(/*binding.ivCartItemImage*/)
holder.getBinding().tvCartItemPrice.text = model.price
holder.getBinding().tvCartItemTitle.text = model.title
}
}
View Holder
private class MyViewHolder(val binding: ActivityCartListBinding) : RecyclerView.ViewHolder(binding.root)
This should solve your issue.

Related

Problem in some views in items row of recyclerview "not showing like design preview"

I trying to practice some android lessons that contains recyclerview topic, currently I succeed to implement all api and response but there's one problem with my item_article_preview.xml.
The title and description of news doesn't shows in emulator like it's in design preview
After running the app
here's my xml row
<?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="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="2"
android:orientation="horizontal">
<ImageView
android:id="#+id/ivArticleImage"
android:layout_width="0dp"
android:layout_height="90dp"
android:layout_weight="0.8"
android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.2"
android:orientation="vertical">
<TextView
android:id="#+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:ellipsize="end"
android:maxLines="2"
android:textColor="#color/black"
android:textSize="15sp"
android:textStyle="bold"
tools:text="TITLE" />
<TextView
android:id="#+id/tvDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:ellipsize="end"
android:maxLines="3"
android:textColor="#color/black"
android:text="DESCRIPTION" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="#+id/tvSource"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="SOURCE"
android:textColor="#android:color/black" />
<TextView
android:id="#+id/tvPublishedAt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="PUBLISHED AT"
android:textColor="#android:color/black"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tvSource" />
</LinearLayout>
I tried other row design but it didn't show the title and descreption at all
<?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="wrap_content"
android:padding="8dp">
<ImageView
android:id="#+id/ivArticleImage"
android:layout_width="160dp"
android:layout_height="90dp"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/tvSource"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="SOURCE"
android:textColor="#android:color/black"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/ivArticleImage" />
<TextView
android:id="#+id/tvTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:ellipsize="end"
android:maxLines="3"
android:text="TITLE"
android:textColor="#android:color/black"
android:textSize="15sp"
android:textStyle="bold"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toRightOf="#+id/ivArticleImage"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/tvDescription"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:ellipsize="end"
android:maxLines="5"
android:text="DESCRIPTION"
android:textColor="#android:color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/ivArticleImage"
app:layout_constraintTop_toBottomOf="#+id/tvTitle" />
<TextView
android:id="#+id/tvPublishedAt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="PUBLISHED AT"
android:textColor="#android:color/black"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tvSource" />
</androidx.constraintlayout.widget.ConstraintLayout>
RecyclerView 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">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvBreakingNews"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="#+id/paginationProgressBar"
style="?attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
android:background="#android:color/transparent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
my adapter class
private const val TAG = "NewsAdapter"
class NewsAdapter : RecyclerView.Adapter<NewsAdapter.ArticleViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder {
val binding = ItemRowBinding.inflate(LayoutInflater.from(parent.context))
return ArticleViewHolder(binding)
}
override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {
val article = differ.currentList[position]
// holder.bind(article)
holder.binding.apply {
Glide.with(this.root).load(article.urlToImage).into(ivArticleImage)
tvSource.text = article.source.name
tvTitle.text = article.title
tvDescription.text = article.description
tvPublishedAt.text = article.publishedAt
this#NewsAdapter.setOnItemClickListener {
onItemClickListener?.let {
it(article)
}
}
}
}
override fun getItemCount(): Int {
return differ.currentList.size
}
inner class ArticleViewHolder( val binding: ItemRowBinding) :
RecyclerView.ViewHolder(binding.root) {
private var onItemClickListener: ((Article) -> Unit)? = null
private fun setOnItemClickListener(listener: (Article) -> Unit) {
onItemClickListener = listener
}
private val diffCallBack = object : DiffUtil.ItemCallback<Article>() {
override fun areItemsTheSame(oldItem: Article, newItem: Article): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Article, newItem: Article): Boolean {
return oldItem == newItem
}
}
val differ = AsyncListDiffer(this, diffCallBack)
}
ACTIVITY:
val list : MutableList<Item> = mutableListOf()
list.add(Item("TITLE", "DESCRITION", "ESPN", "2022-08-02T14:32:47Z"))
val rv = findViewById<RecyclerView>(R.id.rvBreakingNews)
rv.layoutManager = LinearLayoutManager(applicationContext)
rv.adapter = RvAdapter(list)
ADAPTER
class RvAdapter(private var list : List<Item>) : RecyclerView.Adapter<RvAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.title.setText(list[position].getTitle())
holder.desc.setText(list[position].getDescription())
holder.source.setText(list[position].getSource())
holder.published.setText(list[position].getPublished())
}
// return the number of the items in the list
override fun getItemCount(): Int {
return list.size
}
// Holds the views for adding it to image and text
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val title : TextView = itemView.findViewById(R.id.tvTitle)
val desc : TextView = itemView.findViewById(R.id.tvDescription)
val source : TextView = itemView.findViewById(R.id.tvSource)
val published : TextView = itemView.findViewById(R.id.tvPublishedAt)
val imageView : ImageView = itemView.findViewById(R.id.ivArticleImage)
}
}
ACTIVITY XML (SAME AS YOURS):
<?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">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="#+id/paginationProgressBar"
style="?attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
android:background="#android:color/transparent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
ITEM XML(SAME AS YOURS):
<?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="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="2"
android:orientation="horizontal">
<ImageView
android:id="#+id/ivArticleImage"
android:layout_width="0dp"
android:layout_height="90dp"
android:layout_weight="0.8"
android:background="#android:drawable/sym_def_app_icon"
android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.2"
android:orientation="vertical">
<TextView
android:id="#+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:ellipsize="end"
android:maxLines="2"
android:textColor="#color/black"
android:textSize="15sp"
android:textStyle="bold"
tools:text="TITLE" />
<TextView
android:id="#+id/tvDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:ellipsize="end"
android:maxLines="3"
android:textColor="#color/black"
android:text="DESCRIPTION" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="#+id/tvSource"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="SOURCE"
android:textColor="#android:color/black" />
<TextView
android:id="#+id/tvPublishedAt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="PUBLISHED AT"
android:textColor="#android:color/black"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tvSource" />
</LinearLayout>
I found the problem causes this spilled of screen, here in this line
val binding = ItemRowBinding.inflate(LayoutInflater.from(parent.context))
you just inflated the inflater of a parent but there are two parameters is missing,
the viewGroup which it "parent and attachToRoot = false
edit your onCreateViewHolder like this
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = ItemRowBinding.inflate(inflater,parent,false)
return ArticleViewHolder(binding)
}

Horizontal RecyclerView in Horizontal RecyclerView is not scrolling

I have horizontal recycler view in which each child has nested scroll view in which I have another horizontal recycler view. View seems to bo displaying fine but I am not able to scroll child recycler view. When I am trying to scroll - parent recycler view is scrolling, which is not what I want. Already was trying to set android:nestedScrollingEnabled="false” but it’s not working.
Main view 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=".views.home.WeatherView">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_WeatherRecycler"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="#+id/pb_WeatherLoading"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Parent recycler view item xml:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
app:cardCornerRadius="40dp"
app:cardElevation="5dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:srcCompat="#drawable/ic_location">
<ImageView
android:id="#+id/iv_CityImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
tools:srcCompat="#tools:sample/avatars"
/>
<androidx.core.widget.NestedScrollView
android:id="#+id/sv_ScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/iv_LocationIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
app:layout_constraintEnd_toStartOf="#+id/tv_CityName"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/ic_location" />
<TextView
android:id="#+id/tv_CityName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="#+id/iv_LocationIcon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/iv_LocationIcon"
app:layout_constraintTop_toTopOf="#+id/iv_LocationIcon" />
<TextView
android:id="#+id/tv_CurrentTemp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="400dp"
android:text="TextView"
android:textSize="48sp"
app:layout_constraintBottom_toTopOf="#+id/tv_CurrentWeatherDesc"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/iv_LocationIcon"
app:layout_constraintVertical_chainStyle="spread" />
<TextView
android:id="#+id/tv_CurrentWeatherDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="TextView"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="#+id/tv_SunriseLabel"
app:layout_constraintEnd_toEndOf="#+id/tv_CurrentTemp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="#+id/tv_CurrentTemp"
app:layout_constraintTop_toBottomOf="#+id/tv_CurrentTemp" />
<TextView
android:id="#+id/tv_SunriseLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="Sunrise"
app:layout_constraintBottom_toTopOf="#+id/tv_SunsetLabel"
app:layout_constraintEnd_toStartOf="#+id/tv_SunriseValue"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_CurrentWeatherDesc" />
<TextView
android:id="#+id/tv_SunsetLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="32dp"
android:text="Sunset"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/tv_SunsetValue"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_SunriseLabel" />
<TextView
android:id="#+id/tv_SunriseValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:text="SunriseVal"
app:layout_constraintBaseline_toBaselineOf="#+id/tv_SunriseLabel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/tv_SunriseLabel" />
<TextView
android:id="#+id/tv_SunsetValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:text="SunsetVal"
app:layout_constraintBaseline_toBaselineOf="#+id/tv_SunsetLabel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/tv_SunsetLabel" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_HourlyForecastRecycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="32dp"
android:scrollbars="horizontal|vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_SunsetLabel" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Child item xml:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardCornerRadius="10dp"
app:cardElevation="4dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv_HourlyForecast_Time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="TextView"
app:layout_constraintBottom_toTopOf="#+id/iv_ForecastHourly_WeatherIcon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/iv_ForecastHourly_WeatherIcon"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="#+id/tv_HourlyForecast_Temp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_HourlyForecast_Time"
app:srcCompat="#drawable/ic_error" />
<TextView
android:id="#+id/tv_HourlyForecast_Temp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/iv_ForecastHourly_WeatherIcon" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Main view code:
#AndroidEntryPoint
class WeatherView : Fragment() {
private var _binding: FragmentWeatherViewBinding? = null
private val binding: FragmentWeatherViewBinding get() = _binding!!
private val viewModel by viewModels<WeatherViewModel>()
private lateinit var weatherAdapter: WeatherAdapter
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentWeatherViewBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val cities = getSavedCitiesFromFirebase()
viewModel.getWeatherAndImageForCities(cities)
setupRecyclerView()
observeWeatherData()
}
private fun observeWeatherData() {
viewModel.citiesLoadingLiveData.observe(viewLifecycleOwner, { isLoading ->
if (isLoading) {
showLoading(true)
} else {
showLoading(false)
}
})
viewModel.citiesDataLiveData.observe(viewLifecycleOwner, { cities ->
if (cities != null) {
weatherAdapter.setCities(cities)
}
})
viewModel.cityFetchErrorLiveData.observe(viewLifecycleOwner, {
/* To Do */
})
}
private fun setupRecyclerView() {
weatherAdapter = WeatherAdapter()
binding.rvWeatherRecycler.apply {
layoutManager = LinearLayoutManager(
requireContext(), RecyclerView.HORIZONTAL, false
)
adapter = weatherAdapter
}
}
private fun showLoading(isLoading: Boolean) {
binding.pbWeatherLoading.visibility = if (isLoading) View.VISIBLE else View.GONE
}
private fun getSavedCitiesFromFirebase(): List<String> {
return listOf("Berlin", "Amsterdam")
}
}
Parent recycler view adapter code:
class WeatherAdapter: RecyclerView.Adapter<WeatherAdapter.WeatherViewHolder>() {
private var cities: MutableList<CityData> = mutableListOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeatherViewHolder {
val itemBinding = ItemWeatherBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return WeatherViewHolder(itemBinding.root, itemBinding)
}
override fun onBindViewHolder(holder: WeatherViewHolder, position: Int) {
holder.bind(cities[position])
}
override fun getItemCount(): Int {
return cities.size
}
fun setCities(newCities: List<CityData>) {
cities.clear()
cities.addAll(newCities)
notifyDataSetChanged()
}
class WeatherViewHolder(private val itemView: View, private val itemBinding: ItemWeatherBinding): RecyclerView.ViewHolder(itemBinding.root) {
fun bind(item: CityData) {
itemBinding.rvHourlyForecastRecycler.apply {
layoutManager = LinearLayoutManager(
itemView.context, RecyclerView.HORIZONTAL, false
)
adapter = HourlyForecastAdapter(item.forecastModel.list)
setHasFixedSize(true)
}
itemBinding.tvCityName.text = item.weatherModel.name
itemBinding.tvCurrentTemp.text = TemperatureConverter.convertKelvinToCelsius(item.weatherModel.main.temp).toString()
itemBinding.tvCurrentWeatherDesc.text = item.weatherModel.weather[0].description
itemBinding.tvSunriseValue.text = TimeConverter.convertTime(item.weatherModel.sys.sunrise)
itemBinding.tvSunsetValue.text = TimeConverter.convertTime(item.weatherModel.sys.sunset)
Glide
.with(itemBinding.ivCityImage)
.load(item.cityImg)
.error(R.drawable.ic_error)
.centerCrop()
.into(itemBinding.ivCityImage)
}
}
}
Child recycler view adapter code:
class HourlyForecastAdapter(private val forecast: List<WeatherForecast>): RecyclerView.Adapter<HourlyForecastAdapter.HourlyForecastViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HourlyForecastViewHolder {
val itemBinding = ItemWeatherHourlyForecastBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return HourlyForecastViewHolder(itemBinding)
}
override fun onBindViewHolder(holder: HourlyForecastViewHolder, position: Int) {
holder.bind(forecast[position])
}
override fun getItemCount(): Int {
return forecast.size
}
class HourlyForecastViewHolder(private val itemBinding: ItemWeatherHourlyForecastBinding): RecyclerView.ViewHolder(itemBinding.root) {
fun bind(item: WeatherForecast) {
Timber.d("DT: ${item.dt}")
itemBinding.tvHourlyForecastTime.text = TimeConverter.convertTime(item.dt.toInt())
itemBinding.tvHourlyForecastTemp.text = TemperatureConverter.convertKelvinToCelsius(item.main.temp).toString()
Glide
.with(itemBinding.ivForecastHourlyWeatherIcon)
.load("https://openweathermap.org/img/wn/${item.weather[0].icon}#2x.png")
.error(R.drawable.ic_error)
.centerCrop()
.into(itemBinding.ivForecastHourlyWeatherIcon)
}
}
}

Multiple RecyclerView(two) has lag - android

I have a list that load in RecyclerView with CardView and in CardView I have a RecyclerView that have (max) 10 items, I load it now, but it has lag:
My First LessonContentListAdapter.kt:
class LessonContentListAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var onItemClickListener: ((LessonsContentList) -> Unit)? = null
fun setOnItemClickListener(listener: (LessonsContentList) -> Unit) {
onItemClickListener = listener
}
private val callback = object : DiffUtil.ItemCallback<LessonsContentList>() {
override fun areItemsTheSame(
oldItem: LessonsContentList,
newItem: LessonsContentList
): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(
oldItem: LessonsContentList,
newItem: LessonsContentList
): Boolean {
return oldItem == newItem
}
}
val differ = AsyncListDiffer(this, callback)
override fun getItemCount(): Int {
return differ.currentList.size
}
inner class LessonContentListItems(private val lessonContentListItemsBinding: LessonContentListItemsBinding) :
RecyclerView.ViewHolder(lessonContentListItemsBinding.root) {
fun bind(lessons: LessonsContentList) {
lessonContentListItemsBinding.txtContentTitleO.text = lessons.titleOriginal
lessonContentListItemsBinding.txtContentTitleT.text = lessons.titleTranslate
lessonContentListItemsBinding.txtTime.text = lessons.timeLaps
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view =
LessonContentListItemsBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
return LessonContentListItems(view)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as LessonContentListItems).bind(differ.currentList[position])
val childLessonContentListVectorsAdapter =
ChildLessonContentListVectorsAdapter(
differ.currentList[position].imgLevels
)
holder.itemView.recyclerLessonsContentListVectors.layoutManager = LinearLayoutManager(
holder.itemView.recyclerLessonsContentListVectors.context,
LinearLayoutManager.HORIZONTAL,
false
)
holder.itemView.recyclerLessonsContentListVectors.setHasFixedSize(true)
holder.itemView.recyclerLessonsContentListVectors.adapter =
childLessonContentListVectorsAdapter
}
}
Second ChildLessonContentListVectorsAdapter.kt:
class ChildLessonContentListVectorsAdapter(imgLevels: List<ImgLevelsDetalis>) :
RecyclerView.Adapter<ChildLessonContentListVectorsAdapter.MyViewHolder>() {
var childModelArrayList: List<ImgLevelsDetalis> = imgLevels
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var heroImage: ImageView
init {
heroImage = itemView.findViewById(R.id.imgHaveStudied)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.child_lessons_content_list, parent, false)
return MyViewHolder(view)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val currentItem: ImgLevelsDetalis = childModelArrayList[position]
holder.heroImage.setImageResource(currentItem.img)
}
override fun getItemCount(): Int {
return childModelArrayList.size
}
}
First fragment_lesson_content_list.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"
android:background="#color/white"
android:clickable="true"
android:fitsSystemWindows="true"
android:focusable="true"
tools:context=".presentation.ui.lessoncontentlist.LessonContentListFragment">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbarLessonContentList"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/purple_500"
android:contentInsetStart="0dp"
android:contentInsetLeft="0dp"
android:minHeight="?attr/actionBarSize"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
app:contentInsetStartWithNavigation="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<ImageButton
android:id="#+id/imgBackContent"
android:layout_width="50dp"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:background="#null"
android:paddingLeft="10dp"
android:src="#drawable/ic_baseline_arrow_back_24" />
<TextView
android:id="#+id/txtTitleContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textColor="#color/white"
android:textStyle="bold" />
</RelativeLayout>
</androidx.appcompat.widget.Toolbar>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerLessonsContentList"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/toolbarLessonContentList" />
</androidx.constraintlayout.widget.ConstraintLayout>
second lesson_content_list_items.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
card_view:cardBackgroundColor="#color/purple_700"
card_view:cardCornerRadius="4dp"
card_view:layout_constraintLeft_toLeftOf="parent"
card_view:layout_constraintRight_toRightOf="parent"
card_view:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:weightSum="10">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_weight="5"
android:orientation="horizontal"
android:weightSum="10">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="8"
android:orientation="vertical">
<TextView
android:id="#+id/txtContentTitleO"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Grammer"
android:textColor="#color/white"
android:textStyle="bold" />
<TextView
android:id="#+id/txtContentTitleT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="مکالمه"
android:textColor="#color/white" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:gravity="right"
android:orientation="horizontal">
<TextView
android:id="#+id/txtTime"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:text="2Min"
android:textColor="#color/white"
android:textStyle="bold" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="5dp"
android:adjustViewBounds="true"
android:scaleType="center"
android:src="#drawable/ic_baseline_timelapse_24" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:gravity="right"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerLessonsContentListVectors"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:orientation="horizontal" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
Third child_lessons_content_list.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_gravity="right">
<ImageView
android:id="#+id/imgHaveStudied"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Firstly, you can use setInitialItemPrefetchCount() for a prefetching feature for nested RecyclerView. for more information please check this article
I think, the main reason, loading images from the server blocks the main thread. You can do this asynchronously. please check this article too.

How to test(tdd) an element inside child recycler view?

add to cart errorI've used a recycler view inside another recycler view. While using test-driven development, I was trying to test the click functionality of add to cart button code as follows:
MenuDishAdapter- child recycler view
MenuAdapter- parent recycler view
class MenuAdapter(private val context: Context, val menuList:List<MenuData>, val menuActivity: MenuActivity):RecyclerView.Adapter<MenuAdapter.MenuViewHolder>() {
class MenuViewHolder(private val itemBinding:RvDishGroupBinding):RecyclerView.ViewHolder(itemBinding.root) {
val dishGroupBinding:RvDishGroupBinding = itemBinding
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MenuViewHolder = MenuViewHolder(
RvDishGroupBinding.inflate(LayoutInflater.from(parent.context), parent, false))
#SuppressLint("CutPasteId")
override fun onBindViewHolder(holder: MenuViewHolder, position: Int) {
val getPos= menuList[position]
holder.dishGroupBinding.dishCatgTypeMtv.text=getPos.categoryType
val adapter = MenuDishAdapter(context, menuList[position].categoryDish, menuActivity, )
holder.dishGroupBinding.dishLl.adapter= adapter
/*Logger.i("Menu list size ${menuList.size}")
Logger.i("Menu list $menuList")*/
if(position==menuList.size-1)
{
holder.dishGroupBinding.rvGroupSeparatorVw.visibility= View.GONE
}
}
override fun getItemCount(): Int = menuList.size
}
class MenuDishAdapter(
private val context: Context,
val menuList: List<DishData>,
val menuActivity: MenuActivity
) :
RecyclerView.Adapter<MenuDishAdapter.MenuDishViewHolder>() {
class MenuDishViewHolder(private val dishItem: RvDishItemBinding) :
RecyclerView.ViewHolder(dishItem.root) {
val dishItemBinding = dishItem
}
var isFavourite: Boolean = false
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MenuDishViewHolder =
MenuDishViewHolder(
RvDishItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
override fun onBindViewHolder(holder: MenuDishViewHolder, position: Int) {
val getPos= menuList[position]
Glide.with(context).load(getPos.dishImage).placeholder(R.drawable.img_dessert).into( holder.dishItemBinding.rvDishImgIv)
holder.dishItemBinding.rvDishNameMtv.text= getPos.dishName
if(getPos.dishDescription.isNullOrEmpty())
{
holder.dishItemBinding.rvDishDescriptionMtv.visibility=View.GONE
}
else
{
holder.dishItemBinding.rvDishDescriptionMtv.text= getPos.dishDescription
}
holder.dishItemBinding.rvDishPriceMtv.text= "$"+ getPos.dishPrice
if(!getPos.isVeg)
{
holder.dishItemBinding.rvDishTypeIv.backgroundTintList=
ContextCompat.getColorStateList(menuActivity, R.color.red)
}
holder.dishItemBinding.rvDishCustomizationMtv.text= context.getString(R.string.your_customisations_are)+" Radish, Mushroom, carrots, turnip, radish"
holder.dishItemBinding.rvDishFavMarkIb.setOnClickListener {
if(isFavourite)
{
holder.dishItemBinding.rvDishFavMarkIb.setBackgroundResource(R.drawable.ic_unfav)
Toast.makeText(context, "${getPos.dishName} removed from Favourite. ", Toast.LENGTH_SHORT).show()
notifyDataSetChanged()
isFavourite= false
}
else
{
holder.dishItemBinding.rvDishFavMarkIb.setBackgroundResource(R.drawable.ic_fav)
Toast.makeText(context, "${getPos.dishName} marked Favourite. ", Toast.LENGTH_SHORT).show()
notifyDataSetChanged()
isFavourite=true
}
}
holder.dishItemBinding.rvAddToCartBtn.setOnClickListener {
Utils.printShortToast(context, "${getPos.dishName} added to the cart")
}
holder.dishItemBinding.rvDishCustomizeBtn.setOnClickListener {
Utils.printShortToast(context, "${getPos.dishName} customised")
}
}
override fun getItemCount(): Int = menuList.size
}
XML for MenuDishAdapter
<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="133dp"
android:layout_marginStart="6dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="6dp"
android:id="#+id/rv_dish_item_ll">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/detail_parent_cl"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:id="#+id/rv_dish_img_cv"
android:layout_width="109dp"
android:layout_height="104dp"
android:elevation="5dp"
app:cardCornerRadius="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/rv_dish_img_iv"
android:layout_width="109dp"
android:layout_height="104dp"
android:scaleType="fitXY"
tools:src="#drawable/img_fav_2" />
</androidx.cardview.widget.CardView>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/dish_details_ll"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="0dp"
android:orientation="vertical"
android:weightSum="5"
app:layout_constraintBottom_toBottomOf="#id/rv_dish_img_cv"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/rv_dish_img_cv"
app:layout_constraintTop_toTopOf="#id/rv_dish_img_cv">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/dish_name_cl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_weight="1"
android:orientation="horizontal">
<com.google.android.material.textview.MaterialTextView
android:id="#+id/rv_dish_name_mtv"
style="#style/TextAppearance.MdcTypographyStyles.Body22"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginEnd="8dp"
android:ellipsize="end"
android:gravity="start"
android:maxLines="1"
android:textColor="#color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/rv_dish_type_iv"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Masala Noodles" />
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/rv_dish_type_iv"
android:layout_width="21dp"
android:layout_height="18dp"
android:layout_gravity="end"
android:background="#drawable/ic_veg_dish"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/detail_middle_cl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:orientation="horizontal">
<LinearLayout
android:id="#+id/text_ll"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/rv_dish_fav_mark_ib"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textview.MaterialTextView
android:id="#+id/rv_dish_description__mtv"
style="#style/TextAppearance.MdcTypographyStyles.Body12"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:layout_marginEnd="2dp"
android:layout_marginStart="0dp"
android:textAlignment="textStart"
android:textColor="#color/black"
tools:text="#string/description" />
<com.google.android.material.textview.MaterialTextView
android:id="#+id/rv_dish_price_mtv"
style="#style/TextAppearance.MdcTypographyStyles.Body22"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textAlignment="textStart"
tools:text="$10.5" />
</LinearLayout>
<androidx.appcompat.widget.AppCompatImageButton
android:id="#+id/rv_dish_fav_mark_ib"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:clickable="true"
android:elevation="5dp"
android:focusable="true"
android:paddingStart="10dp"
android:paddingTop="0dp"
android:paddingEnd="0dp"
android:paddingBottom="5dp"
android:background="#drawable/ic_unfav"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/buttons_cl"
android:layout_width="match_parent"
android:layout_height="23dp"
android:layout_marginTop="2dp"
android:paddingBottom="1dp"
android:paddingTop="0dp"
android:layout_weight="1"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatButton
android:id="#+id/rv_add_to_cart_btn"
style="#style/TextAppearance.MdcTypographyStyles.Button1"
android:layout_width="109dp"
android:layout_height="0dp"
android:layout_marginStart="0dp"
android:layout_marginEnd="2dp"
android:background="#drawable/bg_button"
android:backgroundTint="#color/primaryColor"
android:drawableStart="#drawable/ic_button_cart"
android:drawablePadding="0dp"
android:focusable="true"
android:padding="2dp"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:text="#string/add_to_cart"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatButton
android:id="#+id/rv_dish_customize_btn"
style="#style/TextAppearance.MdcTypographyStyles.Button1"
android:layout_width="109dp"
android:layout_height="0dp"
android:layout_marginStart="2dp"
android:layout_marginEnd="0dp"
android:background="#drawable/bg_button"
android:backgroundTint="#color/black"
android:focusable="true"
android:padding="2dp"
android:text="#string/customize"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
<com.google.android.material.textview.MaterialTextView
android:id="#+id/rv_dish_customization_mtv"
style="#style/TextAppearance.MdcTypographyStyles.Body12"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="3dp"
android:ellipsize="end"
android:maxLines="1"
android:text="#string/your_customisations_are"
android:textAlignment="textStart"
android:textColor="#color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#id/dish_details_ll"
app:layout_constraintStart_toStartOf="#id/rv_dish_img_cv"
app:layout_constraintTop_toBottomOf="#id/rv_dish_img_cv"
tools:text="Your customisations are - Onion, Tomato, Mushroom, cucumber, radish" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
Now while testing the add to cart button the test case is as follows:
**Class name: MenuActivityTest
see code commented in testingMenuList() **
#RunWith(AndroidJUnit4::class)
#LargeTest
class MenuActivityTest {
#get:Rule
var rule = ActivityScenarioRule(MenuActivity::class.java)
//test to check the visibility of the menu screen layout on the device
#Test
fun checkScreenDisplay() {
onView(withId(R.id.menu_cl))
.check(matches(isDisplayed()))
}
#Test
fun testingMenuList() {
//testing whether the recycler view is displayed for not
onView(withId(R.id.menu_rv)).check(matches(isDisplayed()))
onView(allOf(withId(R.id.dish_ll), isDisplayed()))
//testing the scroll to position to 3rd position
onView(withId(R.id.menu_rv)).perform(
RecyclerViewActions
.scrollToPosition<RecyclerView.ViewHolder>(3)
)
//testing a particular item of the list
onView(allOf(withId(R.id.dish_catg_type_mtv), withText("Beverages")))
onView(allOf(withId(R.id.rv_dish_name_mtv), withText("Coffee")))
onView(allOf(withId(R.id.rv_dish_price_mtv), withText("0")))
onView(
allOf(
withId(R.id.rv_dish_description__mtv),
withText("Because ground coffee beans, coffee roasts, and brewing methods vary, so do coffee drinks. They come in so many different varieties and flavors, such as black coffee, espresso, latte, cappuccino, or mocha.")
)
)
/*onView(allOf(isDisplayed(), withId(R.id.rv_add_to_cart_btn)))
.perform(RecyclerViewActions.actionOnItemAtPosition<MenuDishAdapter.MenuDishViewHolder>(2, click()));
*/
/*val result = onView(
allOf(
withId(R.id.rv_add_to_cart_btn),
withText("Coffee")
)
).perform(
click()
)
Utils.printErrorLog("Result is: $result")*/
onView(allOf(withId(R.id.rv_add_to_cart_btn), isDescendantOfA(allOf(withId(R.id.buttons_cl))))).check(matches(isFocusable()))
*/
/* onData(allOf(withId(R.id.rv_add_to_cart_btn)))
.inAdapterView(allOf(withId(R.id.rv_dish_item_ll)))
.atPosition(1)
.perform(click())*/
}
}
Each and every time in running the testingMenuList I'm getting the error(screenshot attached).
What is the correct method to check the add to cart button click functionality?
The flow is as: MenuActivity has a recycler view menu_rv and this menu_rv contains another recycler view name dish_ll. Inside dish_ll, rv_add_to_cart_btn is the button that is being tested using the TDD approach.

why imageview not showing inside cardview?

I am developing a new app but image view not showing inside card view I want to know exactly where I am making a mistake
below my layout
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/cardview"
android:layout_width="match_parent"
android:layout_height="93dp"
android:layout_marginTop="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/companyLogo"
android:layout_width="45dp"
android:layout_height="26dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="11dp"
android:layout_marginRight="11dp"
android:padding="4dp"
android:scaleType="fitXY"
app:layout_constraintBottom_toTopOf="#+id/companyWebsite"
app:layout_constraintEnd_toStartOf="#+id/companyName"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
<TextView
android:id="#+id/companyWebsite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="56dp"
android:layout_marginLeft="56dp"
android:layout_marginTop="40dp"
android:text="Company Website"
android:textSize="8sp"
app:layout_constraintBottom_toBottomOf="#id/companyLogo"
app:layout_constraintStart_toStartOf="#+id/companyLogo"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<TextView
android:id="#+id/companyName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginEnd="286dp"
android:layout_marginRight="286dp"
android:text="Company Name"
android:textSize="8sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/companyLogo"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
My current UI from the real device:
below my RecyclerviewAdapter class where I have downloaded image view using glide and implemented ImageView logic
below my RecyclerviewAdapter class where I have downloaded image view using glide and implemented ImageView logic
class SpectrumAdapter(
private val spectrumResponse: ArrayList <SpectrumResponseItem>
) : RecyclerView.Adapter<SpectrumViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SpectrumViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.spectrum_list, parent, false)
return SpectrumViewHolder(view)
}
override fun getItemCount(): Int {
return spectrumResponse.size
}
override fun onBindViewHolder(holder: SpectrumViewHolder, position: Int) {
return holder.bind(spectrumResponse[position])
}
}
class SpectrumViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val companyLogo: ImageView = itemView.findViewById(R.id.companyLogo)
private val companyName: TextView = itemView.findViewById(R.id.companyName)
private val companyWebsite: TextView = itemView.findViewById(R.id.companyWebsite)
fun bind(spectrum: SpectrumResponseItem) {
Glide.with(itemView.context).load(spectrum.logo).into(companyLogo)
companyName.text = spectrum.company
companyWebsite.text = spectrum.website
}
}

Categories

Resources