Skip to content

Commit

Permalink
Merge pull request #121 from AlanCheen/feature/sticky-header
Browse files Browse the repository at this point in the history
Feature/sticky header
  • Loading branch information
AlanCheen authored Oct 18, 2022
2 parents fb01b55 + 11d4044 commit 9ae2d1d
Show file tree
Hide file tree
Showing 16 changed files with 1,676 additions and 43 deletions.
13 changes: 11 additions & 2 deletions app/src/main/java/me/yifeiyuan/flapdev/ConfigMenuView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package me.yifeiyuan.flapdev

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import android.widget.SeekBar
import androidx.recyclerview.widget.RecyclerView
Expand Down Expand Up @@ -33,8 +34,8 @@ class ConfigMenuView : FrameLayout {
//1 Grid
//2 Staggered
//3 IndexedStaggered
binding.layoutManagerGroup.setOnCheckedChangeListener { group, checkedId ->
when (checkedId) {
val layoutManagerClickListener = OnClickListener { v ->
when (v.id) {
R.id.linear -> {
callback?.onLayoutManagerChanged(0)
}
Expand All @@ -47,8 +48,16 @@ class ConfigMenuView : FrameLayout {
R.id.indexedStaggered -> {
callback?.onLayoutManagerChanged(3)
}
R.id.stickyHeader->{
callback?.onLayoutManagerChanged(4)
}
}
}
binding.linear.setOnClickListener(layoutManagerClickListener)
binding.grid.setOnClickListener(layoutManagerClickListener)
binding.staggered.setOnClickListener(layoutManagerClickListener)
binding.indexedStaggered.setOnClickListener(layoutManagerClickListener)
binding.stickyHeader.setOnClickListener(layoutManagerClickListener)

binding.clearAll.setOnClickListener {
callback?.onClearAllData()
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/java/me/yifeiyuan/flapdev/FlapApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package me.yifeiyuan.flapdev
import android.app.Application
import android.util.Log
import android.widget.Toast
import androidx.core.view.get
import androidx.multidex.MultiDexApplication
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import me.yifeiyuan.flap.Flap
import me.yifeiyuan.flap.apt.delegates.*
import me.yifeiyuan.flap.dsl.adapterHook
Expand All @@ -17,6 +20,12 @@ import me.yifeiyuan.flapdev.components.*
class FlapApplication : MultiDexApplication() {

companion object {

val ViewPager2.recyclerView: RecyclerView
get() {
return this[0] as RecyclerView
}

var application: Application? = null
set(value) {
field = value
Expand Down
72 changes: 72 additions & 0 deletions app/src/main/java/me/yifeiyuan/flapdev/SingleScrollDirection.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package me.yifeiyuan.flapdev

import android.view.MotionEvent
import androidx.recyclerview.widget.RecyclerView
import java.lang.Math.abs

/**
* Created by 程序亦非猿 on 2022/10/18.
*/

fun RecyclerView.enforceSingleScrollDirection() {
val enforcer = SingleScrollDirectionEnforcer()
addOnItemTouchListener(enforcer)
addOnScrollListener(enforcer)
}

private class SingleScrollDirectionEnforcer : RecyclerView.OnScrollListener(), RecyclerView.OnItemTouchListener {

private var scrollState = RecyclerView.SCROLL_STATE_IDLE
private var scrollPointerId = -1
private var initialTouchX = 0
private var initialTouchY = 0
private var dx = 0
private var dy = 0

override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
when (e.actionMasked) {
MotionEvent.ACTION_DOWN -> {
scrollPointerId = e.getPointerId(0)
initialTouchX = (e.x + 0.5f).toInt()
initialTouchY = (e.y + 0.5f).toInt()
}
MotionEvent.ACTION_POINTER_DOWN -> {
val actionIndex = e.actionIndex
scrollPointerId = e.getPointerId(actionIndex)
initialTouchX = (e.getX(actionIndex) + 0.5f).toInt()
initialTouchY = (e.getY(actionIndex) + 0.5f).toInt()
}
MotionEvent.ACTION_MOVE -> {
val index = e.findPointerIndex(scrollPointerId)
if (index >= 0 && scrollState != RecyclerView.SCROLL_STATE_DRAGGING) {
val x = (e.getX(index) + 0.5f).toInt()
val y = (e.getY(index) + 0.5f).toInt()
dx = x - initialTouchX
dy = y - initialTouchY
}
}
}
return false
}

override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}

override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}

override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
val oldState = scrollState
scrollState = newState
if (oldState == RecyclerView.SCROLL_STATE_IDLE && newState == RecyclerView.SCROLL_STATE_DRAGGING) {
recyclerView.layoutManager?.let { layoutManager ->
val canScrollHorizontally = layoutManager.canScrollHorizontally()
val canScrollVertically = layoutManager.canScrollVertically()
if (canScrollHorizontally != canScrollVertically) {
if ((canScrollHorizontally && abs(dy) > abs(dx))
|| (canScrollVertically && abs(dx) > abs(dy))) {
recyclerView.stopScroll()
}
}
}
}
}
}
28 changes: 28 additions & 0 deletions app/src/main/java/me/yifeiyuan/flapdev/StickyHeaders.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package me.yifeiyuan.flapdev;

import android.view.View;

/**
* Created by 程序亦非猿 on 2022/10/17.
*/
interface StickyHeaders {

boolean isStickyHeader(int position);

interface ViewSetup {
/**
* Adjusts any necessary properties of the {@code holder} that is being used as a sticky header.
*
* {@link #teardownStickyHeaderView(View)} will be called sometime after this method
* and before any other calls to this method go through.
*/
void setupStickyHeaderView(View stickyHeader);

/**
* Reverts any properties changed in {@link #setupStickyHeaderView(View)}.
*
* Called after {@link #setupStickyHeaderView(View)}.
*/
void teardownStickyHeaderView(View stickyHeader);
}
}
Loading

0 comments on commit 9ae2d1d

Please sign in to comment.