Как прокручивать recyclerView автоматически / периодически, используя Runnable и логические флаги - PullRequest
0 голосов
/ 03 ноября 2018

Я столкнулся с довольно сложной ситуацией, когда мне нужно автоматически и периодически прокручивать 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 голосов
/ 05 ноября 2018

Поработав головой в течение дня, я понял, как это сделать. Для тех, кто может быть в такой ситуации,

Ну, во-первых, я использовал LocalBroadCastManager, Handler и пару флагов в моем EventListener, чтобы добиться этого.

Какой-то код,

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

        });

ура :) 1026 *

...