Установка onClickListener на самом RecyclerView не на элементе - PullRequest
0 голосов
/ 26 июня 2018

Я хочу установить onClickListener в RecyclerView, не для его элементов . Поэтому, если пользователь нажимает на Recyclerview, он вызывает событие щелчка (даже если оно пустое RecyclerView или полно элементов).

  • Я использую MVVM.
  • Я пытался mRecyclerView.setClickable (true), не работает;

Что я хотел

mRecyclerView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
        }
    });

Мой класс адаптера

public class TaskItemAdapter extends RecyclerView.Adapter<TaskItemAdapter.BaseItemAdapterViewHolder> {
private static final String TAG = TaskItemAdapter.class.getSimpleName();
private List<Task> mTaskList;
private View.OnLongClickListener mOnLongClickListener;

public TaskItemAdapter(List<Task> taskList, View.OnLongClickListener longClickListener) {
    mTaskList = taskList;
    mOnLongClickListener = longClickListener;
}

@NonNull
@Override
public BaseItemAdapterViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    if (parent instanceof RecyclerView) {
        int layoutId = R.layout.item_list_main;
        View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
        view.setFocusable(true);
        return new BaseItemAdapterViewHolder(view);

    } else {
        throw new RuntimeException(TAG + "Not bound to recyclerView");
    }
}

@Override
public void onBindViewHolder(@NonNull BaseItemAdapterViewHolder holder, int position) {
    Task task = mTaskList.get(position);
    holder.mItemTextView.setText("- " + task.getName());

    holder.itemView.setTag(task);
    holder.itemView.setOnLongClickListener(mOnLongClickListener);

}

@Override
public int getItemCount() {
    return mTaskList.size();
}

public void loadItems(List<Task> taskList) {
    mTaskList = taskList;
    notifyDataSetChanged();
}


public class BaseItemAdapterViewHolder extends RecyclerView.ViewHolder {
    @BindView(R.id.item_textView)
    TextView mItemTextView;

    public BaseItemAdapterViewHolder(View view) {
        super(view);
        ButterKnife.bind(this, view);

    }

}

}

Ответы [ 6 ]

0 голосов
/ 05 июля 2018

A RecyclerView не предоставляет функции обратного вызова OnClick по умолчанию. Таким образом, вы можете создать OnTouchListener для использования событий кликов.

public class RVClickHandler implements View.OnTouchListener {

    private RecyclerView mRecyclerView;
    private float mStartX;
    private float mStartY;

    public RVClickHandler(RecyclerView recyclerView) {
        mRecyclerView = recyclerView;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        boolean isConsumed = false;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                mStartX = event.getX();
                mStartY = event.getY();
                break;
            }
            case MotionEvent.ACTION_UP: {
                float endX = event.getX();
                float endY = event.getY();
                if(detectClick(mStartX, mStartY, endX, endY)) {
                    //Ideally it would never be called when a child View is clicked.
                    //I am not so sure about this.
                    View itemView = mRecyclerView.findChildViewUnder(endX, endY);
                    if(itemView == null) {
                        //RecyclerView clicked
                        mRecyclerView.performClick();
                        isConsumed = true;
                    }
                }
                break;
            }
        }
        return isConsumed;
    }

    private static boolean detectClick(float startX, float startY, float endX, float endY) {
        return Math.abs(startX-endX) < 3.0 && Math.abs(startY-endY) < 3.0;
    }

}

добавьте это к вашему RecyclerView следующим образом

recyclerView.setOnTouchListener(new RVClickHandler(recyclerView));

Теперь вы можете прикрепить обычный OnClickListener для обработки кликов.

recyclerView.setOnClickListener((v) -> {
    //Called when an empty space is clicked inside RecyclerView.
});

События кликов для дочерних представлений могут обрабатываться внутри ViewHolder

0 голосов
/ 04 июля 2018

Вместо добавления прослушивателя onClick в RecyclerView вы можете добавить View для адаптера View.

@Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.recycler_layout, parent, false);
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(mContext,"RecyclerView Clicked", Toast.LENGTH_SHORT).show();
            }
        });

        return new MyViewHolder(itemView);
    }
0 голосов
/ 02 июля 2018

Поскольку вы настраиваете фокус на представление «Адаптер» в onCreateView, ваш родительский объект (он же реселлер-просмотр не получит фокус, пока вы не установите правило фокусировки.) Вы можете попробовать

recycler.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
0 голосов
/ 29 июня 2018

Мне удается это сделать:

Я передаю два слушателя к адаптеру:

View.OnClickListener;
View.OnTouchListener;

В методе onCreateViewHolder Я устанавливаю двух слушателей и передаю recyclerViewID в тег.

int layoutId = R.layout.item_list_main;
View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
view.setFocusable(true);
parent.setOnTouchListener(mOnTouchListener);
view.setTag(R.id.PARENT_VIEW_ID, parent.getId());
view.setOnClickListener(mOnClickListener);
return new BaseItemAdapterViewHolder(view);

В основном виде деятельности:

  1. View.OnTouchListener работают в пустом пространстве реселлера. сам по себе.
  2. View.OnClickListener работают в пунктах recyclerView.
  3. И использовал слушатель пустого макета клика.

Так что теперь, независимо от того, что пользователь нажимает на recyclerView или его элемент, или его пустое состояние, он будет вызывать весь клик.

0 голосов
/ 29 июня 2018
mRecyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        return true;
    }
});

Тогда просто обработайте желаемый тип MotionEvent. Верните true, если вы не хотите, чтобы RecylerView делал с ним что-то еще.

0 голосов
/ 26 июня 2018

Из View.OnTouchListener onTouch () нажмите и отпустите событие. можно вызвать виды.

...