18

SwipeRefreshLayout在下面的布局中使用:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:background="@color/homePageBackground"
  android:orientation="vertical" >


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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >
<fragment
        android:id="@+id/announcementHomefragment"
        android:name="in.test.app.AnnouncementFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/homePageBackground" >

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="15dp"
                android:background="@color/homePageBackground" >

                <TextView
                    android:id="@+id/newsTitle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="15dp"
                    android:layout_marginTop="5dp"
                    android:gravity="center"
                    android:text="@string/new_list"
                    android:textAppearance="?android:attr/textAppearanceSmall"
                    android:textColor="@color/white"
                    android:textStyle="bold" />

                <fragment
                    android:id="@+id/newshomefragment"
                    android:name="in.test.app.NewsFragment"
                    android:layout_width="wrap_content"
                    android:layout_height="190dp"
                    android:layout_below="@id/newsTitle"
                    android:layout_marginTop="-15dp" />

                <TextView
                    android:id="@+id/productTitle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/newshomefragment"
                    android:layout_gravity="center"
                    android:layout_marginLeft="15dp"
                    android:layout_marginTop="5dp"
                    android:gravity="center"
                    android:text="@string/product_in_home"
                    android:textAppearance="?android:attr/textAppearanceSmall"
                    android:textColor="@color/white"
                    android:textStyle="bold" />

                <fragment
                    android:id="@+id/proCategoryhomefragment"
                    android:name="in.test.app.CategoryFragment"
                    android:layout_width="wrap_content"
                    android:layout_height="170dp"
                    android:layout_below="@id/productTitle"
                    android:layout_marginTop="-15dp" />

                <TextView
                    android:id="@+id/trainingTitle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/proCategoryhomefragment"
                    android:layout_gravity="center"
                    android:layout_marginLeft="15dp"
                    android:layout_marginTop="2dp"
                    android:gravity="center"
                    android:text="@string/trainings_in_home"
                    android:textAppearance="?android:attr/textAppearanceSmall"
                    android:textColor="@color/white"
                    android:textStyle="bold" />

                <fragment
                    android:id="@+id/trainingfragment"
                    android:name="in.test.app.TrainingFragment"
                    android:layout_width="match_parent"
                    android:layout_height="180dp"
                    android:layout_below="@id/trainingTitle"
                    android:layout_marginBottom="10dp"
                    android:layout_marginTop="-15dp" />
            </RelativeLayout>
        </ScrollView>
    </LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout>

当我拉下它时SwipeRefreshLayout它正在工作,但正如您在上面的代码中看到的那样,我在其中有一个滚动视图。因此,当我拉下滚动视图时,它会下降,并且一半的图像没有显示,因为它下降了。当我试图再次拉起时,我的滚动视图没有上升。相反,SwipeRefreshLayout正在接听电话。我应该怎么办?

请帮帮我。

4

7 回答 7

29

我会说最好有一个扩展的 SwipeRefreshLayout 和监听器,以便能够从显示此布局的类中添加各种条件。

类似于以下内容: GeneralSwipeRefreshLayout.java

public class GeneralSwipeRefreshLayout extends SwipeRefreshLayout {   
  private OnChildScrollUpListener mScrollListenerNeeded;

  public interface OnChildScrollUpListener {
    boolean canChildScrollUp();
  }

  public GeneralSwipeRefreshLayout(Context context) {
    super(context);   
  }
  public GeneralSwipeRefreshLayout(Context context, AttributeSet attrs) {
    super(context, attrs);   
  }

 /**
  * Listener that controls if scrolling up is allowed to child views or not
  */
  public void setOnChildScrollUpListener(OnChildScrollUpListener listener) {
    mScrollListenerNeeded = listener;   
  }

  @Override
  public boolean canChildScrollUp() {
    if (mScrollListenerNeeded == null) {
      Log.e(GeneralSwipeRefreshLayout.class.getSimpleName(), "listener is not defined!");
    }
    return mScrollListenerNeeded != null && mScrollListenerNeeded.canChildScrollUp();
  }
}

然后在显示包含 ListView 或 GridView 布局的 SwipeRefreshLayout 的类中,您可以执行以下操作:

mSwipeLayout.setOnChildScrollUpListener(new OnChildScrollUpListener() {
  @Override
  public boolean canChildScrollUp() {
    return mListView.getFirstVisiblePosition() > 0 || 
           mListView.getChildAt(0) == null || 
           mListView.getChildAt(0).getTop() < 0;
  }
});
于 2014-10-22T22:18:00.117 回答
6

只需创建一个扩展 SwipeRefreshLayout覆盖该方法的类canChildScrollUp()。当您想要向下滚动控件时返回 true。

例如对于滚动视图,你可以试试这个,

@override.
boolean canChildScrollUp()
{
   //your condition to check scrollview reached at top while scrolling
   if(scrollview.getScrollY() == 0.0)
      return true;
   else
      return false;
}
于 2014-04-23T06:50:44.187 回答
5

正如其他人已经说过的那样,如果您没有将可滚动视图(即列表视图)作为 SwipeRefreshLayout 的直接子级,则库存 canChildScrollUp 将不起作用。

与 SwipeRefreshLayout 用于检查子视图滚动能力的简单逻辑有关。

我在 ActionbarActivity 中使用 ListView,并且希望在我的列表视图为空时包含一个空视图。这会导致问题,因为 SwipeRefreshLayout 类只能有一个子级。请注意,它还会检查此子项的向上滚动能力,以确定下拉项是否导致子项向上滚动,或者是否导致子项内容刷新。

因此,如果您想使用与 SwipeRefreshLayout 相同的逻辑,只需扩展该类,并创建一个方法以允许您将句柄传递给可滚动视图。请注意,股票实现使用 canScrollVertically() 完全符合我们的要求,但仅出现在 SDK >= 14 中。

也不要忘记在扩展类时包含包含参数“AttributeSet”的构造函数,否则在布局文件中使用该类会遇到问题。

因此,在包含列表视图的 Activity 的 onCreate 方法(在我的情况下,它是一个 ActionBarActivity)中,只需调用 setMyScrollableView 传入您的 ListView 或您使用的任何滚动视图。

/*Constructor*/
public MySwipeRefreshLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
}


 View mMyScrollableView = null;  //The content that get's pulled down.
 /*Method used to pass in my scrollable view*/
 public void setMyScrollableView(View view){
    mMyScrollableView = view;
 }

/**
 * @return Whether it is possible for the child view of this layout to
 * scroll up.  This was taken for the most part directly from SwipeRefreshLayout
 */
public boolean canChildScrollUp() {
    if(mMyScrollableView == null)
      return false;
    if (android.os.Build.VERSION.SDK_INT < 14) {
        if (mMyScrollableView instanceof AbsListView) {
            final AbsListView absListView = (AbsListView) mMyScrollableView;
            return absListView.getChildCount() > 0
        && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
        .getTop() < absListView.getPaddingTop());
        } else {
            return mMyScrollableView.getScrollY() > 0;
        }
    } else {
        return ViewCompat.canScrollVertically(mMyScrollableView, -1);
    }
}
于 2014-07-29T20:42:03.703 回答
3

@User22791 的解决方案完美运行,基于此,我在 github 上创建了一个可用的库,您可以使用(和修改)该库,以便开发人员更轻松地使用 swipeRefreshLayout。它在这里:https ://github.com/dagova/referencedSwipeRefreshLayout

基本上,您只需在布局中引用要在方法 canChildScrollUp 中检查的视图。我希望它会有用。

于 2014-05-29T09:56:29.610 回答
2

更简单的解决方案是使用onScrollListener并检查用户是否可以看到 firstElement。

someView.setOnScrollListener(new AbsListView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(AbsListView absListView, int scrollState) {
        if (scrollState == SCROLL_STATE_IDLE) {
            if (isViewAtTop()) {
                swipeLayout.setEnabled(true);
            } else {
                swipeLayout.setEnabled(false);
            }
        }

    }

    @Override
    public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if (firstVisibleItem == 0) {
            swipeLayout.setEnabled(true);
        } else {
            swipeLayout.setEnabled(false);
        }
    }
});

其中方法 isViewAtTop() 是其他一些方法,用于检查此视图是否滚动到顶部

于 2014-07-25T09:30:07.467 回答
2

我还发现其他答案不太奏效。

我花了一些时间才弄清楚他们使用的方法getScrollY()正如这个答案所解释的那样,是一种View描述它在容器内滚动多远的方法,而不是描述你的 Scroll 容器滚动了多少的方法。

如果您使用与其他答案相同的技术(覆盖该canChildScrollUp()方法),您可以轻松检查 Scrollable 是否处于最高点:

@Override
public boolean canChildScrollUp() {
    return !isListAtTop();
}

private boolean isListAtTop()   {   
    if(mGridView.getChildCount() == 0) return true;
    return mGridView.getChildAt(0).getTop() == 0;
}

(如您所见,我使用的是 a GridView,但您也可以使用 a ListView

于 2014-07-03T13:46:31.700 回答
1

好的,我已经开始工作了。如果SwipeRefreshLayout是布局的根并且ScrollView位于层次结构的深处(我把ScrollView里面放了 a RelativeLayout)而不是 的直接子级SwipeRefreshLayout,它不会检测到ScrollView正确的向上滑动。

您应该创建一个自定义类来扩展SwipeRefreshLayout和覆盖canChildScrollUp()方法SwipRefreshLayout

这是一个例子:

 public class CustomSwipeRefreshLayout extends SwipeRefreshLayout {

    private ScrollView scrollview;

    public CustomSwipeRefreshLayout(Context context) {
        super(context);
    }

    public CustomSwipeRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setView(ScrollView view) {
        this.scrollview = view;
    }

    @Override
    public boolean canChildScrollUp() {
        return scrollview.getScrollY() != 0;
    }

}
于 2014-05-15T13:17:17.780 回答