【问题标题】:SwipeRefreshLayout interfering with setOnScrollListenerSwipeRefreshLayout 干扰 setOnScrollListener
【发布时间】:2015-02-12 09:16:38
【问题描述】:

每次向上或向下滚动列表时,我都会使用OnScrollListener 隐藏(或取消隐藏)一些视图。这是附加到我的ListView 的代码。

lv.setOnScrollListener(new OnScrollListener() {

            private int mLastFirstVisibleItem;
            private boolean mIsScrollingUp = true;
            private LinearLayout ll = (LinearLayout) getActivity()
                    .findViewById(R.id.llSearchPlaces);

            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {

            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem,
                                 int visibleItemCount, int totalItemCount) {



                if (view.getId() == lv.getId()) {
                    final int currentFirstVisibleItem = lv
                            .getFirstVisiblePosition();
                    if (currentFirstVisibleItem > mLastFirstVisibleItem) {

                        if (mIsScrollingUp == true) {
                            mIsScrollingUp = false;
                             Log.i("a", "scrolling down...");

                            floatingActionButton.hide();

                            Animation animation = new TranslateAnimation(0, 0,
                                    0, 200);
                            animation.setDuration(300);
                            animation
                                    .setAnimationListener(new AnimationListener() {

                                        @Override
                                        public void onAnimationEnd(
                                                Animation animation) {
                                            ll.setVisibility(View.INVISIBLE);
                                        }

                                        @Override
                                        public void onAnimationRepeat(
                                                Animation animation) {
                                        }

                                        @Override
                                        public void onAnimationStart(
                                                Animation animation) {
                                        }
                                    });

                            ll.startAnimation(animation);
                        }

                    } else if (currentFirstVisibleItem < mLastFirstVisibleItem) {

                        if (mIsScrollingUp == false) {
                            mIsScrollingUp = true;
                            floatingActionButton.show();
                             Log.i("a", "scrolling up...");

                            Animation animation = new TranslateAnimation(0, 0,
                                    200, 0);
                            animation.setDuration(400);
                            animation
                                    .setAnimationListener(new AnimationListener() {

                                        @Override
                                        public void onAnimationEnd(
                                                Animation animation) {

                                        }

                                        @Override
                                        public void onAnimationRepeat(
                                                Animation animation) {

                                        }

                                        @Override
                                        public void onAnimationStart(
                                                Animation animation) {
                                            ll.setVisibility(View.VISIBLE);

                                        }
                                    });

                            ll.startAnimation(animation);

                        }
                    }

                    mLastFirstVisibleItem = currentFirstVisibleItem;

                }
            }
        });

布局:

<android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/swipe_refresh_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ListView
        android:id="@id/android:list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fadeScrollbars="true"
        android:listSelector="#00000000"
        android:scrollbars="none" />

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

自从我添加了SwipeRefreshLayout,当我在上面的监听器中Log 时,我什么也得不到。如何同时使用这两个项目?

编辑:似乎this 是我需要的,但我无法让它继续工作

作为那篇文章的一部分,我在onScroll 中添加了这个,但它似乎不起作用。

        if (firstVisibleItem == 0) {
            swipeLayout.setEnabled(true);
        } else {
            swipeLayout.setEnabled(false);
        }

EDIT2:这是问题的核心:似乎onScroll 方法会在 Activity 首次启动并且列表加载时触发,然后再也不会加载。

【问题讨论】:

    标签: android listview swiperefreshlayout onscrolllistener


    【解决方案1】:

    RecyclerViewListView 我也遇到了同样的问题。向下滚动查看任何数量的项目,都无法返回列表顶部。

    这将禁用SwipeRefreshLayout,直到第一个可见项目或任何项目位置可见。您还可以沿此绑定不同的滚动侦听器。确保在重新填充列表时启用(如果以前禁用)SwipeRefreshLayout

    public class SwipeRefreshLayoutToggleScrollListenerListView implements AbsListView.OnScrollListener {
        private List<AbsListView.OnScrollListener> mScrollListeners = new ArrayList<AbsListView.OnScrollListener>();
        private int mExpectedVisiblePosition = 0;
    
        public SwipeRefreshLayoutToggleScrollListenerListView(SwipeRefreshLayout mSwipeLayout) {
            this.mSwipeLayout = mSwipeLayout;
        }
    
        private SwipeRefreshLayout mSwipeLayout;
        public void addScrollListener(AbsListView.OnScrollListener listener){
            mScrollListeners.add(listener);
        }
        public boolean removeScrollListener(AbsListView.OnScrollListener listener){
            return mScrollListeners.remove(listener);
        }
        public void setExpectedFirstVisiblePosition(int position){
            mExpectedVisiblePosition = position;
        }
    
        private void notifyOnScrolled(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount){
            for(AbsListView.OnScrollListener listener : mScrollListeners){
                listener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
            }
        }
        private void notifyScrollStateChanged(AbsListView view, int scrollState){
            for(AbsListView.OnScrollListener listener : mScrollListeners){
                listener.onScrollStateChanged(view, scrollState);
            }
        }
    
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
          notifyScrollStateChanged(view, scrollState);
        }
    
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            notifyOnScrolled(view, firstVisibleItem, visibleItemCount, totalItemCount);
            if(firstVisibleItem != RecyclerView.NO_POSITION)
                mSwipeLayout.setEnabled(firstVisibleItem == mExpectedVisiblePosition);
        }
    }
    

    编辑:

    lv.setOnScrollListener(new SwipeRefreshLayoutToggleScrollListenerListView(mSwiperLayout){
       //override methods here, don't forget the super calls. 
    });
    

    【讨论】:

    • 谢谢。还在为这个苦苦挣扎。在上述不是Override 的方法上,它们需要在哪里调用?这就是我所在的位置:当 Activity 启动时,它会立即调用 onScrollStateChanged(不知道为什么——我猜想填充列表?)它将启用 SwipeLayout。然后,当我手动向上或向下滚动列表时,它不会被调用。如果从未调用过布局,我将无法禁用它。另外,我不是implements AbsListView.OnScrollListener。我只是使用匿名内部class
    • 如果我说得对,你担心使用情况,请参阅我的编辑。即使没有匿名实例化,您仍然可以覆盖方法。
    • 感谢您的编辑,我确实是这样的。不知道为什么我实际上提出了那部分。我确实注意到了,您提供的方法没有被覆盖,除了notifyScrollStateChanged,我没有看到它们被使用。想知道这是否就是我还没有弄清楚这个的原因。
    • 如果您不需要这些方法,您可以删除它们。如果您想为一个 ListView 提供多个滚动侦听器,则使用它们
    • 您好,感谢您的帮助。还在做这个。无法使用此代码解决此问题...会及时更新
    【解决方案2】:

    您应该覆盖 canChildScrollUpSwipeRefreshView。轮询这个方法的目的是为了知道包含的 View 是否要向上滚动:

    为任意包含的视图提供可设置界面的扩展:

    public class SwipeRefreshWrapper extends SwipeRefreshLayout {
        private ScrollResolver mScrollResolver;
    
        public SwipeRefreshWrapper(Context context) {
            super(context);
        }
    
        public SwipeRefreshWrapper(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public void setScrollResolver(ScrollResolver scrollResolver) {
            mScrollResolver = scrollResolver;
        }
    
        @Override
        public boolean canChildScrollUp() {
            if(mScrollResolver != null){
                return mScrollResolver.canScrollUp();
            }else {
                return super.canChildScrollUp();
            }
        }
    
        public static interface ScrollResolver{
            public boolean canScrollUp();
        }
    }
    

    用法(ListView也有一个不错的方法:canScrollVertically()):

    final SwipeRefreshWrapper wrapper = (SwipeRefreshWrapper) rootView.findViewById(R.id.wrapper);
    final ListView list = (ListView) rootView.findViewById(R.id.list);
    
    wrapper.setScrollResolver(new SwipeRefreshWrapper.ScrollResolver() {
                                  @Override
                                  public boolean canScrollUp() {
                                     return list.canScrollVertically(-1);
                                  }
                              });
    

    【讨论】:

      【解决方案3】:
      yourListview.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(timelogListView != null && timelogListView.getChildCount() > 0){
                      boolean firstItemVisible = timelogListView.getFirstVisiblePosition() == 0;
                      boolean topOfFirstItemVisible = timelogListView.getChildAt(0).getTop() == 0;
                      enable = firstItemVisible && topOfFirstItemVisible;
                  }
                  swipeLayout.setEnabled(enable); 
                  if(firstVisibleItem+visibleItemCount == totalItemCount && totalItemCount!=0)
                  {
                      if(flag_loading == false)
                      {
                          flag_loading = true;
                          ConnectionDetector conn = new ConnectionDetector(getActivity());
                          if(conn.isConnectingToInternet()){
                              // call for your pagination async
                          }else{
      
                          }
                      }
                  }
              }
          });
      

      默认情况下:private boolean flag_loading = false;并在您的分页 async if(YourListview.size()

      【讨论】:

      • 这似乎你在假设我正在使用一个分页的ListView,它会无休止地滚动。不是,是固定大小。
      猜你喜欢
      • 2015-09-22
      • 1970-01-01
      • 1970-01-01
      • 2015-02-09
      • 2012-07-17
      • 2019-06-17
      • 2011-04-02
      • 2020-04-01
      • 2017-08-27
      相关资源
      最近更新 更多