Réponses:
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 protégé et n'ont pas ajouté de hook "setOnScrollChangedListener". Nous devrons donc le faire pour nous-mêmes.
Nous avons d'abord 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 hook 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 devons spécifier cette nouvelle classe ObservableScrollView dans la mise en page, au lieu des balises ScrollView existantes.
<com.test.ObservableScrollView
android:id="@+id/scrollview1"
... >
...
</com.test.ObservableScrollView>
Enfin, nous mettons tout cela ensemble 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 () s'occupe de toutes les conditions de boucle pour nous, nous n'avons donc pas à nous en soucier. La seule mise en garde 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 de la solution d'Andy: dans son code, il utilise scrollTo, le problème est que si vous lancez une vue de défilement dans une direction puis en lancez une autre dans une autre direction, vous remarquerez que la première n'arrête pas sa précédente aventure. mouvement.
Cela est dû au fait que scrollView utilise computeScroll () pour faire ses mouvements de projection et qu'il entre en conflit avec scrollTo.
Afin d'éviter cela, programmez simplement onScrollChanged de cette façon:
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 booléen statique initialisé à true. (cela permet d'éviter les boucles infinies sur ScrollChanged)
onOverScrolled est la seule fonction que j'ai trouvée qui pourrait être utilisée pour empêcher le scrollView de flinguer (mais il y en a peut-être d'autres que j'ai manquées!)
Pour accéder à cette fonction (qui est protégée), vous devez l'ajouter à votre ObservableScrollViewer
public void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
}
Pourquoi pas simplement des implémentations OnTouchListener
dans votre activité. Remplacez ensuite la méthode onTouch, puis récupérez la position de défilement du premier ScrollViewOne.getScrollY()
et mettez à jourScrollViewTwo.scrollTo(0, ScrollViewOne.getScrollY());
Juste une autre idée ... :)
Dans le package Android support-v4, Android fournit une nouvelle classe nommée NestedScrollView
.
nous pouvons remplacer le <ScrollView>
nœud par <android.support.v4.widget.NestedScrollView>
dans la mise en page xml, et implémenter son NestedScrollView.OnScrollChangeListener
en Java pour gérer le défilement.
Cela facilite les choses.