SwipeRefreshLayout with multiple ListViews

I have a fairly complex structure with FrameLayoutcontaining 2 LinearLayout(only one is displayed at a time).

One of them LinearLayoutrequires updating to update.

So my XML layout looks something like this:

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

I want to be able to retrieve-update as a whole LinearLayout, so my idea was to wrap it all up with SwipeRefreshLayout. But pulling TextViewnow does not work, and sometimes the behavior is really strange (I see a bubble, but it disappears immediately).

Only if I pull on one of ListViews does the item work as intended.

I even tried to import MultiSwiperefreshLayout(from here ) and install:

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

- , Refreshlayout , , ?

+4
1

! . :

<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 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 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() → > canChildScrollUp (MotionEvent ev), : canChildScrollUp. - google sammple refrence.

, ListView ScrollView TextView . , ListView SwipeRefreshLayout.

, .

0

Source: https://habr.com/ru/post/1584519/