带有多个ListView的SwipeRefreshLayout

时间:2015-04-24 15:10:49

标签: android android-layout listview swiperefreshlayout

我有一个非常复杂的结构,FrameLayout包含2 LinearLayout s(一次只显示一个)。

其中一个LinearLayout需要拉动刷新。

所以我的布局XML看起来像这样:

<FrameLayout>
    [...]
    <SwipeRefreshLayout>
        <LinearLayout>
            <TextView/>
            <TextView/>
            <ListView/>
            <TextView/>
            <ListView/>
        </LinearLayout>
    </SwipeRefreshLayout>
</FrameLayout>

我希望能够在整个Linearlayout上进行快速刷新,这就是为什么我的想法是用SwipeRefreshLayout来包装它。但是拉上TextView s现在不起作用,有时行为真的很奇怪(我看到泡沫但它会立即消失)。

只有当我拉上其中一个ListView时,事情就会按预期运作。

我甚至尝试导入MultiSwiperefreshLayout(来自here)并设置:

swipeLayout.setSwipeableChildren(R.id.xxx); // Id of my linearlayout

您是否知道如何使Refreshlayout包裹像我一样的复杂布局并在那里正常工作?

1 个答案:

答案 0 :(得分:0)

我解决了! 我遇到了同样的问题,并解决了它。 我的问题如下:

<MultiSwipeRefreshLayout>
    <LinearLayout>
        <RelativeLayout>
            <ListView  @+id/list_1 />
            <TextView  @+id/list_1_empty_view />
        </RelativeLayout>

        <RelativeLayout>
            <ListView  @+id/list_2 />
            <TextView  @+id/list_2_empty_view />
        </RelativeLayout>
    </LinearLayout>
</MultiSwipeRefreshLayout>

我决定参考:https://developer.android.com/samples/SwipeRefreshMultipleViews/index.html

在这个例子的思想背后,我重写了SwipeRefreshLayout,点亮了差异。

1)首先,我新增了一个MultiSwipeRefreshLayout.java类,因为我的modificine,除了扩展SwipeRefreshLayout类之外,我必须这样做;

2)其次,我将SwipeRefreshLayout.java的所有内容复制到MultiSwipeRefreshLayout.java,并在下面添加以下代码:

private View[] mSwipeableChildren;

/**
 * 记录子视图中是否有控件可以上滑的;该值在每次的ACTION_DOWN时计算一次。
 */
private boolean canChildScrollUp = true;
/**
 * Set the children which can trigger a refresh by swiping down when they are visible. These
 * views need to be a descendant of this view.
 */
public void setSwipeableChildren(final int... ids) {
    assert ids != null;

    // Iterate through the ids and find the Views
    mSwipeableChildren = new View[ids.length];
    for (int i = 0; i < ids.length; i++) {
        mSwipeableChildren[i] = findViewById(ids[i]);
    }
}
/**
 * This method controls when the swipe-to-refresh gesture is triggered. By returning false here
 * we are signifying that the view is in a state where a refresh gesture can start.
 *
 * <p>As {@link android.support.v4.widget.SwipeRefreshLayout} only supports one direct child by
 * default, we need to manually iterate through our swipeable children to see if any are in a
 * state to trigger the gesture. If so we return false to start the gesture.
 */
public boolean canChildScrollUp(MotionEvent ev) {
    if (mSwipeableChildren != null && mSwipeableChildren.length > 0
            && ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
        // Iterate through the scrollable children and check if any of them can not scroll up
        // 找到那个能接受到 ev 的控件
        View target = null;
        for (View view : mSwipeableChildren) {
            if (view != null && view.isShown() && isInViewRect(ev, view)) {
                target = view;
            }
        }

        // 当前接受滑动事件的ListView是否可以向上滑动
        if (target != null && canViewScrollUp(target) ) {
            canChildScrollUp = true;
        }else{
            canChildScrollUp = false;
        }
    }
    return canChildScrollUp;
}

/**
 * 判断点击事件是否在目标控件内
 * @param ev
 * @param view
 * @return
 */
private static boolean isInViewRect(MotionEvent ev, View view){
    //计算View的坐标
    int location[] = new int[2];
    view.getLocationOnScreen(location);
    RectF viewRectF = new RectF(
            location[0], location[1],
            location[0]+view.getWidth(), location[1] + view.getHeight()
    );

    float xOnScreen = ev.getRawX();
    float yOnScreen = ev.getRawY();

    return viewRectF.contains(xOnScreen, yOnScreen);
}

/**
 * Utility method to check whether a {@link View} can scroll up from it's current position.
 * Handles platform version differences, providing backwards compatible functionality where
 * needed.
 */
private static boolean canViewScrollUp(View view) {
    if (android.os.Build.VERSION.SDK_INT >= 14) {
        // For ICS and above we can call canScrollVertically() to determine this
        return ViewCompat.canScrollVertically(view, -1);
    } else {
        if (view instanceof AbsListView) {
            // Pre-ICS we need to manually check the first visible item and the child view's top
            // value
            final AbsListView listView = (AbsListView) view;
            return listView.getChildCount() > 0 &&
                    (listView.getFirstVisiblePosition() > 0
                            || listView.getChildAt(0).getTop() < listView.getPaddingTop());
        } else {
            // For all other view types we just check the getScrollY() value
            return view.getScrollY() > 0;
        }
    }
}

更改原始方法:canChildScrollUp() - &gt;&gt; canChildScrollUp(MotionEvent ev), 并添加一个字段:canChildScrollUp。其余内容与上面的google sammple相同。

好的,然后我们可以添加多个ListView或ScrollView或TextView或其他widget.I意味着我们可以在SwipeRefreshLayout中包含多个ListView。

我是中国人,为了上帝的缘故,原谅我的英语水平。