Saya memiliki 2 ScrollView di layout android saya. Bagaimana cara menyinkronkan posisi gulir mereka?
Jawaban:
Ada metode di ScrollView ...
protected void onScrollChanged(int x, int y, int oldx, int oldy)
Sayangnya Google tidak pernah berpikir bahwa kami perlu mengaksesnya, itulah sebabnya mereka membuatnya dilindungi dan tidak menambahkan pengait "setOnScrollChangedListener". Jadi kita harus melakukannya sendiri.
Pertama kita membutuhkan antarmuka.
package com.test;
public interface ScrollViewListener {
void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy);
}
Kemudian kita perlu mengganti kelas ScrollView, untuk menyediakan pengait 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);
}
}
}
Dan kita harus menentukan kelas ObservableScrollView baru ini di layout, bukan di tag ScrollView yang ada.
<com.test.ObservableScrollView
android:id="@+id/scrollview1"
... >
...
</com.test.ObservableScrollView>
Terakhir, kami menggabungkan semuanya di kelas 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);
}
}
}
Kode scrollTo () menangani kondisi loop apa pun untuk kita, jadi kita tidak perlu khawatir tentang itu. Satu-satunya peringatan adalah bahwa solusi ini tidak dijamin akan berfungsi di versi Android mendatang, karena kami mengganti metode yang dilindungi.
Perbaikan pada solusi Andy: Dalam kodenya, dia menggunakan scrollTo, masalahnya adalah, jika Anda melemparkan satu tampilan gulir ke satu arah dan kemudian melemparkan yang lain ke arah lain, Anda akan melihat bahwa yang pertama tidak menghentikan lemparan sebelumnya. gerakan.
Hal ini disebabkan oleh fakta bahwa scrollView menggunakan computeScroll () untuk melakukan gerakan melempar, dan bentrok dengan scrollTo.
Untuk mencegahnya, cukup program onScrollChanged dengan cara ini:
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;
}
}
dengan interceptScroll boolean statis yang diinisialisasi ke true. (ini membantu menghindari loop tak terbatas di ScrollChanged)
onOverScrolled adalah satu-satunya fungsi yang saya temukan yang dapat digunakan untuk menghentikan scrollView agar tidak terlempar (tetapi mungkin ada fungsi lain yang saya lewatkan!)
Untuk mengakses fungsi ini (yang dilindungi) Anda harus menambahkan ini ke ObservableScrollViewer Anda
public void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
}
Mengapa tidak menerapkan OnTouchListener
dalam aktivitas Anda. Kemudian timpa metode onTouch, lalu dapatkan posisi scroll pertama ScrollViewOne.getScrollY()
dan perbaruiScrollViewTwo.scrollTo(0, ScrollViewOne.getScrollY());
Hanya ide lain ... :)
Dalam paket Android support-v4, Android menyediakan kelas baru bernama NestedScrollView
.
kita bisa mengganti <ScrollView>
node dengan <android.support.v4.widget.NestedScrollView>
dalam layout xml, dan mengimplementasikannya NestedScrollView.OnScrollChangeListener
di Java untuk menangani pengguliran.
Itu membuat segalanya lebih mudah.