Respuestas:
Hay un método en ScrollView ...
protected void onScrollChanged(int x, int y, int oldx, int oldy)
Desafortunadamente, Google nunca pensó que necesitaríamos acceder a él, por lo que lo protegieron y no agregaron un gancho "setOnScrollChangedListener". Así que tendremos que hacerlo por nosotros mismos.
Primero necesitamos una interfaz.
package com.test;
public interface ScrollViewListener {
void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy);
}
Luego, necesitamos anular la clase ScrollView para proporcionar el gancho 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);
}
}
}
Y deberíamos especificar esta nueva clase ObservableScrollView en el diseño, en lugar de las etiquetas ScrollView existentes.
<com.test.ObservableScrollView
android:id="@+id/scrollview1"
... >
...
</com.test.ObservableScrollView>
Finalmente, lo juntamos todo en la clase 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);
}
}
}
El código scrollTo () se encarga de cualquier condición de bucle por nosotros, así que no tenemos que preocuparnos por eso. La única advertencia es que no se garantiza que esta solución funcione en versiones futuras de Android, porque estamos anulando un método protegido.
Una mejora a la solución de Andy: en su código, usa scrollTo, el problema es que si arrojas una vista de desplazamiento en una dirección y luego arrojas otra en otra dirección, notarás que la primera no detiene su aventura anterior. movimiento.
Esto se debe al hecho de que scrollView usa computeScroll () para hacer sus gestos de lanzamiento, y entra en conflicto con scrollTo.
Para evitar esto, simplemente programe onScrollChanged de esta manera:
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;
}
}
con interceptScroll un booleano estático inicializado en verdadero. (esto ayuda a evitar bucles infinitos en ScrollChanged)
onOverScrolled es la única función que encontré que podría usarse para detener el desplazamiento de scrollView (¡pero puede haber otras que me haya perdido!)
Para acceder a esta función (que está protegida), debe agregarla a su ObservableScrollViewer
public void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
}
¿Por qué no simplemente implementa OnTouchListener
en su actividad? Luego anule el método onTouch, luego obtenga la posición de desplazamiento del primero ScrollViewOne.getScrollY()
y actualiceScrollViewTwo.scrollTo(0, ScrollViewOne.getScrollY());
Solo otra idea ... :)
En el paquete de Android support-v4, Android proporciona una nueva clase llamada NestedScrollView
.
podemos reemplazar el <ScrollView>
nodo con <android.support.v4.widget.NestedScrollView>
en diseño xml e implementarlo NestedScrollView.OnScrollChangeListener
en Java para manejar el desplazamiento.
Eso facilita las cosas.