Pagination in HeterogeneousRecyclerview - android

I am unable to used pagination in HeterogeneousRecyclerview.it contents horizontal and vertical recycleview. I want to use pagination in VerticalRecycleview endless. When I try to do that it will not satisfy conditon.I will return visibleItemCount,totalItemCount and firstVisibleItemPosition that will not help to load more data. Please suggest me.
Recycle view:
val recyclerView = findViewById<RecyclerView>(R.id.rvMain)
val adapter = MainAdapter(this, getObject())
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this)
recycleViewScroll(recyclerView)
private fun getObject(): ArrayList<Any> {
jsonHelper?.readHorizontalItemsJSON()?.get(0)?.let { objects.add(it) }
jsonHelper?.readVerticalItemsJSON()?.get(0)?.let { objects.add(it) }
jsonHelper?.readHorizontalItemsJSON()?.get(0)?.let { objects.add(it) }
return objects as ArrayList<Any>
}
private fun recycleViewScroll(recyclerView: RecyclerView) {
recyclerView.addOnScrollListener(object :
RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val visibleItemCount = recyclerView.layoutManager!!.childCount
val totalItemCount = recyclerView.layoutManager!!.itemCount
val firstVisibleItemPosition =
(recyclerView.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
val lastpositionView = (recyclerView.layoutManager as LinearLayoutManager).findLastVisibleItemPosition()
//val lastpositionView = (recyclerView.layoutManager as LinearLayoutManager).findLastVisibleItemPosition()
println("dsfdsfdsfdfd----->" + visibleItemCount + "," + totalItemCount + "," + firstVisibleItemPosition!! +","+lastpositionView)
if (!isLoading && !isLastPage) {//
if (visibleItemCount + firstVisibleItemPosition!! >= totalItemCount && firstVisibleItemPosition!! >= 0 && totalItemCount >= PAGE_SIZE) {
loadMoreItems()
}
}
}
})
}
}`
Adapter:
class MainAdapter(private val context: Context, private val items: ArrayList<Any>?=null) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val jsonHelper = JsonHelper(context)
//this method returns the number according to the Vertical/Horizontal object
override
fun getItemViewType(position: Int): Int {
if (items?.get(position) is HorizontalModel)
return HORIZONTAL
return if (items?.get(position) is VerticalModel) VERTICAL else -1
}
override
fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(context)
val view: View
val holder: RecyclerView.ViewHolder
when (viewType) {
HORIZONTAL -> {
view = inflater.inflate(R.layout.layout_horizontal_recycler_view, parent, false)
holder = HorizontalViewHolder(view)
}
VERTICAL -> {
view = inflater.inflate(R.layout.layout_vertical_recycler_view, parent, false)
holder = VerticalViewHolder(view)
}
else -> {
view = inflater.inflate(R.layout.layout_horizontal_recycler_view, parent, false)
holder = HorizontalViewHolder(view)
}
}
return holder
}
override
fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder.itemViewType == HORIZONTAL)
horizontalView(holder as HorizontalViewHolder)
else if (holder.itemViewType == VERTICAL)
verticalView(holder as VerticalViewHolder)
}
private fun horizontalView(holder: HorizontalViewHolder) {
val adapter = HorizontalAdapter(context, jsonHelper.readHorizontalItemsJSON()!!)
holder.recyclerView.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
holder.recyclerView.adapter = adapter
}
private fun verticalView(holder: VerticalViewHolder) {
val adapter = VerticalAdapter(context, jsonHelper.readVerticalItemsJSON()!!)
holder.recyclerView.layoutManager = LinearLayoutManager(context)
holder.recyclerView.adapter = adapter
}
override
fun getItemCount(): Int {
return items?.size ?:0
}
inner class HorizontalViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
internal var recyclerView: RecyclerView = itemView.findViewById(R.id.rvHorizontal)
}
inner class VerticalViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
internal var recyclerView: RecyclerView = itemView.findViewById(R.id.rvVertical)
}
}

Related

Lazy Loading for the images in Recycler view

i am not able to do the lazy loading for the images
this is my code of the adapter. I am providing it all the urls from my database in the form of list please help
class Horizontal_lower_recycler(private val images:List<Image>,private val context: Context,private val recyclerView: RecyclerView):
RecyclerView.Adapter<Horizontal_lower_recycler.MyViewHolder>() {
private var isLoading = false
init {
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
val visibleItemCount = layoutManager.childCount
val totalItemCount = layoutManager.itemCount
val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
if (!isLoading) {
if (visibleItemCount + firstVisibleItemPosition >= totalItemCount
&& firstVisibleItemPosition >= 0
&& totalItemCount >= PAGE_SIZE
) {
isLoading = true
}
}
}
})
}
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val image1: ImageView = itemView.findViewById(R.id.lower_image1)
val image2: ImageView = itemView.findViewById(R.id.lower_image2)
val image3: ImageView = itemView.findViewById(R.id.lower_image3)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context).inflate(
R.layout.bootm_recycler,
parent, false
)
return MyViewHolder(view)
}
override fun getItemCount(): Int {
return images.size / 3 + images.size % 3
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val images = images.subList(position * 3, min(position * 3 + 3, images.size))
for (i in images.indices) {
when (i) {
0 -> {
Glide.with(holder.itemView).load(images[i].url).apply(RequestOptions().format(
DecodeFormat.PREFER_RGB_565).disallowHardwareConfig())
.into(holder.image1)
holder.image1.setOnClickListener {
val intent = Intent(context, image_full_size_avtivity::class.java)
intent.putExtra("url", images[i].url)
context.startActivity(intent)
}
}
1 -> {
Glide.with(holder.itemView).load(images[i].url).apply(RequestOptions().format(
DecodeFormat.PREFER_RGB_565).disallowHardwareConfig())
.into(holder.image2)
holder.image2.setOnClickListener {
val intent = Intent(context, image_full_size_avtivity::class.java)
intent.putExtra("url", images[i].url)
context.startActivity(intent)
}
}
2 -> {
Glide.with(holder.itemView).load(images[i].url).apply(RequestOptions().format(
DecodeFormat.PREFER_RGB_565).disallowHardwareConfig())
.into(holder.image3)
holder.image3.setOnClickListener {
val intent = Intent(context, image_full_size_avtivity::class.java)
intent.putExtra("url", images[i].url)
context.startActivity(intent)
}
}
}
}
}
}
Help me in doing the lazy loading. When i open the app all the images are loaded at once without scrolling the recycler view.

Handle pagination with recyclerview gridlayout manager dynamically in android

I am implementing pagination to show data from API by using the recyclerview gridlayout manager. I have tried multiple ways to implement it, finally found a solution but still, it is not working properly. I show data in the list from API, but whenever my data shows in recyclerview from API then it's on scrolllistener automatically works which it should only when I scroll the list.
I am adding a snippet of my code below.
private lateinit var scrollListener: RecyclerviewLoadMore
private lateinit var mLayoutManager: RecyclerView.LayoutManager
//int
private var pageNum = 1
private var limit = 0
motivationAdapter = MotivationsAdapter(requireActivity(), getVideoList, object : RecyclerViewClickHandler {
override fun onItemClicked(position: Int, type: Int, view: View) {
})
rvMotivation?.adapter = motivationAdapter
rvMotivation?.addItemDecoration(SpacesItemDecoration(2, 30, false))
mLayoutManager = GridLayoutManager(requireActivity(), 2)
rvMotivation?.setHasFixedSize(true)
(mLayoutManager as GridLayoutManager).spanSizeLookup =
object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return when (motivationAdapter?.getItemViewType(position)) {
RecyclerScrollEnums.VIEW_TYPE_ITEM.viewType -> 1
RecyclerScrollEnums.VIEW_TYPE_LOADING.viewType -> 2 //number of columns of the grid
else -> -1
}
}
}
Handler(Looper.getMainLooper()).postDelayed({
//scroll listener
scrollListener = RecyclerviewLoadMore(mLayoutManager as GridLayoutManager)
scrollListener.setOnLoadMoreListener(object :
OnLoadMoreListener {
override fun onLoadMore() {
//Get the number of the current Items of the main Arraylist
val start = motivationAdapter?.itemCount
scrollListener.isLoading = false
if(scrollListener.lastVisibleItem==limit){
motivationAdapter?.addLoadingView()
getVideoAPi()
}
}
})
rvMotivation?.addOnScrollListener(scrollListener)
}, 1000)
I notify data when getting data from the API success.
if (response.success == SOCKET_TRUE) {
pageNum += 1
if (limit>0) {
motivationAdapter?.removeLoadingView()
}
limit += response?.data?.size!!
updateAdapterCategory(response.data)
}
fun updateAdapterCategory(getMotivatedList: ArrayList<DataItem?>?) {
getVideoList?.addAll(getMotivatedList!!)
motivationAdapter?.notifyDataSetChanged()
}
This recyclerview scroll listener class which I found on the internet.
class RecyclerviewLoadMore : RecyclerView.OnScrollListener {
private var visibleThreshold = 5
private lateinit var mOnLoadMoreListener: OnLoadMoreListener
internal var isLoading: Boolean = false
internal var lastVisibleItem: Int = 0
internal var totalItemCount: Int = 0
private var mLayoutManager: RecyclerView.LayoutManager
//linear layout manager
constructor(layoutManager: LinearLayoutManager) {
this.mLayoutManager = layoutManager
}
//grid layout manager
constructor(layoutManager: GridLayoutManager) {
this.mLayoutManager = layoutManager
visibleThreshold *= layoutManager.spanCount
}
//staggered layout manager
constructor(layoutManager: StaggeredGridLayoutManager) {
this.mLayoutManager = layoutManager
visibleThreshold *= layoutManager.spanCount
}
//interface to load more data for pagination
fun setOnLoadMoreListener(mOnLoadMoreListener: OnLoadMoreListener) {
this.mOnLoadMoreListener = mOnLoadMoreListener
}
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
totalItemCount = mLayoutManager.itemCount
if (mLayoutManager is StaggeredGridLayoutManager) {
val lastVisibleItemPositions =
(mLayoutManager as StaggeredGridLayoutManager).findLastVisibleItemPositions(null)
// get maximum element within the list
lastVisibleItem = getLastVisibleItem(lastVisibleItemPositions)
} else if (mLayoutManager is GridLayoutManager) {
lastVisibleItem = (mLayoutManager as GridLayoutManager).findLastVisibleItemPosition()
} else if (mLayoutManager is LinearLayoutManager) {
lastVisibleItem = (mLayoutManager as LinearLayoutManager).findLastVisibleItemPosition()
}
if (!isLoading && totalItemCount <= lastVisibleItem + visibleThreshold) {
mOnLoadMoreListener.onLoadMore()
isLoading = true
}
}
private fun getLastVisibleItem(lastVisibleItemPositions: IntArray): Int {
var maxSize = 0
for (i in lastVisibleItemPositions.indices) {
if (i == 0) {
maxSize = lastVisibleItemPositions[i]
} else if (lastVisibleItemPositions[i] > maxSize) {
maxSize = lastVisibleItemPositions[i]
}
}
return maxSize
}
}

When i refresh my pagelist, My items in PageAdapter will be misplaced for a short time

As above pic show, The items will be misplaced momently while i refresh.
smartRefresh.setOnRefreshListener {
mViewModel.observeComposition(ConnectivityUtil.isNetworkReachable(this),mLabelId.toInt(),lifecycleScope).observe(this, Observer {
mCompositionAdapter.submitList(it)
smartRefresh.finishRefresh()
})
}
My Adapter
class CompositionsAdapter(context: Context) : PagedListAdapter<CompositionAbstract, CompositionsAdapter.ViewHolder>(CompositionAbstractDiffCallback()) {
private val mScreenWidth by lazy {
val displayMetrics = DisplayMetrics()
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
windowManager.defaultDisplay.getRealMetrics(displayMetrics)
displayMetrics.widthPixels
}
val width by lazy {
(mScreenWidth - 15.px * 3) / 2
}
val height by lazy {
val srcWidth = 165f.px
val srcHeight = 155f.px
width * (srcHeight / srcWidth)
}
class ViewHolder(private val binding: HomepageItemGroupCompositionBinding)
: RecyclerView.ViewHolder(binding.root) {
fun bind(item: CompositionAbstract) {
binding.apply {
composition = item.briefComposition
itemView.setOnClickListener {
ARouter.getInstance().build(HomePageArouterConstants.PATH_AUDIO_PLAYER).withString(HomePageArouterConstants.KEY_ID, item.briefComposition.id).navigation()
}
executePendingBindings()
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = HomepageItemGroupCompositionBinding.inflate(LayoutInflater.from(parent.context))
binding.imageView.layoutParams = LinearLayout.LayoutParams(width, height.toInt())
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
getItem(position)?.let {
holder.bind(it)
}
}
}
My Itemdecoration
class GridSpacingItemDecoration(private val spanCount: Int,
private val verticalSpacing: Int,
private val topSpacing: Int
) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
val position = parent.getChildAdapterPosition(view)
if (position / spanCount == 0) {
outRect.top = topSpacing
}
if (position % spanCount == 1) {
outRect.left = 7.px
}
outRect.bottom = verticalSpacing
}
}
My diffUtil
class CompositionAbstractDiffCallback : DiffUtil.ItemCallback<CompositionAbstract>() {
override fun areItemsTheSame(oldItem: CompositionAbstract, newItem: CompositionAbstract): Boolean {
return oldItem.briefComposition.id == newItem.briefComposition.id
}
override fun areContentsTheSame(oldItem: CompositionAbstract, newItem: CompositionAbstract): Boolean {
return oldItem == newItem
}
}
Any ideas for this problem? Thanks for first!

Making an Intent on a selected GridLayout position

I am trying to create a method that will listen to the item that is clicked and if the category is clicked, it should open the activity selected. I have a Grid Layout setup, but I am not really sure how I would set an onClickListener or an onRecyclerViewItemClick for this purpose. I do have a pseudocode that I believe could be implemented, but would need guidance for this.
Here is my MainActivity.kt:
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
private lateinit var appBarConfiguration: AppBarConfiguration
private var mAuthListener : FirebaseAuth.AuthStateListener? = null
lateinit var myApi: IMyAPI
lateinit var txt_user_name:TextView
lateinit var txt_email_address:TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initView()
myApi = RetrofitClient.getInstance().create(IMyAPI::class.java)
Log.d("__MAIN__", "OnCreate")
}
private fun initView() {
recycler_view.layoutManager = GridLayoutManager(this, 2)
recycler_view.addItemDecoration(GridItemDecoration(10, 2))
val categoryListAdapter = CategoryListGridRecyclerAdapter()
recycler_view.adapter = categoryListAdapter
categoryListAdapter.setProductList(generateDummyData())
val navView: NavigationView = findViewById(R.id.nav_view)
navView.setNavigationItemSelectedListener(this)
navView.bringToFront()
}
private fun generateDummyData(): List<Category> {
val listOfCategory = mutableListOf<Category>()
var categoryModel = Category(1, "Products", R.drawable.kumo_logo, 1.90)
listOfCategory.add(categoryModel)
categoryModel = Category(2, "Food", R.drawable.kumo_logo, 1.90)
listOfCategory.add(categoryModel)
categoryModel = Category(3, "Technology", R.drawable.kumo_logo, 1.90)
listOfCategory.add(categoryModel)
categoryModel = Category(4, "News", R.drawable.kumo_logo, 1.90)
listOfCategory.add(categoryModel)
categoryModel = Category(5, "Economy", R.drawable.kumo_logo, 1.90)
listOfCategory.add(categoryModel)
categoryModel = Category(6, "Sports", R.drawable.kumo_logo, 1.90)
listOfCategory.add(categoryModel)
return listOfCategory
}
//Pseudocode:
/*override fun onRecyclerViewItemClick(category: Category, position: Int)
{
lateinit var catClick: Intent
if(category.id == 1)
{
catClick = Intent(this, ShowProducts::class.java)
}
startActivity(catClick) //start activity selected
}*/
override fun onNavigationItemSelected(item: MenuItem):Boolean {
when (item.itemId) {
R.id.nav_sign_out -> {
Log.d("Testing logout ", "user")
FirebaseAuth.getInstance().signOut()
startActivity(Intent(this#MainActivity, LoginActivity::class.java))
finish()
}
}
return true
}
}
GridItemDecoration.kt:
class GridItemDecoration(gridSpacingPx: Int, gridSize: Int) : RecyclerView.ItemDecoration() {
private var mSizeGridSpacingPx: Int = gridSpacingPx
private var mGridSize: Int = gridSize
private var mNeedLeftSpacing = false
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
val frameWidth = ((parent.width - mSizeGridSpacingPx.toFloat() * (mGridSize - 1)) / mGridSize).toInt()
val padding = parent.width / mGridSize - frameWidth
val itemPosition = (view.getLayoutParams() as RecyclerView.LayoutParams).viewAdapterPosition
if (itemPosition < mGridSize) {
outRect.top = 0
} else {
outRect.top = mSizeGridSpacingPx
}
if (itemPosition % mGridSize == 0) {
outRect.left = 0
outRect.right = padding
mNeedLeftSpacing = true
} else if ((itemPosition + 1) % mGridSize == 0) {
mNeedLeftSpacing = false
outRect.right = 0
outRect.left = padding
} else if (mNeedLeftSpacing) {
mNeedLeftSpacing = false
outRect.left = mSizeGridSpacingPx - padding
if ((itemPosition + 2) % mGridSize == 0) {
outRect.right = mSizeGridSpacingPx - padding
} else {
outRect.right = mSizeGridSpacingPx / 2
}
} else if ((itemPosition + 2) % mGridSize == 0) {
mNeedLeftSpacing = false
outRect.left = mSizeGridSpacingPx / 2
outRect.right = mSizeGridSpacingPx - padding
} else {
mNeedLeftSpacing = false
outRect.left = mSizeGridSpacingPx / 2
outRect.right = mSizeGridSpacingPx / 2
}
outRect.bottom = 0
}
}
CategoryListGridRecyclerAdapter.kt
class CategoryListGridRecyclerAdapter:RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var listOfCategory = listOf<Category>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return CategoryListViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.product_row, parent, false))
}
override fun getItemCount(): Int = listOfCategory.size
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
val productViewHolder = viewHolder as CategoryListViewHolder
productViewHolder.bindView(listOfCategory[position])
}
fun setProductList(listOfCategory: List<Category>) {
this.listOfCategory = listOfCategory
notifyDataSetChanged()
}
}
You can do something like this:
lateinit var mOnItemClickListener: (category: Category,pos: Int)-> Unit
fun setOnItemClickListener(callback: (category: Category,pos: Int)-> Unit){
mOnItemClickListener = callback
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return CategoryListViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.product_row, parent, false))
.listen {pos,_ ->
if(::mOnItemClickListener.isInitialized){
mOnItemClickListener(listOfCategory[pos],pos)
}
}
}
//I took this code from a post a while back, don't know the author
fun <T : RecyclerView.ViewHolder> T.listen(event: (position: Int, type: Int) -> Unit): T {
itemView.setOnClickListener {
event.invoke(adapterPosition, itemViewType)
}
return this
}
On MainActivity
categoryListAdapter.setOnItemClickListener { category, pos ->
...
}

Paging LoadRange Not getting called after data invalidate in done

I had a issue with PositionalDataSource, were loadRange not getting called once i invalidate the data source, this issue happens only if i add the item decoration for my recyclerview for sticky header
Without item decoration for recyclerview works fine
Here is my datasource
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<SomeData>) {
getData(0, params.requestedLoadSize)
.doOnSubscribe {
loading.set(true)
}
.map {
callback.onResult(it.data, 0)
}
.doOnComplete {
loading.set(false)
}
.subscribe()
.addTo(disposal)
}
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<SomeData>) {
getData(params.startPosition, params.loadSize)
.doOnSubscribe {
loading.set(true)
}
.map {
callback.onResult(it.data)
}
.doOnComplete {
loading.set(false)
}
.subscribe()
.addTo(disposal)
}
I invalidate the datasource from getData(int,int)
Here is my sticky header item decoration class
class StickyHeaderItemDecoration constructor(listener : StickyHeader) : RecyclerView.ItemDecoration() {
private val mListener: StickyHeader = listener
private var mStickyHeaderHeight = 0
override fun onDrawOver(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDrawOver(canvas, parent, state)
val topChild = parent.getChildAt(0) ?: return
val topChildPosition = parent.getChildAdapterPosition(topChild)
if (topChildPosition == RecyclerView.NO_POSITION) {
return
}
val headerPos = mListener.getHeaderPositionFor(topChildPosition)
val currentHeader = getHeaderViewForItem(headerPos, parent)
fixLayoutSize(parent, currentHeader)
val contactPoint = currentHeader.bottom
val childInContact = getChildInContact(parent, contactPoint, headerPos)
if (childInContact != null && mListener.isHeaderView(
parent.getChildAdapterPosition(
childInContact
)
)
) {
moveHeader(canvas, currentHeader, childInContact)
return
}
drawHeader(canvas, currentHeader)
}
private fun getHeaderViewForItem(headerPosition: Int, parent: RecyclerView): View {
val layoutResId = mListener.getHeaderLayoutIdFor(headerPosition)
val header =
LayoutInflater.from(parent.context).inflate(layoutResId, parent, false)
// mListener.bindHeaderData(header, headerPosition)
return header
}
private fun drawHeader(c: Canvas, header: View) {
c.save()
c.translate(0F, 0F)
header.draw(c)
c.restore()
}
private fun moveHeader(c: Canvas, currentHeader: View, nextHeader: View) {
c.save()
c.translate(0F, (nextHeader.top - currentHeader.height)*1.0F)
currentHeader.draw(c)
c.restore()
}
private fun getChildInContact(
parent: RecyclerView,
contactPoint: Int,
currentHeaderPos: Int
): View? {
var childInContact: View? = null
for (i in 0 until parent.childCount) {
var heightTolerance = 0
val child = parent.getChildAt(i)
//measure height tolerance with child if child is another header
if (currentHeaderPos != i) {
val isChildHeader =
mListener.isHeaderView(parent.getChildAdapterPosition(child))
if (isChildHeader) {
heightTolerance = mStickyHeaderHeight - child.height
}
}
//add heightTolerance if child top be in display area
var childBottomPosition: Int
childBottomPosition = if (child.top > 0) {
child.bottom + heightTolerance
} else {
child.bottom
}
if (childBottomPosition > contactPoint) {
if (child.top <= contactPoint) { // This child overlaps the contactPoint
childInContact = child
break
}
}
}
return childInContact
}
/**
* Properly measures and layouts the top sticky header.
* #param parent ViewGroup: RecyclerView in this case.
*/
private fun fixLayoutSize(
parent: ViewGroup,
view: View
) { // Specs for parent (RecyclerView)
val widthSpec =
View.MeasureSpec.makeMeasureSpec(parent.width, View.MeasureSpec.EXACTLY)
val heightSpec =
View.MeasureSpec.makeMeasureSpec(parent.height, View.MeasureSpec.UNSPECIFIED)
// Specs for children (headers)
val childWidthSpec = ViewGroup.getChildMeasureSpec(
widthSpec,
parent.paddingLeft + parent.paddingRight,
view.layoutParams.width
)
val childHeightSpec = ViewGroup.getChildMeasureSpec(
heightSpec,
parent.paddingTop + parent.paddingBottom,
view.layoutParams.height
)
view.measure(childWidthSpec, childHeightSpec)
view.layout(
0,
0,
view.measuredWidth,
view.measuredHeight.also { mStickyHeaderHeight = it }
)
}
}
Can anyone guess, what may be the issue ?

Categories

Resources