Respostas:
Existe um método em ScrollView ...
protected void onScrollChanged(int x, int y, int oldx, int oldy)
Infelizmente, o Google nunca pensou que precisaríamos acessá-lo, e é por isso que eles o protegeram e não adicionaram um gancho "setOnScrollChangedListener". Portanto, teremos que fazer isso por nós mesmos.
Primeiro, precisamos de uma interface.
package com.test;
public interface ScrollViewListener {
void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy);
}
Em seguida, precisamos substituir a classe ScrollView, para fornecer o 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);
}
}
}
E devemos especificar esta nova classe ObservableScrollView no layout, em vez das tags ScrollView existentes.
<com.test.ObservableScrollView
android:id="@+id/scrollview1"
... >
...
</com.test.ObservableScrollView>
Finalmente, colocamos tudo junto na 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);
}
}
}
O código scrollTo () cuida de quaisquer condições de loop para nós, então não precisamos nos preocupar com isso. A única ressalva é que essa solução não tem garantia de funcionar em versões futuras do Android, porque estamos substituindo um método protegido.
Uma melhoria na solução de Andy: em seu código, ele usa scrollTo, o problema é que, se você lançar um scrollview em uma direção e, em seguida, outro em outra direção, você notará que o primeiro não interrompe o lançamento anterior movimento.
Isso se deve ao fato de que scrollView usa computeScroll () para fazer seus gestos de arremesso e entra em conflito com scrollTo.
Para evitar isso, basta programar onScrollChanged desta forma:
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;
}
}
com interceptScroll, um booleano estático inicializado como verdadeiro. (isso ajuda a evitar loops infinitos em ScrollChanged)
onOverScrolled é a única função que descobri que poderia ser usada para impedir o lançamento de scrollView (mas pode haver outras que eu perdi!)
Para acessar esta função (que é protegida), você deve adicioná-la ao seu ObservableScrollViewer
public void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
}
Porque não apenas implementa OnTouchListener
na sua atividade. Em seguida, substitua o método onTouch, obtenha a posição de rolagem do primeiro ScrollViewOne.getScrollY()
e atualizeScrollViewTwo.scrollTo(0, ScrollViewOne.getScrollY());
Só mais uma ideia ... :)
No pacote Android support-v4, o Android fornece uma nova classe chamada NestedScrollView
.
podemos substituir o <ScrollView>
nó por <android.support.v4.widget.NestedScrollView>
no layout xml e implementá-lo NestedScrollView.OnScrollChangeListener
em Java para lidar com a rolagem.
Isso torna as coisas mais fáceis.