避免SwipeRefresh而在Android的fastScrolling [英] Avoid SwipeRefresh while fastScrolling in android

查看:375
本文介绍了避免SwipeRefresh而在Android的fastScrolling的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 的ListView fastScroll 始终处于启用状态 SwipeRefresh 的实施。当我刷卡列表中向下,它刷新列表。我的问题是 fastScroll 。如果列表的第一个项目可见或者说在其最初的顶部,那么如果滚动的 fastScrollThumb 向下,但它确实在 刷卡 的效果不是向下滚动。反正是有/解决方案,如果我preSS的 fastScrollThumb ,那么它不应该做的刷卡刷新的效果,而它应该向下滚动,因为它自然的行为。

EDITED 我的 XML布局情况如下:

 < XML版本=1.0编码=UTF-8&GT?;
    < android.support.v4.widget.SwipeRefreshLayout
    的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:ID =@ + ID / swipe_container
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent
    机器人:背景=@色/白>

    < RelativeLayout的
        机器人:layout_width =match_parent
        机器人:layout_height =match_parent>

        < RelativeLayout的
            机器人:ID =@ + ID / buttons_layout
            机器人:layout_width =WRAP_CONTENT
            机器人:layout_height =WRAP_CONTENT
            机器人:layout_centerHorizo​​ntal =真
            机器人:layout_marginTop =10dp>

            < ImageView的
                机器人:ID =@ + ID /提交按钮
                机器人:layout_width =WRAP_CONTENT
                机器人:layout_height =WRAP_CONTENT
                机器人:背景=@可绘制/ neoo_tab_selector/>

        < / RelativeLayout的>


        <的ListView
            机器人:ID =@ ID / Android的:清单
            风格=@风格/ NeeoContactListView
            机器人:layout_width =match_parent
            机器人:layout_height =match_parent
            机器人:layout_below =@ + ID / buttons_layout
            机器人:layout_marginTop =10dp/>
    < / RelativeLayout的>

< /android.support.v4.widget.SwipeRefreshLayout>
 

我的 逻辑为onScroll 启用/禁用 SwipeRefresh 是:

  getListView()。setOnScrollListener(新OnScrollListener(){

    @覆盖
    公共无效onScrollStateChanged(AbsListView观点,诠释scrollState){
    }

    @覆盖
    公共无效onScroll(AbsListView观点,诠释firstVisibleItem,诠释visibleItemCount,诠释totalItemCount){
        布尔有效=虚假的;
        如果(getListView()= NULL和放大器;!&安培; getListView()getChildCount()> 0){
            //检查列表的第一个项目是可见
            布尔firstItemVisible = getListView()getFirstVisiblePosition()== 0。
            //检查是否所述第一项的顶部是可见
            布尔topOfFirstItemVisible = getListView()getChildAt(0).getTop()== 0。
            //启用或停用刷新布局
            启用= firstItemVisible和放大器;&安培; topOfFirstItemVisible;
        }
        如果(启用){
            enableSwipe();

        }其他{
            disableSwipe();

        }
    }
});
 

解决方案

我只是看着的 的文档 SwipeRefreshLayout ,我想他们提到你在找什么:

  

...如果侦听确定不应该有一个刷新,就必须   叫 setRefreshing(假)取消的任何视觉指示   刷新。如果活动希望只显示进度动画,它   应该叫 setRefreshing(真)。要禁用手势和进步   动漫,呼叫的setEnabled(假)的看法。

所以,你有几个选项,我先试试玩弄的setEnabled() setRefreshing() ,但正确使用这些我们首先需要能够检测是否的ListView 是快速滚动的方法。有没有监听器或任何要快速滚动,但你可以通过反射得到国家!基于 这个优秀的,严重被低估的答案 我已经写了 FastScrollListener 可用于就像一个 OnScrollListener

  this.listView.setFastScrollEnabled(真正的);
this.listView.setOnScrollListener(新FastScrollListener(this.listView){

    @覆盖
    保护无效onFastScrollStateChanged(AbsListView观点,FastScrollState州){
        //这行禁用SwipeRefreshLayout
        //每当用户快速滚动
        swipeRefreshLayout.setEnabled(州= FastScrollState.DRAGGING!);
    }

    @覆盖
    保护无效onFastScroll(AbsListView观点,诠释firstVisibleItem,诠释visibleItemCount,诠释totalItemCount){

    }
});
 

您也可以尝试调用 setRefreshing()而不是的setEnabled()如果的setEnabled ()不起作用。

这里是的code中的 FastScrollListener

 公共抽象类FastScrollListener实现AbsListView.OnScrollListener {

    私人最终诠释STATE_DRAGGING;
    私人最终诠释STATE_VISIBLE;
    私人最终诠释STATE_NONE;

    公共枚举FastScrollState {
        拖动
        可见,
        NONE,
        未知
    }

    私人FastScrollState fastScrollState = FastScrollState.UNKNOWN;
    私人领域stateField;
    私有对象mFastScroller;

    公共FastScrollListener(AbsListView的ListView){
        尝试 {
            最后一个字段fastScrollerField = AbsListView.class.getDeclaredField(mFastScroller);
            fastScrollerField.setAccessible(真正的);
            mFastScroller = fastScrollerField.get(ListView控件);

            最后一个字段stateDraggingField = mFastScroller.getClass()getDeclaredField(STATE_DRAGGING)。
            stateDraggingField.setAccessible(真正的);
            STATE_DRAGGING = stateDraggingField.getInt(mFastScroller);

            最后一个字段stateVisibleField = mFastScroller.getClass()getDeclaredField(STATE_VISIBLE)。
            stateVisibleField.setAccessible(真正的);
            STATE_VISIBLE = stateVisibleField.getInt(mFastScroller);

            最后一个字段stateNoneField = mFastScroller.getClass()getDeclaredField(STATE_NONE)。
            stateNoneField.setAccessible(真正的);
            STATE_NONE = stateNoneField.getInt(mFastScroller);

            stateField = mFastScroller.getClass()getDeclaredField(mState);
            stateField.setAccessible(真正的);
            fastScrollState = getFastScrollState();

        }赶上(NoSuchFieldException E){
            抛出新IllegalStateException异常(无法找到快速滚动检测所需的领域!,E);
        }赶上(IllegalAccessException E){
            抛出新IllegalStateException异常(无法找到快速滚动检测所需的领域!,E);
        }
    }

    @覆盖
    公共无效onScrollStateChanged(AbsListView观点,诠释scrollState){
        updateFastScrollState(视图);
    }

    @覆盖
    公共无效onScroll(AbsListView观点,诠释firstVisibleItem,诠释visibleItemCount,诠释totalItemCount){
        updateFastScrollState(视图);
        updateFastScroll(查看,firstVisibleItem,visibleItemCount,totalItemCount);
    }

    私人无效updateFastScrollState(AbsListView视图){
        如果(stateField!= NULL){
            最后FastScrollState状态= getFastScrollState();
            如果(fastScrollState!=状态){
                fastScrollState =状态;
                onFastScrollStateChanged(视图,状态);
            }
        }
    }

    私人无效updateFastScroll(AbsListView观点,诠释firstVisibleItem,诠释visibleItemCount,诠释totalItemCount){
        如果(fastScrollState == FastScrollState.DRAGGING){
            onFastScroll(查看,firstVisibleItem,visibleItemCount,totalItemCount);
        }
    }

    私人FastScrollState getFastScrollState(){

        尝试 {
            最终诠释状态= stateField.getInt(mFastScroller);

            如果(国家== STATE_DRAGGING){
                返回FastScrollState.DRAGGING;
            }

            如果(国家== STATE_VISIBLE){
                返回FastScrollState.VISIBLE;
            }

            如果(国家== STATE_NONE){
                返回FastScrollState.NONE;
            }

            返回FastScrollState.UNKNOWN;
        }赶上(IllegalAccessException E){
            抛出新IllegalStateException异常(无法读取快速滚动的状态!,E);
        }
    }

    保护抽象无效onFastScrollStateChanged(AbsListView观点,FastScrollState状态);

    保护抽象无效onFastScroll(AbsListView观点,诠释firstVisibleItem,诠释visibleItemCount,INT totalItemCount);
}
 

我希望我可以帮你,如果你有任何问题,请随时问!


编辑:试试这个,但我怀疑它会工作:

  @覆盖
保护无效onFastScrollStateChanged(AbsListView观点,FastScrollState州){
    布尔有效=虚假的;
    如果(getListView()getChildCount()> 0){
        布尔firstItemVisible = getListView()getFirstVisiblePosition()== 0。
        布尔topOfFirstItemVisible = getListView()getChildAt(0).getTop()== 0。
        启用= firstItemVisible和放大器;&安培; topOfFirstItemVisible;
    }
    refreshLayout.setEnabled(启用);
}
 

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.

EDITED My XML Layout is as follow:

    <?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>

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();

        }
    }
});

解决方案

I just looked into the documentation of the SwipeRefreshLayout and I think they mention what you are looking for:

... 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 call setRefreshing(true). To disable the gesture and progress animation, call setEnabled(false) on the view.

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) {

    }
});

You could also try calling setRefreshing() instead of setEnabled() if setEnabled() doesn't work.

And here is the code of the 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!


EDIT: 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);
}

这篇关于避免SwipeRefresh而在Android的fastScrolling的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆