如何使用 Runnable 和布尔标志滚动 recyclerView automatically/periodically

How to scroll a recyclerView automatically/periodically using a Runnable and boolean flags

我面临着一个相当具有挑战性的情况,我需要根据 RecyclerView.

中触摸事件提供的标志自动并定期滚动 RecyclerView

我有 RecyclerView 个可折叠物品,可折叠物品在 ScrollView 中有一个 ImageView。我知道这是一个糟糕的实现,因为 ScrollView 不会如果 parent 也垂直滚动。

但由于我想要此功能,我想在 ScrollView 可见时禁用 RecyclerView 中的滚动以使其滚动。我为此定制了 LayoutManager 如下:

public class ConditionalScrollManager extends LinearLayoutManager {
    public ConditionalScrollManager(Context context) {
        super(context);
    }

    ConditionalScrollManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    @Override
    public boolean canScrollVertically() {
        return Adapter_Admin.canScroll && super.canScrollVertically();
    }
}

但是,这带来了一个问题,即无法完全看到屏幕底部的项目,因为单击项目后列表不可滚动。

标志 Adapter_Admin.canScroll 来自我的适配器:

canScroll = true;
        flAdmin.setOnClickListener(v -> {
            image = beanOrders.get(getLayoutPosition()).getsImage();
            message = beanOrders.get(getLayoutPosition()).getsMessage();

            scrollOne = true;
            scrollTo = getLayoutPosition();

            if (flAdmin.isFolded()) {
                flAdmin.unfoldWithAnimation();
                canScroll = false;
                Timer timer = new Timer();
                timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        canScroll = true;
                    }
                }, 0, 10);

            } else {
                flAdmin.foldWithAnimation();
                canScroll = true;
                scrollOne = false;
            }
        });

其中 boolean canScroll 是静态全局变量。我尝试添加 TimerTask 使 RecyclerView 可滚动 10 毫秒,这样滚动就可以发生在这里:

rvAdmin.addOnItemTouchListener(new TchListener(this, rvAdmin, new TchListener.ClickListener() {
        @Override
        public void onClick(View view, int position) {
            if (Adapter_Admin.canScroll)
                rvAdmin.scrollToPosition(position);
        }

        @Override
        public void onLongClick(View view, int position) {

        }
    }));

然后将标志恢复为 false,但它不起作用,我没有得到预期的效果。

TchListener 是处理触摸事件的自定义侦听器。

public class TchListener implements RecyclerView.OnItemTouchListener {
private ClickListener clicklistener;
private GestureDetector gestureDetector;

public TchListener(Context context, final RecyclerView recycleView, final ClickListener clicklistener) {

    this.clicklistener = clicklistener;
    gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return true;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            View child = recycleView.findChildViewUnder(e.getX(), e.getY());
            clicklistener.onLongClick(child, recycleView.getChildAdapterPosition(child));

        }
    });
}

@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
    View child = rv.findChildViewUnder(e.getX(), e.getY());
    if (child != null && clicklistener != null && gestureDetector.onTouchEvent(e)) {
        clicklistener.onClick(child, rv.getChildAdapterPosition(child));
    }

    return false;
}

@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {

}

@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

}

public interface ClickListener {
    void onClick(View view, int position);

    void onLongClick(View view, int position);
}}

绞尽脑汁想了一天,想出了办法。 对于可能处于这种情况的任何人,

好吧,首先我在 EventListener 中使用了 LocalBroadCastManagerHandler 和几个标志来实现 it.Oh 诀窍是 scrollToPositionWithOffset.

一些代码,

private BroadcastReceiver scrollReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        int scrollTo = intent.getIntExtra(ConstHelper.SCROLL_TO, 0);
        boolean scroll = intent.getBooleanExtra(ConstHelper.SMOOTH_SCROLL, false);

        if (scroll) {
            ((LinearLayoutManager) Objects.requireNonNull(rvAdmin
                    .getLayoutManager()))
                    .scrollToPositionWithOffset(scrollTo, 8);
        }
    }
};

这就是我 do.Send 滚动标志和滚动数量所需要的,BroadCastManager 为我完成了。

我只需要增加 RecyclerView paddingBottom 使其也滚动到最后一项。

哦,Handler 是将标志设置回 false 以在几秒后禁用滚动;

我的 ClickListener :

flAdmin.setOnClickListener((View v) -> {
            scrollTo = getLayoutPosition();

            image = beanOrders.get(getLayoutPosition()).getsImage();
            message = beanOrders.get(getLayoutPosition()).getsMessage();

            Intent intent = new Intent(ConstHelper.START_SCROLL);
            intent.putExtra(ConstHelper.SMOOTH_SCROLL, true);
            intent.putExtra(ConstHelper.SCROLL_TO, getLayoutPosition());
            LocalBroadcastManager.getInstance(itemView.getContext()).sendBroadcast(intent);

            if (flAdmin.isFolded()) {
                flAdmin.unfoldWithAnimation();
            } else {
                flAdmin.foldWithAnimation();
            }

            new Handler().postDelayed(() -> canScroll = false, 2000);

        });

干杯:)