Risposte:
C'è un metodo in ScrollView ...
protected void onScrollChanged(int x, int y, int oldx, int oldy)
Sfortunatamente Google non ha mai pensato che avremmo avuto bisogno di accedervi, motivo per cui lo hanno protetto e non hanno aggiunto un hook "setOnScrollChangedListener". Quindi dovremo farlo per noi stessi.
Per prima cosa abbiamo bisogno di un'interfaccia.
package com.test;
public interface ScrollViewListener {
void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy);
}
Quindi dobbiamo sovrascrivere la classe ScrollView, per fornire l'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);
}
}
}
E dovremmo specificare questa nuova classe ObservableScrollView nel layout, invece dei tag ScrollView esistenti.
<com.test.ObservableScrollView
android:id="@+id/scrollview1"
... >
...
</com.test.ObservableScrollView>
Infine, mettiamo tutto insieme nella 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);
}
}
}
Il codice scrollTo () si prende cura di qualsiasi condizione del ciclo per noi, quindi non dobbiamo preoccuparci di questo. L'unico avvertimento è che questa soluzione non è garantita per funzionare nelle versioni future di Android, perché stiamo sovrascrivendo un metodo protetto.
Un miglioramento alla soluzione di Andy: nel suo codice, usa scrollTo, il problema è che se lanci uno scrollview in una direzione e poi ne lanci un altro in un'altra direzione, noterai che il primo non interrompe la sua precedente avventura movimento.
Ciò è dovuto al fatto che scrollView utilizza computeScroll () per eseguire i suoi gesti di lancio, ed entra in conflitto con scrollTo.
Per evitare ciò, basta programmare onScrollChanged in questo modo:
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;
}
}
with interceptScroll un booleano statico inizializzato su true. (questo aiuta a evitare loop infiniti su ScrollChanged)
onOverScrolled è l'unica funzione che ho trovato che potrebbe essere utilizzata per fermare il lancio di scrollView (ma potrebbero essercene altre che mi sono perso!)
Per accedere a questa funzione (che è protetta) devi aggiungerla al tuo ObservableScrollViewer
public void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
}
Perché non implementare solo OnTouchListener
nella tua attività. Quindi sovrascrivi il metodo onTouch, quindi ottieni la posizione di scorrimento del primo ScrollViewOne.getScrollY()
e aggiornaScrollViewTwo.scrollTo(0, ScrollViewOne.getScrollY());
Solo un'altra idea ... :)
Nel pacchetto Android support-v4, Android fornisce una nuova classe denominata NestedScrollView
.
possiamo sostituire il <ScrollView>
nodo con <android.support.v4.widget.NestedScrollView>
nel layout xml e implementarlo NestedScrollView.OnScrollChangeListener
in Java per gestire lo scorrimento.
Questo rende le cose più facili.