在android中快速滚动时避免SwipeRefresh [英] Avoid SwipeRefresh while fastScrolling in android
问题描述
我有一个 ListView
始终启用 fastScroll
和 SwipeRefresh
实现.当我向下滑动列表时,它会刷新列表.我的问题是 fastScroll
.如果列表的第一项可见或在其初始顶部,那么如果向下滚动 fastScrollThumb
,它会执行 Swipe
效果而不是向下滚动.无论如何/解决方案,如果我按下 fastScrollThumb
,那么它不应该做 Swipe
刷新效果,而是应该向下滚动,因为它是自然行为.
I have a ListView
having fastScroll
always enabled and SwipeRefresh
implementation. When i swipe the list downward, it refreshes the list. My problem is fastScroll
. If the list has its first item visible or say at its initial top, then if scroll the fastScrollThumb
downward, it does the Swipe
effect not the scroll down. Is there anyway/solution that if i press the fastScrollThumb
, then it should not do Swipe
refresh effect rather it should scroll down as it natural behavior.
已编辑我的 XML Layout
如下:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="@+id/buttons_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp">
<ImageView
android:id="@+id/SubmitButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/neoo_tab_selector" />
</RelativeLayout>
<ListView
android:id="@id/android:list"
style="@style/NeeoContactListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/buttons_layout"
android:layout_marginTop="10dp" />
</RelativeLayout>
</android.support.v4.widget.SwipeRefreshLayout>
我用于启用/禁用 SwipeRefresh
的 onScroll
逻辑是:
My Logic for onScroll
for enabling/disabling the SwipeRefresh
is :
getListView().setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
boolean enable = false;
if(getListView() != null && getListView().getChildCount() > 0){
// check if the first item of the list is visible
boolean firstItemVisible = getListView().getFirstVisiblePosition() == 0;
// check if the top of the first item is visible
boolean topOfFirstItemVisible = getListView().getChildAt(0).getTop() == 0;
// enabling or disabling the refresh layout
enable = firstItemVisible && topOfFirstItemVisible;
}
if(enable){
enableSwipe();
}else{
disableSwipe();
}
}
});
推荐答案
我刚刚查看了 SwipeRefreshLayout
的文档,我认为他们提到了您要查找的内容:
I just looked into the documentation of the SwipeRefreshLayout
and I think they mention what you are looking for:
... 如果侦听器确定不应刷新,则必须调用 setRefreshing(false)
取消任何视觉指示刷新.如果一个活动希望只显示进度动画,它应该调用 setRefreshing(true)
.禁用手势和进度动画,在视图上调用 setEnabled(false)
.
... If the listener determines there should not be a refresh, it must call
setRefreshing(false)
to cancel any visual indication of a refresh. If an activity wishes to show just the progress animation, it should callsetRefreshing(true)
. To disable the gesture and progress animation, callsetEnabled(false)
on the view.
所以你有几个选择,我会首先尝试使用 setEnabled()
或 setRefreshing()
,但要正确使用这些方法,我们首先需要能够检测 ListView
是否正在快速滚动.没有侦听器或任何用于快速滚动的东西,但您可以通过反射获得状态!基于这个优秀但被严重低估的答案,我写了一个FastScrollListener
可以像 OnScrollListener
一样使用:
So you have a few options, I would first try playing around with setEnabled()
or setRefreshing()
, but to properly use those methods we first need to be able to detect if the ListView
is fast scrolling. There is no listener or anything for fast scrolling but you can get the state through reflection! Based on this excellent and seriously underrated answer I have written a FastScrollListener
which can be used just like a OnScrollListener
:
this.listView.setFastScrollEnabled(true);
this.listView.setOnScrollListener(new FastScrollListener(this.listView) {
@Override
protected void onFastScrollStateChanged(AbsListView view, FastScrollState state) {
// This line disabled the SwipeRefreshLayout
// whenever the user is fast scrolling
swipeRefreshLayout.setEnabled(state != FastScrollState.DRAGGING);
}
@Override
protected void onFastScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
如果 setEnabled()
不起作用,您也可以尝试调用 setRefreshing()
而不是 setEnabled()
.
You could also try calling setRefreshing()
instead of setEnabled()
if setEnabled()
doesn't work.
这里是FastScrollListener
的代码:
public abstract class FastScrollListener implements AbsListView.OnScrollListener {
private final int STATE_DRAGGING;
private final int STATE_VISIBLE;
private final int STATE_NONE;
public enum FastScrollState {
DRAGGING,
VISIBLE,
NONE,
UNKNOWN
}
private FastScrollState fastScrollState = FastScrollState.UNKNOWN;
private Field stateField;
private Object mFastScroller;
public FastScrollListener(AbsListView listView) {
try {
final Field fastScrollerField = AbsListView.class.getDeclaredField("mFastScroller");
fastScrollerField.setAccessible(true);
mFastScroller = fastScrollerField.get(listView);
final Field stateDraggingField = mFastScroller.getClass().getDeclaredField("STATE_DRAGGING");
stateDraggingField.setAccessible(true);
STATE_DRAGGING = stateDraggingField.getInt(mFastScroller);
final Field stateVisibleField = mFastScroller.getClass().getDeclaredField("STATE_VISIBLE");
stateVisibleField.setAccessible(true);
STATE_VISIBLE = stateVisibleField.getInt(mFastScroller);
final Field stateNoneField = mFastScroller.getClass().getDeclaredField("STATE_NONE");
stateNoneField.setAccessible(true);
STATE_NONE = stateNoneField.getInt(mFastScroller);
stateField = mFastScroller.getClass().getDeclaredField("mState");
stateField.setAccessible(true);
fastScrollState = getFastScrollState();
} catch (NoSuchFieldException e) {
throw new IllegalStateException("Could not find required fields for fast scroll detection!", e);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not find required fields for fast scroll detection!", e);
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
updateFastScrollState(view);
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
updateFastScrollState(view);
updateFastScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
private void updateFastScrollState(AbsListView view) {
if (stateField != null) {
final FastScrollState state = getFastScrollState();
if (fastScrollState != state) {
fastScrollState = state;
onFastScrollStateChanged(view, state);
}
}
}
private void updateFastScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if(fastScrollState == FastScrollState.DRAGGING) {
onFastScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
}
private FastScrollState getFastScrollState() {
try {
final int state = stateField.getInt(mFastScroller);
if (state == STATE_DRAGGING) {
return FastScrollState.DRAGGING;
}
if (state == STATE_VISIBLE) {
return FastScrollState.VISIBLE;
}
if (state == STATE_NONE) {
return FastScrollState.NONE;
}
return FastScrollState.UNKNOWN;
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not read fast scroll state!", e);
}
}
protected abstract void onFastScrollStateChanged(AbsListView view, FastScrollState state);
protected abstract void onFastScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount);
}
希望我能帮到你,如果你有任何其他问题,请随时提问!
I hope I could help you and if you have any further questions please feel free to ask!
试试这个,但我怀疑它会起作用:
Try this, but I doubt it will work:
@Override
protected void onFastScrollStateChanged(AbsListView view, FastScrollState state) {
boolean enable = false;
if (getListView().getChildCount() > 0) {
boolean firstItemVisible = getListView().getFirstVisiblePosition() == 0;
boolean topOfFirstItemVisible = getListView().getChildAt(0).getTop() == 0;
enable = firstItemVisible && topOfFirstItemVisible;
}
refreshLayout.setEnabled(enable);
}
这篇关于在android中快速滚动时避免SwipeRefresh的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!