如何使用Runnable和boolean标志自动/定期滚动recyclerView

时间:2018-11-03 09:56:09

标签: android android-recyclerview timertask

我面临一个相当具有挑战性的情况,我需要根据RecyclerView中触摸事件提供的标记自动并定期滚动RecyclerView

我有一个RecyclerView的可折叠物品,而可折叠的物品在ImageView内有一个ScrollView。这是一个很差的实现方式,因为我知道ScrollView不会垂直滚动如果父母也这样做的话。

但是,由于我需要此功能,因此我想到了在RecyclerView可见时禁止在ScrollView中滚动,以使其滚动。我为此做了一个自定义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);
}}

1 个答案:

答案 0 :(得分:0)

头呆了一天后,我想出了办法。 对于任何可能遇到这种情况的人,

首先,我在我的LocalBroadCastManager中使用了HandlerEventListener和几个标志来实现它。哦,诀窍是scrollToPositionWithOffset。 / p>

某些代码

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);
        }
    }
};

这就是我要做的。发送标志滚动并滚动滚动,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);

        });

欢呼:)