我HorizontalScrollView
在布局中使用,我需要确定用户已经到达滚动的起点和终点。
因为ListView
我已经尝试过了onScrollListener
,所以可以找到滚动的起点和终点。
我试图在我的身上做同样的事情,Scrollview
但似乎不可能。还有其他可能的方法来实现我所需要的。
我HorizontalScrollView
在布局中使用,我需要确定用户已经到达滚动的起点和终点。
因为ListView
我已经尝试过了onScrollListener
,所以可以找到滚动的起点和终点。
我试图在我的身上做同样的事情,Scrollview
但似乎不可能。还有其他可能的方法来实现我所需要的。
Answers:
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
是可行的HorizontalScrollView
。我怀疑同样适用于ScrollView。
add
不是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;
}
}
您可以使用NestedScrollView
代替ScrollView
。但是,当使用Kotlin Lambda时,它不会知道您想要的是NestedScrollView,setOnScrollChangeListener
而不是View的(API级别23)。您可以通过将第一个参数指定为NestedScrollView来解决此问题。
nestedScrollView.setOnScrollChangeListener { _: NestedScrollView, scrollX: Int, scrollY: Int, _: Int, _: Int ->
Log.d("ScrollView", "Scrolled to $scrollX, $scrollY")
}
// --------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---------
您可以定义一个自定义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);
}
}
onStart
可以解决问题:hsv.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {@Override public void onScrollChanged() {Log.i(TAG,"scroll:"+hsv.getScrollX());}});
在onStart()中,这hsv
是可行的HorizontalScrollView
。