Відповіді:
У ScrollView є метод ...
protected void onScrollChanged(int x, int y, int oldx, int oldy)
На жаль, Google ніколи не думав, що нам потрібно буде отримати до нього доступ, саме тому вони зробили його захищеним і не додали гачок "setOnScrollChangedListener". Тож нам доведеться зробити це для себе.
Спочатку нам потрібен інтерфейс.
package com.test;
public interface ScrollViewListener {
void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy);
}
Потім нам потрібно замінити клас ScrollView, щоб забезпечити гачок 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);
}
}
}
І ми повинні вказати цей новий клас ObservableScrollView у макеті, замість існуючих тегів ScrollView.
<com.test.ObservableScrollView
android:id="@+id/scrollview1"
... >
...
</com.test.ObservableScrollView>
Нарешті, ми поклали все це разом у клас 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);
}
}
}
Код scrollTo () опікується будь-якими умовами циклу для нас, тому нам не потрібно турбуватися про це. Єдине застереження полягає в тому, що це рішення не гарантується для роботи в майбутніх версіях Android, оскільки ми замінюємо захищений метод.
Поліпшення рішення Енді: у своєму коді він використовує scrollTo, проблема полягає в тому, що якщо ви перекинете один прокручувальний перегляд в одному напрямку, а потім перекинете інший в іншому, ви помітите, що перший не зупиняє його попереднє перекидання рух.
Це пов'язано з тим, що scrollView використовує computeScroll (), щоб робити свої махінаційні жести, і він вступає в конфлікт із scrollTo.
Щоб запобігти цьому, просто запрограмуйте onScrollChanged таким чином:
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 статичний логічний код, ініціалізований до true. (це допомагає уникнути нескінченних циклів на ScrollChanged)
onOverScroll - це єдина функція, яку я знайшов, яка може бути використана для зупинки прокрутки scrollView (але можуть бути й інші, яких я пропустив!)
Для того, щоб отримати доступ до цієї функції (яка захищена), ви повинні додати її до свого ObservableScrollViewer
public void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
}
Чому б не просто реалізувати OnTouchListener
у своїй діяльності. Потім перевизначте метод onTouch, отримайте позицію прокрутки першого ScrollViewOne.getScrollY()
та оновітьScrollViewTwo.scrollTo(0, ScrollViewOne.getScrollY());
Ще одна ідея ... :)
У пакеті підтримки Android-v4 Android надає новий клас із назвою NestedScrollView
.
ми можемо замінити <ScrollView>
вузол <android.support.v4.widget.NestedScrollView>
на макет xml і реалізуємо його NestedScrollView.OnScrollChangeListener
на Java для обробки прокрутки.
Це робить справи простішими.