我有一个应用程序,有一个使用的活动ScrollView
。 我需要在用户获取到的底部,以检测ScrollView
。 我做了一些googleing,我发现这个网页 ,其中解释。 但是,在本例中,该人延伸ScrollView
。 正如我所说的,我需要延长活动。
所以,我说:“好吧,让我们尝试做延伸的自定义类ScrollView
,覆盖onScrollChanged()
方法,检测滚动结束,并采取相应的行动。”
我这样做,但在这一行:
scroll = (ScrollViewExt) findViewById(R.id.scrollView1);
它抛出一个java.lang.ClassCastException
。 我改变了<ScrollView>
标记在我的XML,但是,很显然,这是行不通的。 我的问题是:为什么,如果ScrollViewExt
延伸ScrollView
,投我的脸一个ClassCastException
? 有没有什么办法来检测滚动的结束不会弄乱太多了?
谢谢大家了。
编辑:由于答应,这里是一片我的XML的事项:
<ScrollView
android:id="@+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<WebView
android:id="@+id/textterms"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:textColor="@android:color/black" />
</ScrollView>
我改变了它TextView
到WebView
能够证明里面的文字。 我想实现的是“接受按钮不激活直到合同的条款仔细阅读”的事情。 我的扩展类被称为ScrollViewEx
吨。 如果我改变标签ScrollView
的ScrollViewExt
它抛出一个
android.view.InflateException: Binary XML file line #44: Error inflating class ScrollViewExt
因为它不理解的标签ScrollViewEx
。 我不认为它有一个解决方案...
谢谢您的回答!
Answer 1:
做到了!
除了修复亚历山大好心给我的,我不得不创建一个接口:
public interface ScrollViewListener {
void onScrollChanged(ScrollViewExt scrollView,
int x, int y, int oldx, int oldy);
}
于是,我不得不重写从滚动型的OnScrollChanged方法在我ScrollViewExt:
public class ScrollViewExt extends ScrollView {
private ScrollViewListener scrollViewListener = null;
public ScrollViewExt(Context context) {
super(context);
}
public ScrollViewExt(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ScrollViewExt(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setScrollViewListener(ScrollViewListener scrollViewListener) {
this.scrollViewListener = scrollViewListener;
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (scrollViewListener != null) {
scrollViewListener.onScrollChanged(this, l, t, oldl, oldt);
}
}
}
现在,亚历山大说,把包名的XML标签(我的错),使我的Activity类实现之前创建的接口,然后把它放在一起:
scroll = (ScrollViewExt) findViewById(R.id.scrollView1);
scroll.setScrollViewListener(this);
而在方法OnScrollChanged,从界面...
@Override
public void onScrollChanged(ScrollViewExt scrollView, int x, int y, int oldx, int oldy) {
// We take the last son in the scrollview
View view = (View) scrollView.getChildAt(scrollView.getChildCount() - 1);
int diff = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY()));
// if diff is zero, then the bottom has been reached
if (diff == 0) {
// do stuff
}
}
和它的工作!
非常感谢您的帮助,亚历山大!
Answer 2:
我发现了一个简单的方法来检测这样的:
scrollView.getViewTreeObserver()
.addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
if (scrollView.getChildAt(0).getBottom()
<= (scrollView.getHeight() + scrollView.getScrollY())) {
//scroll view is at bottom
} else {
//scroll view is not at bottom
}
}
});
- 不需要自定义滚动型。
- 滚动型只能承载一个直接的孩子,所以scrollView.getChildAt(0)是好的。
- 该解决方案是滚动视图的直接孩子的权利,即使高度match_parent或WRAP_CONTENT。
Answer 3:
所有这些问题的答案是如此复杂,但有内置的方法简单,完成此: canScrollVertically(int)
例如:
@Override
public void onScrollChanged() {
if (!scrollView.canScrollVertically(1)) {
// bottom of scroll view
}
if (!scrollView.canScrollVertically(-1)) {
// top of scroll view
}
}
这也适用于RecyclerView,ListView控件,而实际上由于该方法的任何其他视图上实现View
。
如果你有一个水平滚动型,同样可以实现canScrollHorizontally(int)
Answer 4:
Fustigador答案是伟大的,但我发现了一些设备(如三星Galaxy Note的V)不能达到0,已经2点离开,计算后。 我建议加一点缓冲象下面这样:
@Override
public void onScrollChanged(ScrollViewExt scrollView, int x, int y, int oldx, int oldy) {
// We take the last son in the scrollview
View view = (View) scrollView.getChildAt(scrollView.getChildCount() - 1);
int diff = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY()));
// if diff is zero, then the bottom has been reached
if (diff <= 10) {
// do stuff
}
}
Answer 5:
编辑
随着你的XML的内容,我可以看到你使用滚动型。 如果你想使用自定义视图,你必须写com.your.packagename.ScrollViewExt,你就可以在你的代码中使用它。
<com.your.packagename.ScrollViewExt
android:id="@+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<WebView
android:id="@+id/textterms"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:textColor="@android:color/black" />
</com.your.packagename.ScrollViewExt>
编辑结束
你可以发布XML内容?
我认为,你可以简单地添加滚动监听器和检查的最后一项显示是从列表视图,如最新的一个:
mListView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
if(view.getLastVisiblePosition()==(totalItemCount-1)){
//dosomething
}
}
});
Answer 6:
您可以使用支持图书馆的NestedScrollView
和它的NestedScrollView.OnScrollChangeListener
接口。
https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html
另外,如果您的应用程序的目标是API 23或以上,你可以使用在以下方法的ScrollView
:
View.setOnScrollChangeListener(OnScrollChangeListener listener)
然后按照@Fustigador在他的回答中描述的例子。 但是请注意,如@Will描述,你应该考虑增加一个小的缓冲区,以防用户或系统不能达到列表的底部完全出于任何原因。
还值得注意的是,滚动改变收听者将有时与负值被调用或值比视图高度。 据推测,这些值表示的滚动操作的“势头”。 然而,除非适当的处理(地板/ ABS),他们可能会导致问题检测滚动方向,当视图被滚动到该范围的顶部或底部。
https://developer.android.com/reference/android/view/View.html#setOnScrollChangeListener(android.view.View.OnScrollChangeListener)
Answer 7:
我们应该时时补充scrollView.getPaddingBottom()
来匹配全滚动型高度,因为一段时间滚动视图在XML文件填充,这样情况下,它不会去上班。
scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
if (scrollView != null) {
View view = scrollView.getChildAt(scrollView.getChildCount()-1);
int diff = (view.getBottom()+scrollView.getPaddingBottom()-(scrollView.getHeight()+scrollView.getScrollY()));
// if diff is zero, then the bottom has been reached
if (diff == 0) {
// do stuff
}
}
}
});
Answer 8:
scrollView = (ScrollView) findViewById(R.id.scrollView);
scrollView.getViewTreeObserver()
.addOnScrollChangedListener(new
ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
if (!scrollView.canScrollVertically(1)) {
// bottom of scroll view
}
if (!scrollView.canScrollVertically(-1)) {
// top of scroll view
}
}
});
Answer 9:
大多数的答案工作的事实旁边,即当u滚动至底部,听者多次触发 ,这在我的情况是不可取的 。 为了避免这种行为,我已经添加标志scrollPositionChanged来检查,如果滚动位置,即使再次调用方法之前改变。
public class EndDetectingScrollView extends ScrollView {
private boolean scrollPositionChanged = true;
private ScrollEndingListener scrollEndingListener;
public interface ScrollEndingListener {
void onScrolledToEnd();
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
View view = this.getChildAt(this.getChildCount() - 1);
int diff = (view.getBottom() - (this.getHeight() + this.getScrollY()));
if (diff <= 0) {
if (scrollPositionChanged) {
scrollPositionChanged = false;
if (scrollEndingListener != null) {
scrollEndingListener.onScrolledToEnd();
}
}
} else {
scrollPositionChanged = true;
}
}
public void setScrollEndingListener(ScrollEndingListener scrollEndingListener) {
this.scrollEndingListener = scrollEndingListener;
}
}
然后,只需设置监听器
scrollView.setScrollEndingListener(new EndDetectingScrollView.ScrollEndingListener() {
@Override
public void onScrolledToEnd() {
//do your stuff here
}
});
你可以做同样的事情如果u做到像
scrollView.getViewTreeObserver().addOnScrollChangedListener(...)
但你必须从你的类添加此聆听者提供标志。
Answer 10:
要确定您是否在您的自定义结束ScrollView
,你也可以使用一个成员变量和存储最后y位置。 然后,你可以比较当前滚动位置的最后一个Y位置。
private int scrollViewPos;
...
@Override
public void onScrollChanged(ScrollViewExt scrollView, int x, int y, int oldx, int oldy) {
//reached end of scrollview
if (y > 0 && scrollViewPos == y){
//do something
}
scrollViewPos = y;
}
文章来源: Detect end of ScrollView