내 안드로이드 레이아웃에 2 개의 ScrollView가 있습니다. 스크롤 위치를 어떻게 동기화 할 수 있습니까?
답변
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);
}
그런 다음 ScrollViewListener 후크를 제공하기 위해 ScrollView 클래스를 재정의해야합니다.
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);
}
}
}
그리고 레이아웃에 기존 ScrollView 태그 대신이 새로운 ObservableScrollView 클래스를 지정해야합니다.
<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가 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을 사용하면 정적 부울이 true로 초기화됩니다. (이것은 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 support-v4 패키지에서 Android는 NestedScrollView
.
레이아웃 xml에서 <ScrollView>
노드를
교체 하고 스크롤을 처리하기 위해 Java로 <android.support.v4.widget.NestedScrollView>
구현할 NestedScrollView.OnScrollChangeListener
수 있습니다.
그것은 일을 더 쉽게 만듭니다.