Избегайте SwipeRefresh при быстрой прокрутке в Android
У меня есть ListView
имеющий fastScroll
всегда включен и SwipeRefresh
реализация. Когда я смахиваю список вниз, он обновляет список. Моя проблема fastScroll
, Если в списке есть первый видимый элемент или, скажем, в начале, то прокрутите fastScrollThumb
вниз, это делает Swipe
эффект не прокручивать вниз. Есть ли в любом случае / решение, что если я нажму fastScrollThumb
, то это не должно делать Swipe
Эффект обновления скорее должен прокручиваться вниз, так как это естественное поведение.
Отредактированный мой 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>
мой Logic for onScroll
для включения / выключения SwipeRefresh
является:
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();
}
}
});
2 ответа
Я просто заглянул в документацию SwipeRefreshLayout
и я думаю, что они упоминают, что вы ищете:
... Если слушатель определяет, что обновления не должно быть, он должен вызвать
setRefreshing(false)
отменить любую визуальную индикацию обновления. Если действие хочет показать только анимацию прогресса, оно должно вызватьsetRefreshing(true)
, Чтобы отключить жест и анимацию прогресса, позвонитеsetEnabled(false)
на вид.
Так что у вас есть несколько вариантов, я бы сначала попробовал поиграться с setEnabled()
или же setRefreshing()
, но чтобы правильно использовать эти методы, мы должны сначала определить, ListView
быстрая прокрутка. Нет слушателя или чего-либо еще для быстрой прокрутки, но вы можете получить состояние через отражение! На основании этого превосходного и серьезно недооцененного ответа я написал FastScrollListener
который может быть использован так же, как 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) {
}
});
Вы также можете попробовать позвонить setRefreshing()
вместо setEnabled()
если setEnabled()
не работает
И вот код 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);
}
Я надеюсь, что смогу помочь вам, и если у вас есть какие-либо дополнительные вопросы, пожалуйста, не стесняйтесь спрашивать!
РЕДАКТИРОВАТЬ: Попробуйте это, но я сомневаюсь, что это будет работать:
@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);
}
Быстрая прокрутка в переработке просмотра была добавлена в API 26. https://developer.android.com/topic/libraries/support-library/revisions.
Если вы хотите использовать его, предварительно используйте API.
https://github.com/L4Digital/FastScroll
Эта библиотека имеет встроенную функцию fastscroll и прослушиватель прокрутки, который может отключить макет обновления при прокрутке.
Разработчик решает проблему здесь: