ฉันมี 2 ScrollViews ในเลย์เอาต์ Android ของฉัน ฉันจะซิงโครไนซ์ตำแหน่งการเลื่อนได้อย่างไร?
ฉันมี 2 ScrollViews ในเลย์เอาต์ Android ของฉัน ฉันจะซิงโครไนซ์ตำแหน่งการเลื่อนได้อย่างไร?
คำตอบ:
มีวิธีการใน 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 hook
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 เวอร์ชันอนาคตเนื่องจากเรากำลังลบล้างวิธีการป้องกัน
การปรับปรุงวิธีแก้ปัญหาของ Andy: ในโค้ดของเขาเขาใช้ scrollTo ปัญหาคือถ้าคุณเหวี่ยง scrollview หนึ่งไปในทิศทางเดียวแล้วเหวี่ยงอีกอันไปในทิศทางอื่นคุณจะสังเกตเห็นว่าอันแรกไม่ได้หยุดการพุ่งก่อนหน้าของเขา การเคลื่อนไหว.
นี่เป็นเพราะการที่ 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;
}
}
ด้วย interceptScroll บูลีนแบบคงที่เริ่มต้นเป็นจริง (สิ่งนี้ช่วยหลีกเลี่ยงการวนซ้ำที่ไม่มีที่สิ้นสุดบน ScrollChanged)
onOverScrolled เป็นฟังก์ชันเดียวที่ฉันพบซึ่งสามารถใช้เพื่อหยุด 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 เพื่อจัดการกับการเลื่อน
นั่นทำให้สิ่งต่างๆง่ายขึ้น