내가 사용하고 HorizontalScrollView
레이아웃과 나는 스크롤의 시작과 끝 지점에 도달 한 사용자를 식별해야합니다.
들어 ListView
나는 a를 시도했다 onScrollListener
그리고 스크롤의 시작과 끝 지점을 찾을 수 있습니다.
나는 똑같이하려고했지만 Scrollview
불가능한 것 같습니다. 필요한 것을 달성 할 수있는 다른 방법이 있습니까?
내가 사용하고 HorizontalScrollView
레이아웃과 나는 스크롤의 시작과 끝 지점에 도달 한 사용자를 식별해야합니다.
들어 ListView
나는 a를 시도했다 onScrollListener
그리고 스크롤의 시작과 끝 지점을 찾을 수 있습니다.
나는 똑같이하려고했지만 Scrollview
불가능한 것 같습니다. 필요한 것을 달성 할 수있는 다른 방법이 있습니까?
답변:
View 호출의 모든 인스턴스 getViewTreeObserver()
. 이제의 인스턴스를 보유 할 때 메소드를 사용하여 인스턴스를 ViewTreeObserver
추가 할 수 있습니다 .OnScrollChangedListener()
addOnScrollChangedListener()
이 클래스에 대한 자세한 내용은 여기를 참조 하십시오 .
모든 스크롤 이벤트를 알 수 있지만 좌표는 없습니다. 그래도 리스너 를 사용 getScrollY()
하거나 getScrollX()
리스너 내에서 가져올 수 있습니다 .
scrollView.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() {
@Override
public void onScrollChanged() {
int scrollY = rootScrollView.getScrollY(); // For ScrollView
int scrollX = rootScrollView.getScrollX(); // For HorizontalScrollView
// DO SOMETHING WITH THE SCROLL COORDINATES
}
});
hsv.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {@Override public void onScrollChanged() {Log.i(TAG,"scroll:"+hsv.getScrollX());}});
ONSTART에 어디 () hsv
A는 HorizontalScrollView
작동합니다. ScrollView에서도 동일하게 작동한다고 생각합니다.
add
and가 아니기 set
때문에 모든 리스너는 명시 적으로 제거 될 때까지 유지됩니다. 따라서 샘플에서 리스너 구현으로 사용되는 익명 클래스는 참조하는 모든 것, 즉 외부 클래스와 함께 누출됩니다.
이것은 매우 유용 할 수 있습니다. NestedScrollView
대신에 사용하십시오 ScrollView
. 지원 라이브러리 23.1는 도입 OnScrollChangeListener
에 NestedScrollView
. 이런 식으로 할 수 있습니다.
myScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
@Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
Log.d("ScrollView","scrollX_"+scrollX+"_scrollY_"+scrollY+"_oldScrollX_"+oldScrollX+"_oldScrollY_"+oldScrollY);
//Do something
}
});
NestedScrollView
는 지원 라이브러리의 일부이며, 그 setOnScrollChangeListener
방법에는 최소 버전 요구 사항이 없습니다.
View
의 ' setOnScrollChangeListener
API 레벨 23를 필요로하는
다음은 스크롤 및 스크롤 종료에 대한 알림을 처리하기 위해 작성한 파생 HorizontalScrollView입니다. 사용자가 스크롤 적극적으로 중지 할 때 제대로 처리 하고 완전히 감속 할 때 사용자가 갈 수 후 :
public class ObservableHorizontalScrollView extends HorizontalScrollView {
public interface OnScrollListener {
public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY);
public void onEndScroll(ObservableHorizontalScrollView scrollView);
}
private boolean mIsScrolling;
private boolean mIsTouching;
private Runnable mScrollingRunnable;
private OnScrollListener mOnScrollListener;
public ObservableHorizontalScrollView(Context context) {
this(context, null, 0);
}
public ObservableHorizontalScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ObservableHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
if (action == MotionEvent.ACTION_MOVE) {
mIsTouching = true;
mIsScrolling = true;
} else if (action == MotionEvent.ACTION_UP) {
if (mIsTouching && !mIsScrolling) {
if (mOnScrollListener != null) {
mOnScrollListener.onEndScroll(this);
}
}
mIsTouching = false;
}
return super.onTouchEvent(ev);
}
@Override
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
super.onScrollChanged(x, y, oldX, oldY);
if (Math.abs(oldX - x) > 0) {
if (mScrollingRunnable != null) {
removeCallbacks(mScrollingRunnable);
}
mScrollingRunnable = new Runnable() {
public void run() {
if (mIsScrolling && !mIsTouching) {
if (mOnScrollListener != null) {
mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this);
}
}
mIsScrolling = false;
mScrollingRunnable = null;
}
};
postDelayed(mScrollingRunnable, 200);
}
if (mOnScrollListener != null) {
mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY);
}
}
public OnScrollListener getOnScrollListener() {
return mOnScrollListener;
}
public void setOnScrollListener(OnScrollListener mOnEndScrollListener) {
this.mOnScrollListener = mOnEndScrollListener;
}
}
뷰의 스크롤 위치를 알고 싶다면 View 클래스에서 다음 확장 기능을 사용할 수 있습니다.
fun View?.onScroll(callback: (x: Int, y: Int) -> Unit) {
var oldX = 0
var oldY = 0
this?.viewTreeObserver?.addOnScrollChangedListener {
if (oldX != scrollX || oldY != scrollY) {
callback(scrollX, scrollY)
oldX = scrollX
oldY = scrollY
}
}
}
NestedScrollView
대신 사용할 수 있습니다 ScrollView
. 그러나 Kotlin Lambda를 사용할 때 setOnScrollChangeListener
View (API 레벨 23) 대신 NestedScrollView를 원한다는 것을 알 수 없습니다 . 첫 번째 매개 변수를 NestedScrollView로 지정하여이 문제를 해결할 수 있습니다.
nestedScrollView.setOnScrollChangeListener { _: NestedScrollView, scrollX: Int, scrollY: Int, _: Int, _: Int ->
Log.d("ScrollView", "Scrolled to $scrollX, $scrollY")
}
사용자 정의 ScrollView 클래스를 정의하고 다음과 같이 스크롤 할 때 호출되는 인터페이스를 추가 할 수 있습니다.
public class ScrollChangeListenerScrollView extends HorizontalScrollView {
private MyScrollListener mMyScrollListener;
public ScrollChangeListenerScrollView(Context context) {
super(context);
}
public ScrollChangeListenerScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScrollChangeListenerScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setOnMyScrollListener(MyScrollListener myScrollListener){
this.mMyScrollListener = myScrollListener;
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if(mMyScrollListener!=null){
mMyScrollListener.onScrollChange(this,l,t,oldl,oldt);
}
}
public interface MyScrollListener {
void onScrollChange(View view,int scrollX,int scrollY,int oldScrollX, int oldScrollY);
}
}
// --------Start Scroll Bar Slide--------
final HorizontalScrollView xHorizontalScrollViewHeader = (HorizontalScrollView) findViewById(R.id.HorizontalScrollViewHeader);
final HorizontalScrollView xHorizontalScrollViewData = (HorizontalScrollView) findViewById(R.id.HorizontalScrollViewData);
xHorizontalScrollViewData.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
int scrollX; int scrollY;
scrollX=xHorizontalScrollViewData.getScrollX();
scrollY=xHorizontalScrollViewData.getScrollY();
xHorizontalScrollViewHeader.scrollTo(scrollX, scrollY);
}
});
// ---------End Scroll Bar Slide---------
onStart
은 트릭을 수행합니다hsv.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {@Override public void onScrollChanged() {Log.i(TAG,"scroll:"+hsv.getScrollX());}});
.onStart () 어디hsv
에서HorizontalScrollView
작동합니다.