Основное действие моего приложения имеет настраиваемый список, и каждый элемент списка должен отображать связанную с ним кнопку действия при левом смахивании и скрывать эту кнопку, когда тот же элемент списка снова смахивается вправо. Теперь я пытаюсь обнаружить события смахивания для каждого элемента списка, создав класс детектора смахивания и затем установив его в качестве прослушивателя касаний для элемента списка в классе ItemHolder.

Однако из-за возможности прокрутки RecyclerView прокрутка отдельных элементов списка остается незамеченной. Как определить смахивание по отдельным элементам списка?

MainActivity - onCreate ()

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main_recycler);

    ArrayList<Subject> subjects = new ArrayList<>();

    subjects.add(new Subject(1, "Physics"));
    subjects.add(new Subject(2, "Chemistry"));
    subjects.add(new Subject(3, "Biology"));

    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.subject_recycler_list_view);
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
    SubjectRecyclerListAdapter adapter = new SubjectRecyclerListAdapter(getApplicationContext(), R.layout.row_layout , subjects);

    recyclerView.setAdapter(adapter);
    recyclerView.setLayoutManager(layoutManager);
}

SwipeDetector

public class SwipeDetector implements View.OnTouchListener {
    static final int MIN_DISTANCE = 50;
    private float downX, downY, upX, upY;

    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                downX = event.getX();
                downY = event.getY();
                //   return true;
            }
            case MotionEvent.ACTION_UP: {
                upX = event.getX();
                upY = event.getY();

                float deltaX = downX - upX;
                float deltaY = downY - upY;

                // swipe horizontal?
                if ( Math.abs(deltaX) > MIN_DISTANCE){
                    // left or right
                    if ( deltaX < 0){
                        Log.i("Swipe Detector","LeftToRightSwipe!");
                        return true;
                    }
                    if ( deltaX > 0){
                        Log.i("Swipe Detector","RightToLeftSwipe!");
                        return true;
                    }
                } else{
                    Log.i("Swipe Detector","Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
                }
            }
        }

        return false;
    }
}

itemHolder - Конструктор

public SubjectHolder(Context context, View itemView) {
    super(itemView);

    this.subjectTextView = (TextView) itemView.findViewById(R.id.name);

    SwipeDetector swipeDetector = new SwipeDetector();
    itemView.setOnTouchListener(swipeDetector);
}

Обнаружение смахивания работает для любого другого представления, кроме элементов списка RecyclerView (или дочерних элементов любого другого прокручиваемого представления). Как определить смахивание по элементам списка?

3
Shashank 7 Май 2018 в 06:09

1 ответ

Лучший ответ

Проблема решена, но я не знаю, правильный ли это способ, но он определенно работает. Вот как это происходит -

Создайте интерфейс SwipeActions с двумя методами, которые будут использоваться для обратных вызовов при смахивании влево и вправо.

SwipeActions

public interface SwipeActions {
    public void onLeftSwipe(MotionEvent e);
    public void onRightSwipe(MotionEvent e);
}

Затем упомяните SwipeAction как одно из свойств SwipeDetector , а затем инициализируйте его в конструкторе.

public class SwipeDetector implements View.OnTouchListener {
    static final int MIN_DISTANCE = 50;
    private float downX, downY, upX, upY;
    public SwipeActions swipeActions;

    public SwipeDetector(SwipeActions swipeActions) {
        this.swipeActions = swipeActions;
    }

    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                downX = event.getX();
                downY = event.getY();
            }
            case MotionEvent.ACTION_UP: {
                upX = event.getX();
                upY = event.getY();

                float deltaX = downX - upX;
                float deltaY = downY - upY;

                if ( Math.abs(deltaX) > MIN_DISTANCE){
                    if ( deltaX < 0){
                        swipeActions.onRightSwipe(event);
                        return true;
                    }
                    if ( deltaX > 0){
                        swipeActions.onLeftSwipe(event);
                        return true;
                    }
                } else{
                    Log.i("Swipe Detector","Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
                }
            }
        }

        return false;
    }
}

Действия смахивания принимают объект MotionEvent в качестве параметра, который будет использоваться в MainActivity для получения объекта дочернего представления, на котором выполняется смахивание. выполнено. Так что измените MainActivity на это -

MainActivity - onCreate

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main_recycler);

    ArrayList<Subject> subjects = new ArrayList<>();

    subjects.add(new Subject(1, "Physics"));
    subjects.add(new Subject(2, "Chemistry"));
    subjects.add(new Subject(3, "Biology"));

    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.subject_recycler_list_view);

    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
    SubjectRecyclerListAdapter adapter = new SubjectRecyclerListAdapter(getApplicationContext(), R.layout.row_layout , subjects);
    SwipeDetector swipeDetector = new SwipeDetector(new SwipeActions() {
        @Override
        public void onLeftSwipe(MotionEvent evnt) {
            View childView = recyclerView.findChildViewUnder(evnt.getX(), evnt.getY());
            if(childView != null) {
                // Perform your action on childView (Swiped List Item)
            }
            else {
                Log.i("Main Recycler Activity", "Child View is Null");
            }
        }

        @Override
        public void onRightSwipe(MotionEvent evnt) {
            View childView = recyclerView.findChildViewUnder(evnt.getX(), evnt.getY());
            if(childView != null) {
                if(swipedViews.contains(childView)) {
                    // Perform your action on childView (Swiped List Item)
                }
            }
            else {
                Log.i("Main Recycler Activity", "Child View is Null");
            }
        }
    });

    recyclerView.setOnTouchListener(swipeDetector);
    recyclerView.setAdapter(adapter);
    recyclerView.setLayoutManager(layoutManager);
}

Кроме того, я удалил TouchListener из itemHolder

itemHolder - Конструктор

public SubjectHolder(Context context, View itemView) {
    super(itemView);

    this.subjectTextView = (TextView) itemView.findViewById(R.id.name);
}
0
Shashank 8 Май 2018 в 05:45