Lorsque j'ai utilisé smoothScrollToPosition avec RecyclerView, il ne s'est arrêté qu'à mi-chemin, c'est donc un mémo lorsque je l'ai vérifié.
Utiliser LinearLayoutManager La direction du défilement est verticale
Je veux m'assurer que la position d'arrêt du défilement est en haut
Selon le sens du défilement, il peut monter ou descendre ...
smoothScrollToPosition L'implémentation dans le LinearLayoutManager couramment utilisé ressemble à ceci.
LinearLayoutManager.java
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext());
//Définir la cible de défilement Position dans le défilement
linearSmoothScroller.setTargetPosition(position);
//Faire défiler à l'aide de la molette
startSmoothScroll(linearSmoothScroller);
}
LinearSmoothScroller
hérite de SmoothScroller
.
SmoothScroller
SmoothScroller
est une classe abstraite, et il y a une méthode appelée ʻonTargetFound` dedans.
SmoothScroller.java
public abstract static class SmoothScroller {
...(Abréviation)
/**
* Called when the target position is laid out. This is the last callback SmoothScroller
* will receive and it should update the provided {@link Action} to define the scroll
* details towards the target view.
* @param targetView The view element which render the target position.
* @param state Transient state of RecyclerView
* @param action Action instance that you should update to define final scroll action
* towards the targetView
*/
protected abstract void onTargetFound(View targetView, State state, Action action);
...(Abréviation)
}
SmoothScroller
a plusieurs rappels, mais ce rappel est le dernier à être notifié et sera appelé lorsque la vue cible entrera dans la mise en page. Quant à ce qu'il faut faire ici, il y a un commentaire à l'effet qui met à jour l'ʻactionpassée comme argument et affine la position. Maintenant, vérifions quel type d'implémentation est spécifiquement dans
LinearSmoothScroller`.
LinearSmoothScroller
LinearSmoothScroller.java
@Override
protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
final int dx = calculateDxToMakeVisible(targetView, getHorizontalSnapPreference());
final int dy = calculateDyToMakeVisible(targetView, getVerticalSnapPreference());
final int distance = (int) Math.sqrt(dx * dx + dy * dy);
final int time = calculateTimeForDeceleration(distance);
if (time > 0) {
action.update(-dx, -dy, time, mDecelerateInterpolator);
}
}
Il calcule la quantité requise de défilement dans les directions x et y et exécute ʻaction.update. Le contenu de l'implémentation de
CalculateDx / DyToMakeVisible` à calculer est trouble, donc si vous ne regardez que les commentaires, cela ressemble à ceci.
LinearSmoothScroller.java
/**
* Calculates the vertical scroll amount necessary to make the given view fully visible
* inside the RecyclerView.
*
* @param view The view which we want to make fully visible
* @param snapPreference The edge which the view should snap to when entering the visible
* area. One of {@link #SNAP_TO_START}, {@link #SNAP_TO_END} or
* {@link #SNAP_TO_ANY}.
* @return The vertical scroll amount necessary to make the view visible with the given
* snap preference.
*/
public int calculateDyToMakeVisible(View view, int snapPreference) {
Il dit qu'il calculera la quantité de défilement requise avant que la vue entière du premier argument puisse être vue. Le deuxième argument indique la position où vous voulez que la vue soit finalement affichée, et choisissez parmi les trois suivants.
En regardant le getVerticalSnapPreference
qui détermine le deuxième argument, cela ressemble à ceci.
LinearSmoothScroller.java
protected int getVerticalSnapPreference() {
return mTargetVector == null || mTargetVector.y == 0 ? SNAP_TO_ANY :
mTargetVector.y > 0 ? SNAP_TO_END : SNAP_TO_START;
}
Il bascule entre SNAP_TO_START
et SNAP_TO_END
selon le sens du défilement. En d'autres termes, à cette fin, cela peut être réalisé en modifiant (écrasant) cette snapPreference.
La description est devenue longue, mais j'ai trouvé que le code qui devrait réellement être implémenté est suffisant pour étendre un peu le LinearSmoothScroller
par défaut.
CustomLayoutManager.kt
class CustomLayoutManager(context: Context) : LinearLayoutManager(context) {
override fun smoothScrollToPosition(recyclerView: RecyclerView, state: RecyclerView.State?, position: Int) {
val linearSmoothScroller = object : LinearSmoothScroller(recyclerView.context) {
override fun getVerticalSnapPreference(): Int = if (reverseLayout) SNAP_TO_END else SNAP_TO_START
}
linearSmoothScroller.targetPosition = position
startSmoothScroll(linearSmoothScroller)
}
}
À propos, dans cet exemple, seul reverseLayout
est pris en compte, mais je pense qu'il est général de l'implémenter en tenant également compte du sens de défilement (vertical / horizontal).
Recommended Posts