Вложенный RecyclerView onClick не срабатывает

У меня есть два вложенных RecyclerViews - в основном список горизонтальных RecyclerViews, и я изо всех сил пытаюсь сделать элементы в горизонтальном RecyclerView кликабельными.

Это основной макет

<?xml version = "1.0" encoding = "utf-8"?>
<LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
              android:layout_width = "match_parent"
              android:layout_height = "match_parent"
              android:orientation = "vertical">

    <androidx.recyclerview.widget.RecyclerView
        android:id = "@+id/overview_list"
        android:visibility = "gone"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content"/>

    <components.emptyView.EmptyView
        android:id = "@+id/empty_state"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content"
        android:layout_marginTop = "32dp"/>
</LinearLayout>

Затем RecyclerView имеет следующий макет элемента:

<?xml version = "1.0" encoding = "utf-8"?>
<androidx.recyclerview.widget.RecyclerView android:id = "@+id/tables"
                                           xmlns:android = "http://schemas.android.com/apk/res/android"
                                           android:layout_width = "match_parent"
                                           android:layout_height = "wrap_content"
                                           android:layout_marginBottom = "8dp"
                                           android:layout_marginTop = "8dp"
                                           android:clipToPadding = "false"
                                           android:paddingEnd = "18dp"
                                           android:paddingStart = "18dp"/>

И я пытаюсь получить настройку onclick в адаптере для внутреннего RecyclerView следующим образом:

@Override
    public void onBindViewHolder(@NonNull LeagueTableViewHolder holder, int position) {
        Pair<Long, String> table = tables.get(position);
        holder.bindTable(table.first, table.second);
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // click event here
            }
        });
    }

Я попытался сделать представление элемента ViewHolder программно и в XML доступным для кликов, и, похоже, это не имеет значения. То же самое для внутреннего RecyclerView.

Любая идея, что я делаю неправильно?

Обновлено: добавлен родительский адаптер RecyclerView

public class OverviewListAdapter extends RecyclerView.Adapter<BaseViewHolder> {
    public final static int TEAM_PICTURE = 0;
    public final static int FIXTURES = 1;
    public final static int LEAGUE_TABLES = 2;
    public final static int LATEST_NEWS = 3;
    public final static int LATEST_EVENTS = 4;
    private final RecyclerView.RecycledViewPool viewPool;

    private List<BaseOverviewItemVM> viewModels = new ArrayList<>();
    private int tint;

    private OverviewLatestNewsVM newsVM;
    private OverviewLatestEventsVM eventsVM;
    private OverviewTablesVM tablesVM;
    private OverviewFixturesVM fixturesVM;
    private OverviewTeamPicVM teamPicVM;


    OverviewListAdapter(int tint) {
        this.tint = tint;
        viewPool = new RecyclerView.RecycledViewPool();
    }

    void addViewModel(OverviewLatestNewsVM viewModel){
        if (newsVM == null){
            newsVM = viewModel;
            viewModels.add(newsVM);
            sort();
            int viewModelIndex = viewModels.indexOf(newsVM);
            notifyItemInsertedIfValid(viewModelIndex);
        } else {
            int currentNewsIndex = viewModels.indexOf(newsVM);
            newsVM = viewModel;
            if (currentNewsIndex >= 0) {
                this.viewModels.set(currentNewsIndex, newsVM);
            }
            notifyItemChangedIfValid(currentNewsIndex);
        }
    }

    void addViewModel(OverviewLatestEventsVM viewModel){
        if (eventsVM == null){
            eventsVM = viewModel;
            viewModels.add(eventsVM);
            sort();
            int viewModelIndex = viewModels.indexOf(eventsVM);
            notifyItemChangedIfValid(viewModelIndex);
        } else {
            int currentIndex = viewModels.indexOf(eventsVM);
            eventsVM = viewModel;
            if (currentIndex >= 0) {
                this.viewModels.set(currentIndex, eventsVM);
            }
            notifyItemChangedIfValid(currentIndex);
        }
    }

    void addViewModel(OverviewFixturesVM viewModel){
        if (fixturesVM == null){
            fixturesVM = viewModel;
            viewModels.add(fixturesVM);
            sort();
            int viewModelIndex = viewModels.indexOf(fixturesVM);
            notifyItemChangedIfValid(viewModelIndex);
        } else {
            int currentIndex = viewModels.indexOf(fixturesVM);
            fixturesVM = viewModel;
            if (currentIndex >= 0) {
                this.viewModels.set(currentIndex, fixturesVM);
            }
            notifyItemChangedIfValid(currentIndex);
        }
    }

    void addViewModel(OverviewTablesVM viewModel){
        if (tablesVM == null){
            tablesVM = viewModel;
            viewModels.add(tablesVM);
            sort();
            int viewModelIndex = viewModels.indexOf(tablesVM);
            notifyItemChangedIfValid(viewModelIndex);
        } else {
            int currentIndex = viewModels.indexOf(tablesVM);
            tablesVM = viewModel;
            if (currentIndex >= 0) {
                this.viewModels.set(currentIndex, tablesVM);
            }
            notifyItemChangedIfValid(currentIndex);
        }
    }

    void addViewModel(OverviewTeamPicVM viewModel){
        if (teamPicVM == null){
            teamPicVM = viewModel;
            viewModels.add(teamPicVM);
            sort();
            int viewModelIndex = viewModels.indexOf(teamPicVM);
            notifyItemChangedIfValid(viewModelIndex);
        } else {
            int currentIndex = viewModels.indexOf(teamPicVM);
            teamPicVM = viewModel;
            if (currentIndex >= 0) {
                this.viewModels.set(currentIndex, teamPicVM);
            }
            notifyItemChangedIfValid(currentIndex);
        }
    }

    private void sort(){
        // sort by the item type defined at the top of this class
        Collections.sort(viewModels, (o1, o2) -> {
            if (o1.getType() > o2.getType()){
                return 1;
            } else if (o1.getType() < o2.getType()){
                return -1;
            }
            return 0;
        });
    }

    private void notifyItemInsertedIfValid(int index){
        if (index >= 0 && index < getItemCount()){
            notifyItemInserted(index);
        } else {
            notifyDataSetChanged();
        }
    }

    private void notifyItemChangedIfValid(int index){
        if (index >= 0 && index < getItemCount()){
            notifyItemChanged(index);
        } else {
            notifyDataSetChanged();
        }
    }

    @NonNull
    @Override
    public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        switch (viewType){
            case FIXTURES:
                View fixturesView = inflater.inflate(R.layout.row_overview_fixtures, parent, false);
                OverviewFixturesVH fixturesHolder = new OverviewFixturesVH(fixturesView);
                fixturesHolder.fixturesOverview.setRecycledViewPool(viewPool);
                return fixturesHolder;
            case LEAGUE_TABLES:
                View tablesView = inflater.inflate(R.layout.row_overview_league_tables, parent, false);
                OverviewTablesVH tablesHolder = new OverviewTablesVH(tablesView);
                tablesHolder.tablesList.setRecycledViewPool(viewPool);
                return tablesHolder;
            case LATEST_EVENTS:
                View upcomingEvents = inflater.inflate(R.layout.row_latest_list_view, parent, false);
                return new OverviewLatestEventsVH(upcomingEvents, tint);
            case TEAM_PICTURE:
                View teamPicView = inflater.inflate(R.layout.row_overview_team_pic, parent, false);
                return new OverviewTeamPicVH(teamPicView);
            default:
                View latestNewsView = inflater.inflate(R.layout.row_latest_list_view, parent, false);
                return new OverviewLatestNewsVH(latestNewsView, tint);
        }
    }

    @Override
    public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
        if (holder instanceof  OverviewFixturesVH) {
            Optional<BaseOverviewItemVM> fixturesVM = getViewModelOfType(FIXTURES);
            fixturesVM.ifPresent(viewModel -> ((OverviewFixturesVH) holder).setFixtures(((OverviewFixturesVM)viewModel).getFixtures()));
        } else if (holder instanceof OverviewTablesVH) {
            Optional<BaseOverviewItemVM> tablesVM = getViewModelOfType(LEAGUE_TABLES);
            tablesVM.ifPresent(vm -> ((OverviewTablesVH) holder).setTableIds(((OverviewTablesVM) vm).getTableIds()));
        } else if (holder instanceof OverviewLatestEventsVH){
            Optional<BaseOverviewItemVM> eventsVM = getViewModelOfType(LATEST_EVENTS);
            eventsVM.ifPresent(vm -> ((OverviewLatestEventsVH) holder).setEvents(((OverviewLatestEventsVM) vm).getEvents()));
        } else if (holder instanceof OverviewLatestNewsVH){
            Optional<BaseOverviewItemVM> newsVM = getViewModelOfType(LATEST_NEWS);
            newsVM.ifPresent(vm -> ((OverviewLatestNewsVH) holder).setNews(((OverviewLatestNewsVM) vm).getNews()));
        } else if (holder instanceof OverviewTeamPicVH){
            Optional<BaseOverviewItemVM> teamPicVM = getViewModelOfType(TEAM_PICTURE);
            teamPicVM.ifPresent(vm -> ((OverviewTeamPicVH) holder).setPictureUrl(((OverviewTeamPicVM) vm).getTeamPicUrl()));
        }
    }

    @Override
    public int getItemViewType(int position) {
        return viewModels.get(position).getType();
    }

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

    private Optional<BaseOverviewItemVM> getViewModelOfType(int type){
        if (viewModels != null ) {
            for (BaseOverviewItemVM viewModel : viewModels) {
                if (viewModel.getType() == type){
                    return Optional.of(viewModel);
                }
            }
        }
        return Optional.empty();
    }
}

попробуйте поместить свой основной макет во вложенный прокрутку

Vivek Mishra 02.04.2019 12:04

Можете ли вы включить код адаптера вашего родительского recyclerview?

MD Naseem Ashraf 02.04.2019 12:06

Использование NestedScrollView не сработало :(

Tudor S. 02.04.2019 12:07

@MDNaseemAhraf добавил это, спасибо

Tudor S. 02.04.2019 12:11

@ТюдорС. проверить это

Malik Motani 02.04.2019 13:43
3
5
1 314
1

Ответы 1

Я думаю, вы сможете справиться с этим, создав слушателя и обработав с ним вызов:

public interface clickListenerItem {
        void onItemClick(Item element);
    } 

добавьте этот интерфейс в свой adapter и в свой main.

Добавление этой функции в ваш *nameclass*ViewHolder extends RecyclerView.ViewHolder :

 public void bind(final ItemName item, final clickListenerItem listener) {
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override public void onClick(View v) {
                    listener.onItemClick(item);
                }
            });
        }

затем добавьте в свои переменные адаптера: private final clickListenerItem clickItem;

в вашем конструкторе: this.clickItem = clickItem;

и в onBindViewHolder вашего вызова адаптера:

public void onBindViewHolder(final @NonNull ItemViewHolder holder, int position) {
holder.bind(list.get(position), clickItem);
}

теперь при инициализации вашего адаптера в основном вы просто добавляете своего слушателя, добавляя его с помощью такого вызова:

adapter = new ItemAdapter(this, list, (new ItemAdapter.clickListenerItem(){
            @Override public void onItemClick(Item thisItem) {
                Toast.makeText(getApplicationContext(), "Loading Item...", Toast.LENGTH_LONG).show();
                Intent viewElem = new Intent(getApplicationContext(), ViewItem.class);
                startActivityForResult(viewElem ,codeForResult);
  }
        }));

Я надеюсь, что это поможет вам, очевидно, вы можете изменить последнюю часть, чтобы не вызывать новое действие, а изменить его с тем, что вы хотите видеть или делать с вашим элементом.

Другие вопросы по теме