Skip to content

Commit

Permalink
Add attach() and detach() methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
iammert committed Mar 3, 2020
1 parent 5ef07a6 commit f52091d
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,14 @@ class MainActivity : AppCompatActivity() {
* SETUP ATTACHER
*/
val indexOffsets = getCategoryIndexOffsets(categories)
TabScrollAttacher(tabLayout, recyclerView, indexOffsets) {
val attacher = TabScrollAttacher(tabLayout, recyclerView, indexOffsets) {
scrollSmoothly()
}

attacher.attach()

//attacher.detach()

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,67 +13,78 @@ class TabScrollAttacher(
configuration: Configuration.() -> Unit = {}
) {

private val layoutManager: LinearLayoutManager
private lateinit var layoutManager: LinearLayoutManager

private lateinit var config: Configuration

private var attacherState = AttacherState.IDLE

private val config: Configuration
private var isAttached = false

private var scrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)

if (attacherState == AttacherState.TAB_SELECTED) {
return
}

val isScrolling = dx != 0 || dy != 0
if (attacherState == AttacherState.IDLE && isScrolling) {
attacherState = AttacherState.RECYCLERVIEW_SCROLLING
}

val calculatedRecyclerViewItemPosition = when {
layoutManager.findLastVisibleItemPosition() == layoutManager.itemCount - 1 -> layoutManager.findLastVisibleItemPosition()
layoutManager.findFirstVisibleItemPosition() == 0 -> layoutManager.findFirstVisibleItemPosition()
else -> findMidVisibleRecyclerItemPosition()
}

val tabIndex = getTabIndex(calculatedRecyclerViewItemPosition)
if (tabIndex != tabLayout.selectedTabPosition) {
tabLayout.getTabAt(tabIndex)?.select()
}
}

override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
attacherState = AttacherState.IDLE
}
}
}

private var tabSelectedListener = object : SimpleTabSelectedListener() {
override fun onTabSelected(p0: TabLayout.Tab?) {
super.onTabSelected(p0)
if (attacherState != AttacherState.RECYCLERVIEW_SCROLLING) {
attacherState = AttacherState.TAB_SELECTED
val recyclerViewPosition = tabStartIndexOffsets[tabLayout.selectedTabPosition]
recyclerView.scrollToPosition(recyclerViewPosition, config.scrollMethod)
}
}
}

init {
require(recyclerView.layoutManager is LinearLayoutManager) { "Only LinearLayoutManager is supported." }
layoutManager = recyclerView.layoutManager as LinearLayoutManager
config = Configuration().apply(configuration)
observeRecyclerViewScroll()
observeTabLayoutSelection()
}

private fun observeRecyclerViewScroll() {
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)

if (attacherState == AttacherState.TAB_SELECTED) {
return
}

val isScrolling = dx != 0 || dy != 0
if (attacherState == AttacherState.IDLE && isScrolling) {
attacherState = AttacherState.RECYCLERVIEW_SCROLLING
}

val calculatedRecyclerViewItemPosition = when {
layoutManager.findLastVisibleItemPosition() == layoutManager.itemCount - 1 -> layoutManager.findLastVisibleItemPosition()
layoutManager.findFirstVisibleItemPosition() == 0 -> layoutManager.findFirstVisibleItemPosition()
else -> findMidVisibleRecyclerItemPosition()
}

val tabIndex = getTabIndex(calculatedRecyclerViewItemPosition)
if (tabIndex != tabLayout.selectedTabPosition) {
tabLayout.getTabAt(tabIndex)?.select()
}
}

override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
attacherState = AttacherState.IDLE
}
}
})
fun detach() {
if (isAttached) {
recyclerView.removeOnScrollListener(scrollListener)
tabLayout.removeOnTabSelectedListener(tabSelectedListener)
isAttached = false
}
}

@SuppressLint("ClickableViewAccessibility")
private fun observeTabLayoutSelection() {
tabLayout.addOnTabSelectedListener(object : SimpleTabSelectedListener() {
override fun onTabSelected(p0: TabLayout.Tab?) {
super.onTabSelected(p0)
if (attacherState != AttacherState.RECYCLERVIEW_SCROLLING) {
attacherState = AttacherState.TAB_SELECTED
val recyclerViewPosition = tabStartIndexOffsets[tabLayout.selectedTabPosition]
recyclerView.scrollToPosition(recyclerViewPosition, config.scrollMethod)
}
}
})
fun attach() {
if (isAttached.not()) {
recyclerView.addOnScrollListener(scrollListener)
tabLayout.addOnTabSelectedListener(tabSelectedListener)
isAttached = true
}
}

private fun findMidVisibleRecyclerItemPosition(): Int {
Expand Down

0 comments on commit f52091d

Please sign in to comment.