Issue with constraint layout not showing unless I add absolute dimension - android

I have this layout and am trying to switch on a corresponding LL based on a position. However the first Linear Layout will only show up and be drawn if I give the text view inside an absolute dimension such as 200dp for the width, I have tried 0dp with constraints as well.
<?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:id="#+id/draft_rider_container"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#000000"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="match_parent"
android:layout_height="30dp"
android:text="lost"
android:textColor="#android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
<LinearLayout
android:id="#+id/section"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="gone">
<TextView
android:id="#+id/fake"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
tools:text="Andrea Dovizioso's"></TextView>
</LinearLayout>
<LinearLayout
android:id="#+id/row"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="gone">
<TextView
android:id="#+id/rider_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
tools:text="Andrea Dovizioso's"></TextView>
</LinearLayout>
This layout is rendered from a recycler view that is on my fragment which is placed like this :
<?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=".roster.RosterFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/player_rider_list"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#ffffff"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginRight="15dp"
android:layout_marginBottom="15dp"
android:src="#drawable/baseline_edit_white_24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:rippleColor="#color/colorPrimary" />
And here is my adapter :
class PlayerRidersAdapter : RecyclerView.Adapter<PlayerRidersAdapter.ViewHolder>() {
var riderList = ArrayList<Rider>()
override fun onCreateViewHolder(parent: ViewGroup, position: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.rider_item_layout, null, false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return riderList.count() + 2
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
when(position) {
0 -> showHeader(holder)
3 -> showSection(holder)
else -> showRow(holder)
}
}
fun showHeader(holder: ViewHolder) {
holder.headerContainer.visibility = View.VISIBLE
holder.sectionContainer.visibility = View.GONE
holder.rowContainer.visibility = View.GONE
}
fun showRow(holder: ViewHolder) {
holder.headerContainer.visibility = View.GONE
holder.sectionContainer.visibility = View.GONE
holder.rowContainer.visibility = View.VISIBLE
//holder.name.text = rider.name
}
fun showSection(holder: ViewHolder) {
holder.headerContainer.visibility = View.GONE
holder.sectionContainer.visibility = View.VISIBLE
holder.rowContainer.visibility = View.GONE
}
fun addRiders(riders : ArrayList<Rider>){
riderList.addAll(riders)
notifyDataSetChanged()
}
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var headerContainer = view.findViewById<LinearLayout>(R.id.header)
var sectionContainer = view.findViewById<LinearLayout>(R.id.section)
var rowContainer = view.findViewById<LinearLayout>(R.id.row)
var name = view.findViewById<TextView>(R.id.rider_name)
}
}

In your adapter, specify the following in onCreateViewHolder():
val view = LayoutInflater.from(parent.context).inflate(R.layout.rider_item_layout, parent, false)
Specifying the root argument will let the inflated layout be sized properly. This is most likely your problem.
However, match_parent sometimes has strange behavior when used in ConstraintLayout, so use 0dp instead and remember to constrain the effected sides. It would be nice for ConstraintLayout to either handle this case, report it as an error or, at least, support a Lint check.
An aside: The constraints on the TextViews that are held within a LinearLayout have no effect. Constraints only apply to direct children of ConstraintLayout.

Related

Recyclerview in Recyclerview scrolling first time laggy

I have Recyclerview multiple view types and have Recyclerview in Recyclerview when scroll lag first time I do not know why scroll lag first time
here my layout fragment
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:id="#+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presentation.LottoFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/teal_700"
android:padding="20dp">
<LinearLayout
android:id="#+id/searchLinearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/menuTextInputLayout"
style="#style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/label">
<AutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="#+id/contentLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_peekHeight="56dp"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/ic_list_header_background"
android:clickable="true"
android:elevation="4dp"
android:orientation="horizontal"
android:padding="20dp">
<TextView
android:id="#+id/lotto_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="#font/kanit_light"
android:text="0 items(s)" />
<ImageView
android:id="#+id/filterIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:src="#android:drawable/arrow_up_float"
android:visibility="gone" />
</LinearLayout>
<LinearLayout
android:id="#+id/front_layer_linear_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/lotto_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="64dp"
tools:itemCount="3"
tools:listitem="#layout/item_lotto_prizes_one" />
</LinearLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
here my fragment
lottoRecyclerView.apply {
layoutManager = LinearLayoutManager(context)
adapter = lottoLatestAdapter
}
here my Adapter:
class LottoLatestAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
companion object {
private const val VIEW_TYPE_LOTTO_PRIZE_ONE = 1
private const val VIEW_TYPE_LOTTO_PRIZE_RUNNING_NUMBER = 2
private const val VIEW_TYPE_LOTTO_PRIZE_ONE_NEAR = 3
private const val VIEW_TYPE_LOTTO_PRIZE_OTHER = 4
}
var latestList: MutableList<LottoPrizesLatestModel> = mutableListOf()
set(value) {
field = value
notifyDataSetChanged()
}
private val viewPool : RecycledViewPool = RecycledViewPool()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
VIEW_TYPE_LOTTO_PRIZE_ONE -> {
LottoPrizeOneHolder(ItemLottoPrizesOneBinding.inflate(inflater, parent, false))
}
VIEW_TYPE_LOTTO_PRIZE_RUNNING_NUMBER -> {
LottoPrizeRunningNumberHolder(
ItemLottoRunningNumbersBinding.inflate(
inflater,
parent,
false
)
)
}
VIEW_TYPE_LOTTO_PRIZE_ONE_NEAR -> {
LottoPrizeOneNearHolder(
ItemLottoPrizesOneNearBinding.inflate(
inflater,
parent,
false
)
)
}
VIEW_TYPE_LOTTO_PRIZE_OTHER -> {
LottoPrizeOtherListHolder(
ItemLottoPrizesOtherListBinding.inflate(
inflater,
parent,
false
),
LottoLatestPrizeOtherAdapter()
)
}
else -> throw NullPointerException("Not have view Type")
}
}
override fun getItemViewType(position: Int): Int {
return when (latestList[position]) {
is LottoPrizesLatestModel.LottoLatestPrizeOne -> VIEW_TYPE_LOTTO_PRIZE_ONE
is LottoPrizesLatestModel.LottoLatestRunningNumbers -> VIEW_TYPE_LOTTO_PRIZE_RUNNING_NUMBER
is LottoPrizesLatestModel.LottoLatestPrizeFirstNear -> VIEW_TYPE_LOTTO_PRIZE_ONE_NEAR
is LottoPrizesLatestModel.LottoLatestPrizeOther -> VIEW_TYPE_LOTTO_PRIZE_OTHER
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is LottoPrizeOneHolder -> holder.bind(latestList[position] as LottoPrizesLatestModel.LottoLatestPrizeOne)
is LottoPrizeRunningNumberHolder -> holder.bind(latestList[position] as LottoPrizesLatestModel.LottoLatestRunningNumbers)
is LottoPrizeOneNearHolder -> holder.bind(latestList[position] as LottoPrizesLatestModel.LottoLatestPrizeFirstNear)
is LottoPrizeOtherListHolder -> {
viewPool.putRecycledView(holder)
holder.bind(latestList[position] as LottoPrizesLatestModel.LottoLatestPrizeOther, viewPool)
}
}
}
override fun getItemCount(): Int = latestList.size
}
here my layout holder
<?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:layout_margin="8dp">
<TextView
android:id="#+id/title_prize_other_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="#font/kanit_light"
android:gravity="center"
android:textSize="26sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/prize_other_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/title_prize_other_text_view"
tools:itemCount="10"
tools:listitem="#layout/item_lotto_prizes_other" />
<GridLayout
android:id="#+id/prize_other_grip_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="2"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/title_prize_other_text_view" />
<TextView
android:id="#+id/text_prize_one_near_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/kanit_light"
android:text="#string/lotto_prize_per_baht"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/prize_other_recycler_view" />
</androidx.constraintlayout.widget.ConstraintLayout>
and here my holder recyclerView in RecyclerView
class LottoPrizeOtherListHolder(
private val binding: ItemLottoPrizesOtherListBinding,
private val lottoLatestPrizeOtherAdapter: LottoLatestPrizeOtherAdapter
) :
RecyclerView.ViewHolder(binding.root) {
fun bind(
lottoLatestPrizeOther: LottoPrizesLatestModel.LottoLatestPrizeOther,
viewPool: RecyclerView.RecycledViewPool
) = with(binding) {
prizeOtherRecyclerView.apply {
layoutManager = GridLayoutManager(
context,
2,
GridLayoutManager.VERTICAL,
false
).apply {
initialPrefetchItemCount = lottoLatestPrizeOther.prizeModel.number.size
}
this.adapter = lottoLatestPrizeOtherAdapter
setRecycledViewPool(viewPool)
}
lottoLatestPrizeOtherAdapter.numberList =
lottoLatestPrizeOther.prizeModel.number.toMutableList()
titlePrizeOtherTextView.text = lottoLatestPrizeOther.prizeModel.name
textPrizeOneNearTextView.text = itemView.context.getString(
R.string.lotto_prize_per_baht,
lottoLatestPrizeOther.prizeModel.reward
)
}
}
my problem is : When i scroll recyclerview for first time it is not smooth and logcat show recyclerview Skipped 51 frames! adapter but when I reach end of recyclerView and scroll to up then scroll down it is very smooth and my recyclerview have TextView Only !!! how can I solve this issue?
this my video App https://youtu.be/Li7aKWmEfXQ
In your fragment add this after applying LayoutManager:
lottoRecyclerView.setDrawingCacheEnabled(true);
lottoRecyclerView.setItemViewCacheSize(myCacheSize);
The main reason Jank occurs the first time because on the first time it is loading the values onto memory dynamically. while once it is down it already has a few elements pre loaded
You can handle it using
mRecyclerView.setHasFixedSize(true);
mRecyclerview.setNestedScrollingEnabled(false);
in your kotlin code
or add android:nestedScrollingEnabled="false" in your RecyclerView xml
You can reach some performance improvements by applying the following:
recyclerView.setHasFixedSize(true);
recyclerView.setDrawingCacheEnabled(true);
..in combination with lite mode of MapsView:
<com.google.android.gms.maps.MapView
android:layout_width="match_parent"
android:layout_height="200dp"
app:liteMode="true"
app:mapType="normal" />
For it was not an option to disable nestedScrollingEnabled as mentioned by #Narendra_Nath, which further improves performance.

RecyclerView list weirdly displayed

I'm trying to display a list of files and folders using a RecyclerView.
Here is the Adapter and the ViewHolder :
class FilesRecyclerViewAdapter(private val files: Array<File>) : RecyclerView.Adapter<FilesRecyclerViewAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.fragment_file_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = files[position]
holder.icon.setImageResource(if (item.isDirectory) R.drawable.folder else R.drawable.file)
holder.fileName.text = item.name
}
override fun getItemCount(): Int = files.size
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val icon: ImageView = view.findViewById(R.id.icon)
val fileName: TextView = view.findViewById(R.id.fileName)
}
}
The layout for a single item in the list (R.layout.fragment_file_item) :
<?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:id="#+id/fileItem"
android:layout_width="match_parent"
android:layout_height="#dimen/file_item_height">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
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
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="#string/icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/ic_launcher_foreground" />
<TextView
android:id="#+id/fileName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:text="Element"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="#+id/icon"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
And this is how it's included into the main activity :
<?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/fileSystem"
android:layout_width="match_parent"
android:layout_height="match_parent"
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" />
</androidx.constraintlayout.widget.ConstraintLayout>
Finally the code in the onCreate function of the main activity :
private lateinit var fileSystem: RecyclerView
// Later in the code
fileSystem = findViewById(R.id.fileSystem)
fileSystem.layoutManager = LinearLayoutManager(this)
fileSystem.adapter = FilesRecyclerViewAdapter(Environment.getExternalStorageDirectory().listFiles())
I expected to have a list of items with the icon on the left and the name of the folder slighly to the right like on the item layout preview :
Instead, I have this mess :
What did I do wrong ?
app:layout_constraintHorizontal_bias="0.5" makes your RecyclerView start on 50% of view.
Remove it, if you dont need them

Fragment takes time to load RecyclerView when the list is large

I have a RecyclerView implemented along with Paging to load a list from Room Database. The list works fine when the size is small. When the size reaches around 50 - 60, the list still works fine but when i switch to another fragment and then come back to the list, its blocks the UI for around 1.5 - 2 seconds which is super dull in user experience (See GIF below):
My code is as follows:
DAO
#Query("SELECT * FROM account_table WHERE userID = :userID")
fun getAll(userID: String): DataSource.Factory<Int, Account>
Repository
class AccountRepository private constructor(application: Application) {
private val database =
LockyDatabase.getDatabase(
application
)
private val accountDao = database.accountDao()
companion object {
#Volatile
private var instance: AccountRepository? = null
fun getInstance(application: Application) =
instance ?: synchronized(this) {
instance ?: AccountRepository(application).also { instance = it }
}
}
fun getAll(userID: String) = accountDao.getAll(userID)
}
adapter
class CredentialsPagingAdapter(
private val clickListener: ClickListener,
private val optionsClickListener: OptionsClickListener?,
private val isSimplified: Boolean
) : PagedListAdapter<Credentials, CredentialsViewHolder>(
diffCallback
) {
companion object {
private val diffCallback = object : DiffUtil.ItemCallback<Credentials>() {
override fun areItemsTheSame(oldItem: Credentials, newItem: Credentials): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Credentials, newItem: Credentials): Boolean {
return oldItem.equals(newItem)
}
}
}
override fun onBindViewHolder(holder: CredentialsViewHolder, position: Int) {
holder.bind(
clickListener,
optionsClickListener,
getItem(position),
isSimplified
)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CredentialsViewHolder {
return CredentialsViewHolder.from(
parent
)
}
}
viewModel
val accounts = Transformations.switchMap(_sort) {
when (true) {
it.name -> _accounts.sortByEntryName
it.username -> _accounts.sortByUsername
it.email -> _accounts.sortByEmail
it.website -> _accounts.sortByWebsite
it.authType -> _accounts.sortByAuthenticationType
else -> _accounts
}.toLiveData(pageSize = resources.getInteger(R.integer.size_paging_list_default))
}
fragment
private fun subscribeAccounts() {
val adapter = CredentialsPagingAdapter(
/* The click listener to handle account on clicks */
ClickListener {
navigateTo(
AccountFragmentDirections.actionFragmentAccountToFragmentViewAccount(
it as Account
)
)
},
/* The click listener to handle popup menu for each accounts */
OptionsClickListener { view, credential ->
view.apply {
isEnabled = false
}
createPopupMenu(view, credential as Account)
},
false
)
binding.RecyclerViewAccount.apply {
/*
* State that layout size will not change for better performance
*/
setHasFixedSize(true)
/* Bind the layout manager */
layoutManager = LinearLayoutManager(requireContext())
/* Bind the adapter */
this.adapter = adapter
}
viewModel.accounts.observe(viewLifecycleOwner, Observer {
if (it != null) {
/*
* If accounts is not null
* Load recyclerview and
* Update the ui
*/
lifecycleScope.launch {
adapter.submitList(it as PagedList<Credentials>)
}
updateUI(it.size)
}
})
}
Main Activity Layout
<?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"
xmlns:tools="http://schemas.android.com/tools">
<androidx.drawerlayout.widget.DrawerLayout
android:id="#+id/Drawer_Main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.main.MainActivity">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="#+id/Layout_Coordinator_Main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/Toolbar_Main"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#drawable/custom_rounded_background_toolbar"
android:clipChildren="false"
android:outlineAmbientShadowColor="#color/colorShadowColor"
android:outlineSpotShadowColor="#color/colorShadowColor"
android:paddingStart="8dp"
android:paddingEnd="8dp"
app:contentInsetStartWithNavigation="0dp"
tools:targetApi="p">
...
</com.google.android.material.appbar.MaterialToolbar>
<androidx.core.widget.NestedScrollView
android:id="#+id/Nested_Scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"
android:fillViewport="true">
<fragment
android:id="#+id/Navigation_Host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/navigation_drawer_main"
tools:ignore="FragmentTagUsage" />
</androidx.core.widget.NestedScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton ... />
<com.google.android.material.floatingactionbutton.FloatingActionButton ... />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/Navigation_View"
style="#style/Locky.Widget.Custom.NavigationView"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:clipToPadding="false"
android:paddingStart="0dp"
android:paddingEnd="16dp"
app:headerLayout="#layout/drawer_header"
app:itemTextAppearance="#style/Locky.Text.Body.Drawer"
app:menu="#menu/menu_drawer_main" />
</androidx.drawerlayout.widget.DrawerLayout>
</layout>
Fragment Account Layout:
<?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"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<import type="com.th3pl4gu3.locky_offline.repository.Loading.List" />
<variable
name="ViewModel"
type="com.th3pl4gu3.locky_offline.ui.main.main.account.AccountViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/Layout_Fragment_Account"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorOnSurface">
<!--
Recyclerview
-->
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/RecyclerView_Account"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="#{ViewModel.loadingStatus==List.LIST ? View.VISIBLE : View.GONE}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="gone" />
<!--
Empty Views and group
-->
<androidx.constraintlayout.widget.Group
android:id="#+id/Empty_View"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="#{ViewModel.loadingStatus==List.EMPTY_VIEW ? View.VISIBLE : View.GONE}"
app:constraint_referenced_ids="Empty_View_Illustration,Empty_View_Title,Empty_View_Subtitle" />
<ImageView
android:id="#+id/Empty_View_Illustration" ... />
<TextView
android:id="#+id/Empty_View_Title" ... />
<TextView
android:id="#+id/Empty_View_Subtitle" ... />
<!--
Progress Bar
-->
<include
android:id="#+id/Progress_Bar"
layout="#layout/custom_view_list_loading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="#{ViewModel.loadingStatus==List.LOADING ? View.VISIBLE : View.GONE}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Recyclerview List Layout
<?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"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="IsSimplifiedVersion"
type="Boolean" />
<variable
name="Credential"
type="com.th3pl4gu3.locky_offline.core.main.credentials.Credentials" />
<variable
name="ClickListener"
type="com.th3pl4gu3.locky_offline.ui.main.main.ClickListener" />
<variable
name="OptionsClickListener"
type="com.th3pl4gu3.locky_offline.ui.main.main.OptionsClickListener" />
</data>
<com.google.android.material.card.MaterialCardView
style="#style/Locky.ListCardView"
credentialCardConfiguration="#{Credential}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:clickable="true"
android:focusable="true"
android:onClick="#{() -> ClickListener.onClick(Credential)}">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/Credential_Logo"
configureLogo="#{Credential}"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginEnd="16dp"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/Barrier_Logo"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="#drawable/ic_locky_with_background_circle" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/Barrier_Logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="Credential_Logo" />
<TextView
android:id="#+id/Credential_Entry_Name"
style="#style/Locky.Text.Title6.List"
listTitleMessageCardEligibility="#{Credential}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:ems="11"
android:singleLine="true"
android:text="#{Credential.entryName}"
app:layout_constraintBottom_toTopOf="#+id/Credential_First_Subtitle"
app:layout_constraintStart_toEndOf="#id/Barrier_Logo"
app:layout_constraintTop_toTopOf="#+id/Credential_Logo"
app:layout_constraintVertical_chainStyle="spread_inside"
tools:text="This is an entry name and it can be very very very long" />
<TextView
android:id="#+id/Credential_First_Subtitle"
style="#style/Locky.Text.Subtitle.List.Primary"
setCredentialSubtitle="#{Credential}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:ems="13"
android:singleLine="true"
app:layout_constraintBottom_toTopOf="#+id/Credential_Second_Subtitle"
app:layout_constraintStart_toStartOf="#+id/Credential_Entry_Name"
app:layout_constraintTop_toBottomOf="#+id/Credential_Entry_Name"
app:layout_constraintVertical_chainStyle="spread"
tools:text="This is the very first subtitle and this can be very long too" />
<TextView
android:id="#+id/Credential_Second_Subtitle"
style="#style/Locky.Text.Subtitle.List.Secondary"
setCredentialOtherSubtitle="#{Credential}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:ems="14"
android:singleLine="true"
android:textColor="#color/colorAccent"
app:layout_constraintBottom_toBottomOf="#+id/Credential_Logo"
app:layout_constraintStart_toStartOf="#+id/Credential_Entry_Name"
app:layout_constraintTop_toBottomOf="#+id/Credential_First_Subtitle"
app:layout_constraintVertical_chainStyle="spread"
tools:text="This is the second subtitle and this can be very long too" />
<androidx.constraintlayout.widget.Barrier
android:id="#+id/Barrier_More_Options"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="start"
app:constraint_referenced_ids="Credential_More_Options" />
<ImageButton
android:id="#+id/Credential_More_Options"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:background="#drawable/custom_states_background_button_image"
android:onClick="#{(view) -> OptionsClickListener.onClick(view, Credential)}"
android:scaleType="centerCrop"
android:src="#drawable/ic_more_options"
android:visibility="#{IsSimplifiedVersion ? View.GONE : View.VISIBLE}"
app:layout_constraintBottom_toBottomOf="#+id/Credential_Logo"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/Barrier_More_Options"
app:layout_constraintTop_toTopOf="#+id/Credential_Logo" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</layout>
My paging version is 2.1.2
Can someone please help me on this. I tried several days looking for fix but nothing works.
I appreciate the help.
You must remove your NestedScrollView (Nested_Scroll) in your activity layout - you cannot put a vertical RecyclerView within a NestedScrollView.
A NestedScrollView expands every child in the vertical scroll direction to determine the maximum scroll distance. This means that it gives the RecyclerView an infinite height to expand into. This causes RecyclerView to inflate every element, defeating all view recycling and defeating the use of paging - given infinite height, it'll continue to ask Paging for more and more rows to fill the space.

How to scale width of ViewHolder proportionally to height with animations?

I have the following layout file -
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:id="#+id/fragment_marketplace_root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/fragment_marketplace_appbarlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="220dp"
android:fitsSystemWindows="true"
android:minHeight="150dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:titleEnabled="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_collapseMode="pin"
app:layout_collapseParallaxMultiplier="0">
<com.twoverte.views.ClearableAutoCompleteTextView
android:id="#+id/fragment_marketplace_searchview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="14dp"
android:layout_marginEnd="14dp"
android:completionThreshold="0"
android:hint="#string/fragment_marketplace_search_hint"
android:iconifiedByDefault="false"
android:inputType="text|textAutoCorrect"
android:maxLength="25"
android:textIsSelectable="false"
android:textSelectHandle="#xml/empty_shape"
tools:layout_editor_absoluteX="1dp"
tools:layout_editor_absoluteY="1dp" />
<TextView
android:id="#+id/fragment_marketplace_discover_products_from_myverte_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="14dp"
android:layout_marginTop="15dp"
android:fontFamily="#font/noto_sans"
android:text="#string/fragment_marketplace_discover_products_from_myverte"
android:textSize="17sp"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/fragment_marketplace_vendors_recycler_view"
android:layout_width="wrap_content"
android:layout_height="130dp"
android:layout_gravity="bottom"
android:minHeight="40dp"
android:orientation="horizontal"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="1"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="#layout/fragment_marketplace_vendor_row_item" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="#+id/fragment_marketplace_featured_products_nested_scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/fragment_marketplace_featured_products_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/very_light_grey"
android:fontFamily="#font/noto_sans"
android:paddingStart="14dp"
android:paddingLeft="14dp"
android:paddingTop="15dp"
android:paddingEnd="14dp"
android:text="#string/fragment_marketplace_featured_products"
android:textSize="17sp"
android:visibility="gone"
tools:visibility="visible" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/fragment_marketplace_products_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="#color/very_light_grey"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
tools:itemCount="2"
tools:listitem="#layout/fragment_marketplace_products_row_item" />
<View
android:id="#+id/activity_product_page_bottom_view"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_marginTop="60dp"
android:background="#color/light_black"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
and inside my onViewCreated I have the following code -
import kotlinx.android.synthetic.main.fragment_marketplace.fragment_marketplace_vendors_recycler_view as vendorsList
...
...
// onViewCreated ->
val originalVendorListHeight: Int = vendorsList.layoutParams?.height!!
appBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, value ->
vendorsList.updateLayoutParams {
this.height = originalVendorListHeight + value
(this as CollapsingToolbarLayout.LayoutParams).setMargins(0, 0, 0, abs(value))
}
})
Which creates an animation of the top horizontal RV of it being expanding with it's height up and down up to a cap which is what I need.
The issue I am facing now is that each ViewHolder inside that RV is not proportional once expanded as I am only changing it's height and not width and I am facing an issue trying to set the width of each individual VH as I can't rely on it's parent size as before with the height.
Here is my adapter and VH -
class VendorAdapter(private val miniVendorModels: List<MiniVendorModel>, private val context: Context) : RecyclerView.Adapter<VendorsHolder>() {
companion object {
const val EXTRA_VENDOR_MODEL = "EVM"
}
private val vendorsHoldersList = mutableListOf<VendorsHolder>()
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): VendorsHolder {
val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.fragment_marketplace_vendor_row_item, viewGroup, false)
val vendorsHolder = VendorsHolder(view)
vendorsHoldersList.add(vendorsHolder)
return vendorsHolder
}
override fun onBindViewHolder(vendorsHolder: VendorsHolder, i: Int) {
val model = miniVendorModels[i]
Picasso.get().load(model.bannerPicture).into(vendorsHolder.vendorImageView)
vendorsHolder.vendorImageView.setOnClickListener { v: View? ->
try {
val intent = Intent(context, VendorPageActivity::class.java)
intent.putExtra(EXTRA_VENDOR_MODEL, model)
context.startActivity(intent)
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(context, ResourceHelper.getString(R.string.marketplace_vendor_unavailable), Toast.LENGTH_SHORT).show()
}
}
}
override fun getItemCount(): Int = miniVendorModels.size
}
class VendorsHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var vendorImageView: ImageView = itemView.findViewById(R.id.vendors_row_item_imageview)
var rootLayout: ConstraintLayout = itemView.findViewById(R.id.vendors_row_item_root_layout)
var vendorHolderCardview: CardView = itemView.findViewById(R.id.search_image_contact_cardview)
}
<?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:id="#+id/vendors_row_item_root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:id="#+id/search_image_contact_cardview"
android:layout_width="152dp"
android:layout_height="match_parent"
android:layout_margin="5dp"
app:cardCornerRadius="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/vendors_row_item_imageview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
tools:src="#mipmap/ic_launcher" />
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
As you can see, the ViewHolders are Match Parent in height meaning that they will expand with their parents.
I can't use the same trick for the width as it is a horizontal RV, so I will need to use a different method to enable the expanding and reducing all of the RV's VH width.
solved -
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): VendorsHolder {
val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.fragment_marketplace_vendor_row_item, viewGroup, false)
val vendorsHolder = VendorsHolder(view)
vendorsHoldersList.add(vendorsHolder)
vendorsHolder.rootLayout.addOnLayoutChangeListener(object : View.OnLayoutChangeListener {
override fun onLayoutChange(v: View?, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {
vendorsHolder.rootLayout.updateLayoutParams {
this.width = 152 + bottom
}
}
})
return vendorsHolder
}
where 152 is my base width of the viewholder

How to scroll NestedScrollView with a ListView inside?

I'm creating an activity in which I need to show several elements and a listview, and I want that when the user does scroll I want to scroll all the activity not only the listview, for this, I implemented a NestedScrollView, but the scroll does not work, it remains without scrolling, do I need an attribute? or is there a better way to do what I need to do?
I attach my XML code:
<androidx.core.widget.NestedScrollView 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:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- Other items -->
<ListView
android:id="#+id/lvAC"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
try this way:
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView 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"
android:fillViewport="true"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="#+id/view"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#drawable/ic_launcher_background"/>
<ListView
android:id="#+id/lvAC"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#+id/view"
android:nestedScrollingEnabled="true"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
and set this method to your listview :
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
}
Nesting a ListView inside a ScrollView is problematic as it causes multiple vertical scrolling behaviors which is confusing to the user. Instead, use a single RecyclerView that can provide multiple ViewTypes.
Your RecyclerView adapter should implement getItemViewType, returning the number of different views you need to display. For instance, if you have:
<androidx.core.widget.NestedScrollView 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:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- Other items -->
<View
android:id="#+id/view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
/>
<View
android:id="#+id/view2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/view1"
app:layout_constraintStart_toStartOf="parent"
/>
<ListView
android:id="#+id/lvAC"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="#id/view2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
You should have a layout like:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
/>
And your adapter should be something like:
class MyViewHolder(val rootView: View) : RecyclerView.ViewHolder(rootView)
class MyAdapter(val items: List<Any>) : RecyclerView.Adapter<MyViewHolder>() {
companion object {
const val TYPE_VIEW1 = 1
const val TYPE_VIEW2 = 2
const val TYPE_ITEMS = 3
}
override fun getItemViewType(position: Int): Int = when (position) {
0 -> TYPE_VIEW1
1 -> TYPE_VIEW2
else -> TYPE_ITEMS
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder = when (viewType) {
TYPE_VIEW1 -> MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_view1, parent, false))
TYPE_VIEW2 -> MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_view2, parent, false))
else -> MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_other, parent, false))
}
override fun getItemCount(): Int = 2 + items.size
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}

Categories

Resources