Android RecyclerView里面的NestedScrollView水平滚动很难做到

时间:2018-06-04 05:00:06

标签: android android-recyclerview nestedscrollview

我有nestedScrollViewrecyclerViews,其中linearLayoutManager(HORIZONTAL)将使用nestedScrollingEnabled(false)

它与nestedScrollingEnabled一起正常,但水平滚动很难做到。

如果我想向右滚动一个recyclerView,我必须完全停止向下滚动nestedScrollView,然后向右滚动。

horizontal recyclerViews设置为true只会禁用nestedScrollView的fling。

如何让<div *ngFor="let project of projects"> <div *ngIf="project.id === triggerProjectIdRefresh()"> <div *ngFor="let dashboard of project.dashboards; trackBy: dashboardTrack()"> <div *ngIf="dashboard.id === triggerDashboardIdRefresh()" > <!--bottom toolbar--> <!-- Tab system --> <p-tabView id="tabView" [controlClose]="true" (onChange)="setActiveTabDeleteable()" (onClose)="deleteConfirmation(sheet.id)" class="tabGroup" orientation="bottom"> <div *ngFor="let sheet of dashboard.sheets; trackBy: trackSheet()" > <!-- alluser sheets --> <p-tabPanel (mousedown)="tabId(sheet.id)" [header]="sheet.name" *ngIf="sheet.type === 'enduser'" > <!--tabbody--> <p-card class="middlecardSheet"> <!-- widget field is child of tab--> <app-display-widgets style="{border: #7A7A7A 2em solid;}" *ngIf="sheet.id === refreshCurrentSheet()" [dashboardID]="dashboard.id"></app-display-widgets> </p-card> </p-tabPanel> ... 滚动感觉更轻松?

3 个答案:

答案 0 :(得分:3)

真的很感激你的问题,如果你不知道的话,这是非常典型的。 这是一个解决方案。

魔术方法是requestDisallowInterceptTouchEvent,此方法可以允许或拒绝触摸事件。

public static void smartScroll(final ScrollView scrollView, final RecyclerView recyclerView) {
    recyclerView.setOnTouchListener(new View.OnTouchListener() {
        private boolean isListOnTop = false, isListOnBottom = false;
        private float delta = 0, oldY = 0;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    scrollView.requestDisallowInterceptTouchEvent(true);
                    recyclerView.requestDisallowInterceptTouchEvent(false);
                    oldY = event.getY();
                    break;
                case MotionEvent.ACTION_UP:
                    delta = 0;
                    break;
                case MotionEvent.ACTION_MOVE:
                    delta = event.getY() - oldY;
                    oldY = event.getY();

                    isListOnTop = false;
                    isListOnBottom = false;

                    View first = recyclerView.getChildAt(0);
                    View last = recyclerView.getChildAt(recyclerView.getChildCount() - 1);

                    LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
                    if (first != null && layoutManager.findFirstVisibleItemPosition() == 0 && first.getTop() == 0 && delta > 0.0f) {
                        isListOnTop = true;
                    }
                    if (last != null && layoutManager.findLastVisibleItemPosition() == recyclerView.getChildCount() - 1 && last.getBottom() <= recyclerView.getHeight() && delta < 0.0f) {
                        isListOnBottom = true;
                    }

                    if ((isListOnTop && delta > 0.0f) || (isListOnBottom && delta < 0.0f)) {
                        scrollView.requestDisallowInterceptTouchEvent(false);
                        recyclerView.requestDisallowInterceptTouchEvent(true);
                    }
                    break;
                default:
                    break;
            }
            return false;
        }
    });
}

此解决方案适用于ScrollView和RecyclerView,但您可以使用requestDisallowInterceptTouchEvent将其用于ViewPager,ScrollView,ListView等任何类型的视图。

答案 1 :(得分:0)

几个月前我也面临同样的问题,只有对我有用的解决方案是创建自己的自定义RecyclerView和NestedScrollView:

MeroHorizo​​ntalRecyclerView类

public class MeroHorizontalRecyclerView extends RecyclerView {

private GestureDetector mGestureDetector;

public MeroHorizontalRecyclerView(Context context) {
    super(context);
    init();
}

public MeroHorizontalRecyclerView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    init();
}

public MeroHorizontalRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
}

private void init() {
    LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
    layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
    setLayoutManager(layoutManager);

    mGestureDetector = new GestureDetector(getContext(), new VerticalScrollDetector());
}

@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
    if (mGestureDetector.onTouchEvent(e)) {
        return false;
    }
    return super.onInterceptTouchEvent(e);
}

public class VerticalScrollDetector extends
        GestureDetector.SimpleOnGestureListener {

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        return Math.abs(distanceY) > Math.abs(distanceX);
    }

}

}

MeroNestedScrollView类

public class MeroNestedScrollView extends NestedScrollView {

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

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

public MeroNestedScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}


private float xDistance, yDistance, lastX, lastY;

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    final float x = ev.getX();
    final float y = ev.getY();
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            xDistance = yDistance = 0f;
            lastX = ev.getX();
            lastY = ev.getY();

            // This is very important line that fixes
            computeScroll();


            break;
        case MotionEvent.ACTION_MOVE:
            final float curX = ev.getX();
            final float curY = ev.getY();
            xDistance += Math.abs(curX - lastX);
            yDistance += Math.abs(curY - lastY);
            lastX = curX;
            lastY = curY;

            if (xDistance > yDistance) {
                return false;
            }
    }


    return super.onInterceptTouchEvent(ev);
}

}

现在将它们导入xml中:

<com.hancha.utils.MeroNestedScrollView
        android:id="@+id/nestedScroll"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

  <com.hancha.utils.MeroHorizontalRecyclerView
                android:id="@+id/recycler_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/app_bg_color"/>

</com.hancha.utils.MeroNestedScrollView>

希望这有帮助!

答案 2 :(得分:-1)

请您试试以下示例或方式可能会对您有帮助。

myRecyclerViewHorizental.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false) {
            @Override
            public boolean canScrollHorizontally() {
                //return false if you don't want to scroll horizontal
                return true;
            }

            @Override
            public boolean canScrollVertically() {
                //return false if you don't want to scroll vertical
                return false;
            }
        });