J'ai 2 ScrollViews dans mon layout android. Comment puis-je synchroniser leurs positions de défilement?
Réponses
Trop de publicités?Il existe une méthode dans ScrollView...
protected void onScrollChanged(int x, int y, int oldx, int oldy)
Malheureusement, Google n'a jamais pensé que nous aurions besoin d'y accéder, c'est pourquoi ils l'ont rendu protégé et n'ont pas ajouté de crochet "setOnScrollChangedListener". Nous devrons donc le faire nous-mêmes.
Tout d'abord, nous avons besoin d'une interface.
package com.test;
public interface ScrollViewListener {
void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy);
}
Ensuite, nous devons remplacer la classe ScrollView pour fournir le crochet ScrollViewListener.
package com.test;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;
public class ObservableScrollView extends ScrollView {
private ScrollViewListener scrollViewListener = null;
public ObservableScrollView(Context context) {
super(context);
}
public ObservableScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ObservableScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setScrollViewListener(ScrollViewListener scrollViewListener) {
this.scrollViewListener = scrollViewListener;
}
@Override
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
super.onScrollChanged(x, y, oldx, oldy);
if(scrollViewListener != null) {
scrollViewListener.onScrollChanged(this, x, y, oldx, oldy);
}
}
}
Et nous devrions spécifier cette nouvelle classe ObservableScrollView dans la mise en page, au lieu des balises ScrollView existantes.
...
Enfin, nous regroupons tout dans la classe Layout.
package com.test;
import android.app.Activity;
import android.os.Bundle;
public class Q3948934 extends Activity implements ScrollViewListener {
private ObservableScrollView scrollView1 = null;
private ObservableScrollView scrollView2 = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.q3948934);
scrollView1 = (ObservableScrollView) findViewById(R.id.scrollview1);
scrollView1.setScrollViewListener(this);
scrollView2 = (ObservableScrollView) findViewById(R.id.scrollview2);
scrollView2.setScrollViewListener(this);
}
public void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy) {
if(scrollView == scrollView1) {
scrollView2.scrollTo(x, y);
} else if(scrollView == scrollView2) {
scrollView1.scrollTo(x, y);
}
}
}
Le code scrollTo() prend en charge toutes les conditions de boucle pour nous, donc nous n'avons pas à nous inquiéter de cela. La seule réserve est que cette solution n'est pas garantie de fonctionner dans les futures versions d'Android, car nous remplaçons une méthode protégée.
Une amélioration à la solution d'Andy : Dans son code, il utilise scrollTo, le problème est que si vous faites glisser un scrollview dans une direction et ensuite faites glisser un autre dans une autre direction, vous remarquerez que le premier ne s'arrête pas dans son mouvement précédent.
Cela est dû au fait que le scrollView utilise computeScroll() pour effectuer ses gestes de lancement, et cela entre en conflit avec scrollTo.
Pour éviter cela, il suffit de programmer onScrollChanged de cette manière :
public void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy) {
if(interceptScroll){
interceptScroll=false;
if(scrollView == scrollView1) {
scrollView2.onOverScrolled(x,y,true,true);
} else if(scrollView == scrollView2) {
scrollView1.onOverScrolled(x,y,true,true);
}
interceptScroll=true;
}
}
avec interceptScroll un boolean statique initialisé à true. (cela aide à éviter les boucles infinies sur ScrollChanged)
onOverScrolled est la seule fonction que j'ai trouvée qui pouvait être utilisée pour arrêter le scrollView de lancer (mais il pourrait y en avoir d'autres que j'ai manquées !)
Pour accéder à cette fonction (qui est protégée), vous devez ajouter ceci à votre ObservableScrollViewer
public void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
}
Dans le package de support Android support-v4, Android fournit une nouvelle classe nommée NestedScrollView
.
Nous pouvons remplacer le noeud par dans le fichier de mise en page XML, et implémenter son NestedScrollView.OnScrollChangeListener
en Java pour gérer le défilement.
Cela rend les choses plus faciles.