I am using a Recycler view to show Some Card Views.
Each item of recycler view contains a long text.
I am trying to make that text scrollable.
I tried wrapping the text inside a Nested Scroll View.
But on swiping the item, the whole recycler view is scrolled, instead of the text inside the item.
simpler version of my recycler view item layout.
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:onClick="#{()->viewHolder.navigateToDetails()}"
android:paddingHorizontal="25dp"
android:paddingVertical="15dp">
<androidx.core.widget.NestedScrollView
android:id="#+id/crib_text_scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constrainedHeight="true"
app:layout_constraintHeight_max="300dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/category">
<com.example.presentation.custom_views.ReadMoreTextView
android:id="#+id/crib_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
app:mainText="#{cribResponse.post}"
tools:mainText="#tools:sample/lorem[20]" />
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
layout of the fragment that contains recycler view
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/crib_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:nestedScrollingEnabled="true"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="#layout/item_text_crib" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Adapter class
class CribAdapter(private val rvHost: RVHost) :
PagingDataAdapter<CribResponse, CribViewHolder>(diffCallback) {
private val allAudioViewHolders: MutableList<AudioCribViewHolder> = mutableListOf()
var playingViewHolder: AudioCribViewHolder? = null
companion object {
val diffCallback = object : DiffUtil.ItemCallback<CribResponse>() {
override fun areItemsTheSame(oldItem: CribResponse, newItem: CribResponse): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(oldItem: CribResponse, newItem: CribResponse): Boolean {
return oldItem.postId == newItem.postId
}
}
}
override fun onBindViewHolder(holder: CribViewHolder, position: Int) {
val item = getItem(position)
item ?: return
holder.bind(item)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CribViewHolder {
return if (viewType == AUDIO_CRIB) {
AudioCribViewHolder(parent = parent, RVHost = rvHost).apply {
markCreated()
allAudioViewHolders.add(this)
}
} else {
TextCribViewHolder(parent = parent, rvHost = rvHost)
}
}
override fun getItemViewType(position: Int): Int {
val item = getItem(position)
val audio = item?.postAudio
return if (audio == null) TEXT_CRIB else AUDIO_CRIB
}
override fun onViewAttachedToWindow(holder: CribViewHolder) {
super.onViewAttachedToWindow(holder)
if (holder is AudioCribViewHolder) {
holder.markAttach()
}
}
override fun onViewDetachedFromWindow(holder: CribViewHolder) {
super.onViewDetachedFromWindow(holder)
if (holder is AudioCribViewHolder) {
val isPlaying = holder.playing.value ?: false
if (isPlaying) {
holder.resetUI()
playingViewHolder = null
rvHost.stop()
}
holder.markDetach()
}
}
fun selfLifecycleDestroyed() {
allAudioViewHolders.forEach {
it.markDestroyed()
}
}
fun getCrib(position: Int): CribResponse? {
return getItem(position)
}
}
Related
enter image description here
When I click on cardview I want the other cardview color to turn white
here design is that i show in recyclerview
<?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="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:backgroundTint="#android:color/transparent"
android:elevation="0dp"
android:paddingBottom="10dp">
<androidx.cardview.widget.CardView
android:id="#+id/mainCard"
android:layout_width="80dp"
android:layout_height="100dp"
android:layout_marginLeft="1dp"
android:layout_marginTop="1dp"
android:layout_marginBottom="10dp"
app:cardCornerRadius="10dp"
app:cardElevation="15dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/cardImage"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_gravity="center"
android:layout_marginBottom="20dp"
app:srcCompat="#drawable/cate1" />
<TextView
android:id="#+id/mainText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="10dp"
android:text="Telefon, Tablet\nve Aksesuarlar"
android:textColor="#302E2E"
android:textSize="10sp" />
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="#+id/colorCard"
android:layout_width="82dp"
android:layout_height="102dp"
android:visibility="invisible"
app:cardBackgroundColor="#color/orange"
app:cardCornerRadius="10dp"
app:cardElevation="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
The block with adapter codes for the recyclerview that I have listed
I couldn't understand the logic in setOnclickListener
and
I don't know how to make an algorithm
class CategoryMainAdapter(val mContext: Context) :
RecyclerView.Adapter<CategoryMainAdapter.ViewHolderClass>() {
var categoryMainList: List<CategoryMain> = listOf()
inner class ViewHolderClass(view: View) : RecyclerView.ViewHolder(view) {
val mainCard: CardView
val cardImage: ImageView
val mainText: TextView
val colorCard: CardView
init {
mainCard = view.findViewById(R.id.mainCard)
cardImage = view.findViewById(R.id.cardImage)
mainText = view.findViewById(R.id.mainText)
colorCard = view.findViewById(R.id.colorCard)
}
}
#SuppressLint("NotifyDataSetChanged")
fun setList(list: List<CategoryMain>) {
categoryMainList = list
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolderClass {
val design =
LayoutInflater.from(mContext).inflate(R.layout.main_category_design, parent, false)
return ViewHolderClass(design)
}
override fun onBindViewHolder(holder: ViewHolderClass, position: Int) {
val categoryMain = categoryMainList[position]
holder.mainText.text = categoryMain.categoryName
holder.cardImage.setImageResource(categoryMain.categoryPhoto)
holder.mainCard.setOnClickListener() {
holder.colorCard.visibility = View.VISIBLE
holder.mainText.setTextColor(ContextCompat.getColor(mContext, R.color.orange))
}
}
override fun getItemCount(): Int {
return categoryMainList.size
}
}
You can use a multi-select functionality in recycler view like this: How to implement multi-select in RecyclerView? or Multiple selected items RecyclerView in Activity.java
i solved my problem
now when i click on which cardview its color changes
class CategoryMainAdapter(val mContext: Context) :
RecyclerView.Adapter<CategoryMainAdapter.ViewHolderClass>() {
var categoryMainList: List<CategoryMain> = listOf()
var clikedPosition : Int = -1
inner class ViewHolderClass(view: View) : RecyclerView.ViewHolder(view) {
val mainCard: CardView
val cardImage: ImageView
val mainText: TextView
val colorCard: CardView
init {
mainCard = view.findViewById(R.id.mainCard)
cardImage = view.findViewById(R.id.cardImage)
mainText = view.findViewById(R.id.mainText)
colorCard = view.findViewById(R.id.colorCard)
}
}
#SuppressLint("NotifyDataSetChanged")
fun setList(list: List<CategoryMain>) {
categoryMainList = list
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolderClass {
val design =
LayoutInflater.from(mContext).inflate(R.layout.main_category_design, parent, false)
return ViewHolderClass(design)
}
override fun onBindViewHolder(holder: ViewHolderClass, position: Int) {
val categoryMain = categoryMainList[position]
holder.mainText.text = categoryMain.categoryName
holder.cardImage.setImageResource(categoryMain.categoryPhoto)
if (categoryMain.isSelected == true){
categoryMainList[position].isSelected = false
holder.colorCard.visibility = View.INVISIBLE
holder.mainText.setTextColor(ContextCompat.getColor(mContext, R.color.blacklow))
}
holder.mainCard.setOnClickListener() {
if (clikedPosition != -1){
notifyItemChanged(clikedPosition)
}
clikedPosition = position
categoryMainList[position].isSelected = true
holder.colorCard.visibility = View.VISIBLE
holder.mainText.setTextColor(ContextCompat.getColor(mContext, R.color.orange))
}
}
override fun getItemCount(): Int {
return categoryMainList.size
}
}
I am working with nested recyclerView. According to business logic, first I have to call an API that fetched the list of item that is shown in the Parent recycler view. After that, if a user clicks any of the items of the parent recycler view, another API is called which fetches a list of sub-items, and I have to show the item list in the inner recycler view of that clicked-positioned parent recycler view.
I successfully implemented showing items in the parent recycler view and sub-items in the clicked-position nested recycler view.
But the problem I am facing is when I clicked any specific item of the parent recycler view, all the other nested recycler view's item get changed with the newly populated sub-items value.
How can I solve this issue?. Here is the sample code
main_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat 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:orientation="vertical">
<com.google.android.material.card.MaterialCardView
style="#style/CardViewStyle"
android:id="#+id/chapter_layout"
android:layout_width="match_parent">
<com.google.android.material.textview.MaterialTextView
android:id="#+id/chapter_name_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<com.google.android.material.textview.MaterialTextView
android:id="#+id/header_text_view"
android:layout_width="0dp"
android:layout_height="wrap_content"/>
</com.google.android.material.card.MaterialCardView>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/chapter_topic_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="3"
tools:listitem="#layout/item_main" />
</androidx.appcompat.widget.LinearLayoutCompat>
MainItemViewHolder.kt
class MainItemViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
fun bind(item: SpecificChapter, onClick: (SpecificChapter, Int) -> Unit) {
with(view) {
chapter_name_text_view.text = "Chapter "+ item.no
header_text_view.text = item.name
chapter_layout.setOnClickListener { onClick(item, bindingAdapterPosition) }
}
}
}
MainItemAdapter.kt
class MainItemAdapter(
val onClick: (SpecificChapter, Int) -> Unit
) : ListAdapter<SpecificChapter, MainItemViewHolder>(DIFF_CALLBACK) {
companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<SpecificChapter>() {
override fun areItemsTheSame(old: SpecificChapter, aNew: SpecificChapter) = (old.id == aNew.id)
override fun areContentsTheSame(old: SpecificChapter, aNew: SpecificChapter) = (old == aNew)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainItemViewHolder {
return MainItemViewHolder(parent.inflate(R.layout.main_item))
}
override fun onBindViewHolder(holder: MainItemViewHolder, position: Int) {
holder.bind(getItem(position)!!, onClick)
}
}
sub_item.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView
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">
<com.google.android.material.textview.MaterialTextView
android:id="#+id/chapter_topic_text_view"
android:layout_width="0dp"
android:layout_height="wrap_content" />
</com.google.android.material.card.MaterialCardView>
SubItemViewHolder.kt
class SubItemViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
fun bind(item: SpecificTopic, onClick: (SpecificTopic) -> Unit) {
with(view) {
chapter_topic_text_view.text = item.name
chapter_topic_layout.setOnClickListener { onClick(item) }
}
}
}
SubItemAdapter.kt
class SubItemAdapter(
val onClick: (SpecificTopic) -> Unit
) : ListAdapter<SpecificTopic, SubItemViewHolder>(DIFF_CALLBACK) {
companion object {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<SpecificTopic>() {
override fun areItemsTheSame(old: SpecificTopic, aNew: SpecificTopic) = (old.id == aNew.id)
override fun areContentsTheSame(old: SpecificTopic, aNew: SpecificTopic) = (old == aNew)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SubItemViewHolder {
return SubItemViewHolder(parent.inflate(R.layout.sub_item))
}
override fun onBindViewHolder(holder: SpecificTopicViewHolder, position: Int) {
holder.bind(getItem(position)!!, onClick)
}
}
activity_chapter.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/chapter_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="#layout/main_item"/>
</androidx.appcompat.widget.LinearLayoutCompat>
ChapterActivity.kt
class ChapterActivity : BaseActivity<ChapterViewModel>() {
var chapterPosition = 0
private val mainItemAdapter: MainItemAdapter by lazy {
MainItemAdapter { specificChapter, position ->
// sub item Api call when clicked specific item. response is viewmodel.allTopics
chapterPosition = position
specificChapter.id?.let { viewModel.getChapterWiseTopics(it) }
}
}
private val subItemAdapter: SubItemAdapter by lazy {
SubItemAdapter {
}
}
override fun onResume() {
super.onResume()
// Main item Api call. response is viewmodel.allChapters
viewModel.getChapters("subject_code")
}
override fun observeLiveData() {
// showing Main item in parent recyclerView
observe(viewModel.allChapters) {
val chapterList = ArrayList<SpecificChapter>()
chapterList.add(SpecificChapter(...))
chapter_recycler_view.adapter = mainItemAdapter
mainItemAdapter.submitList(chapterList)
chapter_recycler_view.setItemViewCacheSize(chapterList.size)
}
// showing sub item in nested recyclerView
observe(viewModel.allTopics) {
val topicList = ArrayList<SpecificTopic>()
topicList.add(SpecificTopic(...))
with((chapter_recycler_view.findViewHolderForAdapterPosition(chapterPosition) as MainItemViewHolder).itemView) {
this.chapter_topic_recycler_view.adapter = subItemAdapter
subItemAdapter.submitList(topicList)
}
}
}
}
I am using a Androidx Paging library with RecyclerView for pagination in my view.
The issue I am facing is when I scroll down RecyclerView, after the mentioned number of PAGE_SIZE, loadAfter is called and once the new data is received, my RecyclerView scroll up to the top(first item) instead of further scroll down.
I debug my code and saw that my RecyclerView's onBindViewHolder also getting called with position 0. So, I think the whole data is being refreshed. Ideally, this should not happen.
Library version:
implementation 'androidx.paging:paging-runtime:2.1.2'
Here is the code:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="viewModel"
type="com.xyz.viewmodel.orders.OrderListViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:background="#color/colorWindowsSecondaryBg"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/_10sdp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<!--List-->
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/srlFav"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
bind:isRefreshing="#{viewModel.refreshVisibility}"
bind:onRefreshListener="#{viewModel.swipeRefreshListener}">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvOrders"
android:layout_width="match_parent"
android:layout_height="0dp"
bind:listitem="#layout/item_order" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/barrierVisibility"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:barrierAllowsGoneWidgets="true"
app:barrierDirection="top"
app:constraint_referenced_ids="clBottomLoading" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/clBottomLoading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/_10sdp"
android:background="#android:color/transparent"
android:paddingTop="#dimen/_2sdp"
android:visibility="#{viewModel.bottomProgressVisibility && !viewModel.refreshVisibility? View.VISIBLE : View.GONE,default=gone}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/barrierVisibility">
<com.github.ybq.android.spinkit.SpinKitView
android:id="#+id/skv_loading_bottom"
style="#style/SpinKitView.ThreeBounce"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#android:color/transparent"
app:SpinKit_Color="#color/colorPrimaryDark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<!--No data layout-->
<include
android:id="#+id/includeError"
layout="#layout/include_layout_error"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="#{!viewModel.progressVisibility && viewModel.errorVisibility ? View.VISIBLE : View.GONE}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:message="#{viewModel.errorString}" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
OrderListDataSource
class OrderListDataSource(
private val orderRepository: OrderRepository,
private val coroutineScope: CoroutineScope?,
private var showProgress: Boolean = true
) : PageKeyedDataSource<Int, OrdersItem>() {
val ordersLiveData: MutableLiveData<Resource<ResOrders>> = MutableLiveData()
override fun loadInitial(
params: LoadInitialParams<Int>,
callback: LoadInitialCallback<Int, OrdersItem>
) {
if (BaseApp.instance?.let { NetworkUtils.isNetworkAvailable(it) } == true) {
if (showProgress) {
ordersLiveData.postValue(Resource.Loading(EnumLoading.LOADING_FIRST_PAGE))
}
coroutineScope?.launch {
val result = orderRepository.getOrders(1)
if (result is ResOrders) {
ordersLiveData.postValue(Resource.Success(result))
result.orders?.let {
callback.onResult(it, null, 2)
}
} else if (result is BaseError) {
ordersLiveData.postValue(Resource.Error(result))
}
}
} else {
ordersLiveData.postValue(Resource.Loading(EnumLoading.LOADING_CLOSE))
}
}
override fun loadAfter(
params: LoadParams<Int>,
callback: LoadCallback<Int, OrdersItem>
) {
if (BaseApp.instance?.let { NetworkUtils.isNetworkAvailable(it) } == true) {
if (showProgress) {
ordersLiveData.postValue(Resource.Loading(EnumLoading.LOADING_MORE))
}
coroutineScope?.launch {
val result = orderRepository.getOrders(params.key)
if (result is ResOrders) {
ordersLiveData.postValue(Resource.Success(result))
result.orders?.let { callback.onResult(it, params.key + 1) }
} else if (result is BaseError) {
ordersLiveData.postValue(Resource.Error(result))
}
}
} else {
ordersLiveData.postValue(Resource.Loading(EnumLoading.LOADING_CLOSE))
}
}
override fun loadBefore(
params: LoadParams<Int>,
callback: LoadCallback<Int, OrdersItem>
) {
}
}
OrderListDataSourceFactory
class OrderListDataSourceFactory(
private val productRepository: OrderRepository, private val coroutineScope: CoroutineScope?
) : DataSource.Factory<Int, OrdersItem>() {
val ordersLiveData = MutableLiveData<OrderListDataSource>()
private var showProgress: Boolean = true
private var orderListDataSource: OrderListDataSource? = null
override fun create(): DataSource<Int, OrdersItem> {
orderListDataSource = OrderListDataSource(
productRepository, coroutineScope,
showProgress
)
ordersLiveData.postValue(orderListDataSource)
return orderListDataSource!!
}
}
OrderListViewModel
private val pageSize = 10
val listHasData = MutableLiveData<Boolean>().apply { value = true }
private val orderListDataSourceFactory: OrderListDataSourceFactory =
OrderListDataSourceFactory(orderRepository, viewModelScope)
init {
val config = PagedList.Config.Builder()
.setPageSize(pageSize)
.setInitialLoadSizeHint(pageSize * 2)
.setEnablePlaceholders(false)
.build()
orderItem = LivePagedListBuilder(orderListDataSourceFactory, config).build()
}
OrdersAdapter
class OrdersAdapter constructor(private val itemTouchListener: ItemTouchListener) :
PagedListAdapter<OrdersItem, OrderViewHolder>(DiffUtilCallBack()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OrderViewHolder {
val mItemProductBinding = DataBindingUtil.inflate<ViewDataBinding>(
LayoutInflater.from(parent.context),
R.layout.item_order,
parent,
false
)
return OrderViewHolder(mItemProductBinding)
}
override fun onBindViewHolder(holder: OrderViewHolder, position: Int) {
getItem(position)?.let {
holder.bind(it)
val itemClickListener: View.OnClickListener = View.OnClickListener { _ ->
itemTouchListener.onOrderClick(position, it)
}
holder.setItemClickListener(itemClickListener)
}
}
class DiffUtilCallBack : DiffUtil.ItemCallback<OrdersItem?>() {
override fun areItemsTheSame(
oldItem: OrdersItem,
newItem: OrdersItem
): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(
oldItem: OrdersItem,
newItem: OrdersItem
): Boolean {
return oldItem.id == newItem.id
&& oldItem.orderDate.equals(newItem.orderDate)
&& oldItem.orderId.equals(newItem.orderId)
&& oldItem.totalPrice == newItem.totalPrice
&& oldItem.deliveryStatus.equals(newItem.deliveryStatus)
}
}
interface ItemTouchListener {
fun onOrderClick(position: Int, ordersItem: OrdersItem)
}
}
class OrderViewHolder constructor(private val binding: ViewDataBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(ordersItem: OrdersItem) {
binding.setVariable(BR.order, ordersItem)
binding.executePendingBindings()
}
fun setItemClickListener(clickListener: View.OnClickListener) {
binding.root.lOrder.setOnClickListener(clickListener)
}
}
OrderListingFragment
mViewModel.orderItem.observe(this, Observer {
ordersAdapter.submitList(it)
})}
mViewModel.getOrders().observe(this, Observer {
...
}
Can anyone please help me with this?
Thank you in advance!
The issue was because of Skeleton I have used with RecyclerView.
mSkeleton?.hide()
This line was called every time I got the API response.
Ideally, the Skeleton will be displayed initially. So, this line should be called only once. I handled this case and now it's working as expected.
I stocked in a problem. I have a listView and this listView is just for showing data row by row and items are all disabled using override function isEnabled to false.
so this is my code:
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/baseLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:paddingTop="10dp"
android:paddingBottom="10dp">
<ListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:divider="#null"
android:dividerHeight="0dp"
android:focusable="false"
android:focusableInTouchMode="false"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
I need to set click listener on baseLayout but every thing I've done not made the focus on baseLayout and listview calls absListView touch listener. any idea?
...
You have to set listener on list cell, such as.
It is example for recyler view, but it is same case on listview.
class SearchListAdapter(private val context: Context) :
RecyclerView.Adapter() {
private var products: List<Repo> = arrayListOf()
var listener: AdapterListener? = null
override fun onCreateViewHolder(parent: ViewGroup, i: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_repo, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return products.size
}
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
viewHolder.bind(position, products[position])
}
fun setList(contacts: List<Repo>) {
this.products = contacts
notifyDataSetChanged()
}
inner class ViewHolder(itemView: View) : BindingViewHolder<ItemRepoBinding>(itemView) {
fun bind(pos: Int, contact: Repo) {
if (binding == null) {
return
}
binding.tvTitle.text = contact.name
binding.setVariable(
BR.tintlist,
context.resources.getColorStateList(R.color.xml_color_btn_title)
)
binding.root.setOnClickListener(View.OnClickListener {
if (listener != null) {
listener?.onClick(pos, contact)
}
})
}
}
interface AdapterListener {
fun onClick(position: Int, info: Repo)
}
}
i just started using Android studio with Kotlin.
I implemented a listView with a custom adapter, but i don't understand how detect when i click on a item of this listview.
This is my class CalAdapter.kt
class CalAdapter(context: Context,al_session:ArrayList<activity_session>) : BaseAdapter(){
private val mInflator: LayoutInflater
private val al_session:ArrayList<activity_session>
init {
this.mInflator = LayoutInflater.from(context)
this.al_session=al_session
}
override fun getCount(): Int {
return al_session.size
}
override fun getItem(position: Int): Any {
return al_session.get(position)
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
#SuppressLint("ResourceAsColor", "PrivateResource")
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View? {
val view: View?
val vh: ListRowHolder
if (convertView == null) {
view = this.mInflator.inflate(R.layout.calendar_adapter, parent, false)
vh = ListRowHolder(view)
view.tag = vh
} else {
view = convertView
vh = view.tag as ListRowHolder
}
vh.label.text = al_session[position].id.toString()
vh.ivImage.setBackgroundColor(R.color.material_blue_grey_800)
when (al_session[position].provided_sport)
{
"swimming" ->
{
//vh.ivImage.setBackgroundColor(R.color.material_blue_grey_800)
vh.ivImage.setImageResource(R.drawable.ic_swiming)
}
"running" ->
{
//vh.ivImage.setBackgroundColor(R.color.white)
vh.ivImage.setImageResource(R.drawable.ic_running)
}
"cycling" ->
{
//vh.ivImage.setBackgroundColor(R.color.material_blue_grey_800)
vh.ivImage.setImageResource(R.drawable.ic_bicycle)
}
}
return view
}
}
private class ListRowHolder(row: View?) {
val label: TextView = row?.findViewById(R.id.TWActivityID) as TextView
val ivImage: ImageButton = row?.findViewById(R.id.CalActivityButton) as ImageButton
}
This is my function where i implement my listview.
lv is my listview.
fun createActivities()
{
val lv = dynamicList
val test=ArrayList<activity_session>()
var i : Int = 0
while (i < 5) {
if (ActivityList.activityList[i] != null) {
test.add(ActivityList.activityList[i])
}
i += 1
}
val obj_adapter: CalAdapter
obj_adapter = CalAdapter(this.view!!.dynamicList.context, test)
lv.adapter=obj_adapter
}
I created a xml file which represent my listview.
<?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">
<LinearLayout
android:id="#+id/AdapterLayout"
android:layout_width="215dp"
android:layout_height="140dp"
android:orientation="horizontal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageButton
android:id="#+id/CalActivityButton"
android:layout_width="wrap_content"
android:layout_height="140dp"
android:layout_weight="1"
app:srcCompat="#drawable/ic_info_black_24dp" />
<TextView
android:id="#+id/TWActivityID"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"
android:text="TextView"
android:visibility="invisible"
tools:layout_editor_absoluteX="92dp"
tools:layout_editor_absoluteY="230dp" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>
Could someone explain me how to detect when i click on an item of the listview i just created ?
EDIT : Hi again i understood how to do it, i added a setOnClickListener method to my imagebutton in my CalAdapter.kt class
now it looks like that : https://imgur.com/a/Vw9SD
On your activity you should add a listener to the listview.
list.setOnItemClickListener { parent, view, position, id ->
val myItem = parent.getItemAtPosition(position) as MyDataObj
}
You should also have the getItem() method filled correctly on your adapter as you do.