flexbox-layout
flexbox-layout copied to clipboard
Scrollbar disappears sometimes during scrolling
- [x] I have searched existing issues and confirmed this is not a duplicate
Issues and steps to reproduce
I don't really know what exact conditions cause this. I have a few screens and it depends on items in the list and/or device (most probably it has something to deal with dimensions of items and screen combined) Here is a video recording of how it behaves. As you can see it disappears while scrolling up and then appears at the very top of the screen.
It reproduces on this screen every time at the same range. One more important thing is that the screen should be scrolled to the very bottom, otherwise it does not disappears.
But here is another video from the different device where it disappears right after user starts scrolling.
Expected behavior
The scrollbar handle is visible during all the scrolling duration.
Version of the flexbox library
1.1.0 and 2.0.0
Link to code
Layout
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:clipToPadding="false"
android:scrollbars="vertical"
android:scrollbarSize="3dp"
android:scrollbarStyle="outsideOverlay"
android:fadeScrollbars="false"
android:scrollbarAlwaysDrawVerticalTrack="true"
app:layoutManager="com.google.android.flexbox.FlexboxLayoutManager"
tools:listitem="@layout/personalization_item"
/>
RecyclerView
setup:
list.apply {
setHasFixedSize(false)
layoutManager = FlexboxLayoutManager(activity)
adapter = mAdapter
setPadding(paddingLeft, paddingTop, paddingRight, dip(184))
}
Adapter
and ViewHolder
s :
data class Item(
val data: PersonalizationItem,
var isSelected: Boolean
)
class PersonalizationAdapter(
private val checkedChangeListener: (Item) -> Unit,
private val title: CharSequence? = null,
private val initiator: PersonalizationActivity.Initiator
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), Filterable {
companion object {
private const val TYPE_TITLE = 0
private const val TYPE_ITEM = 1
private const val TYPE_TITLE_SIMPLE = 2
}
private var mData: List<Item>? = null
private val mFilter: CustomFilter = CustomFilter(this)
private val mFilteredList = ArrayList<Item>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
TYPE_TITLE -> SecondaryPageAdapter.TitleViewHolder(parent, title ?: "")
TYPE_TITLE_SIMPLE -> SimpleTitleViewHolder(parent, title ?: "")
TYPE_ITEM -> ItemViewHolder(parent)
else -> throw Error()
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is ItemViewHolder -> {
val item = if (title == null) mFilteredList[position] else mFilteredList[position - 1]
(holder as? ItemViewHolder)?.bindView(item)
}
else -> {}
}
}
override fun getItemCount(): Int = if (title == null) mFilteredList.size else mFilteredList.size + 1
override fun getItemViewType(position: Int): Int {
return if (title != null && position == 0) {
if (initiator == PersonalizationActivity.Initiator.ONBOARDING) {
TYPE_TITLE
} else {
TYPE_TITLE_SIMPLE
}
} else TYPE_ITEM
}
fun swapData(data: List<Item>) {
mData = data
mFilteredList.clear()
mFilteredList.addAll(data)
notifyDataSetChanged()
}
fun isEmpty(): Boolean = mData?.isEmpty() ?: true
override fun getFilter(): Filter = mFilter
@Suppress("UNUSED_ANONYMOUS_PARAMETER")
inner class ItemViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder(parent.inflate(R.layout.personalization_item)) {
private val mCheck: AppCompatCheckBox = itemView.findViewById(R.id.cbFollow)
private var item: Item? = null
init {
mCheck.setOnCheckedChangeListener { compoundButton, checked ->
item?.let {
it.isSelected = !it.isSelected
checkedChangeListener.invoke(it)
}
}
}
internal fun bindView(item: Item) {
this.item = null
mCheck.text = item.data.title
mCheck.isChecked = item.isSelected
this.item = item
}
}
private inner class CustomFilter constructor(private val mAdapter: PersonalizationAdapter) : Filter() {
override fun performFiltering(constraint: CharSequence): FilterResults {
mFilteredList.clear()
val results = FilterResults()
if (constraint.isEmpty()) {
mFilteredList.addAll(mData ?: emptyList())
} else {
val filterPattern = constraint.toString().toLowerCase().trim { it <= ' ' }
mData?.filterTo(mFilteredList) { it.data.title.toLowerCase().contains(filterPattern) }
}
results.values = mFilteredList
results.count = mFilteredList.size
return results
}
override fun publishResults(constraint: CharSequence, results: FilterResults) {
this.mAdapter.notifyDataSetChanged()
}
}
class SimpleTitleViewHolder(parent: ViewGroup, title: CharSequence): RecyclerView.ViewHolder(parent.inflate(R.layout.onbording_title_item)) {
init {
(itemView as TextView).apply {
@Suppress("DEPRECATION")
text = Html.fromHtml(title.toString()).toString()
textSizeDimen = R.dimen.personalization_list_header_text_size
textColorResource = R.color.masterDarkGrey
}
}
}
}
Item layout:
<?xml version="1.0" encoding="utf-8"?>
<CheckBox
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cbFollow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:background="@drawable/personalization_item_bg"
android:button="@drawable/ic_checkmark"
android:clickable="true"
android:ellipsize="end"
android:focusable="true"
android:lines="1"
android:minHeight="40dp"
android:paddingStart="6dp"
android:paddingTop="8dp"
android:paddingEnd="20dp"
android:paddingBottom="8dp"
android:textColor="#de000000"
android:textSize="16sp"
tools:checked="true"
tools:ignore="RtlSymmetry"
tools:text="name"
/>
Title layout:
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:textSize="23sp"
android:textStyle="normal"
android:textColor="@color/masterBlack"
app:fontFamily="@font/custom_font_family"
android:typeface="serif"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="32dp"
android:layout_marginBottom="16dp"
tools:text="Nesten der. Du kan også tilpasse andre lokale samfunnsinteresser"
/>
Sorry for such a noisy code. I can not sare a repo so I extracted some snippets that should help. If there is something missing please let me know in a comment.
You could also post:
- targetSdkVersion
- compileSdkVersion
- devices used, along with their API level
target
and compile
sdk versions are 28
The first video is Pixel 2 XL running Android 10
The second video is SGS 8 or 9 not sure about sdk version