【问题标题】:Handle recyclerview click in a fragment instead of holder class处理 recyclerview 点击片段而不是持有者类
【发布时间】:2016-10-05 08:24:48
【问题描述】:

我有一个显示RecyclerView 的片段。我目前在我的持有者类中处理onclick 事件,如下所示:

public class CategoryHolder extends RecyclerView.ViewHolder implements View.OnClickListener  {

    public ImageView categoryImageView;
    public TextView categoryNameTextView;
    public TextView categoryAmountTextView;
    ArrayList<Category> categoriesArrayList = new ArrayList<>();
    Context context;


    public CategoryHolder(View itemView, Context context, ArrayList<Category> categories) {
        super(itemView);
        this.categoriesArrayList = categories;
        this.context = context;

        itemView.setOnClickListener(this);
        this.categoryImageView = (ImageView) itemView.findViewById(R.id.categoryImageView);
        this.categoryNameTextView = (TextView) itemView.findViewById(R.id.categoryNameTextView);
        this.categoryAmountTextView = (TextView) itemView.findViewById(R.id.categoryAmountTextView);
    }


    @Override
    public void onClick(View v) {

        int position = getAdapterPosition();
        Category category = this.categoriesArrayList.get(position);
        Toast.makeText(context, ""+category.getCategoryName() + position, 


    }
}

如您所见,我在 holder 类中实现了 OnClickListener,然后在 Holder 中实现了 setTheOnItemClickListner。

在我的适配器中,我将带有如下数据的数组列表传递给持有者类:

 Context context;
    ArrayList<Category> categories;


    public CategoriesAdapter(Context context, ArrayList<Category> categories) {
        this.context = context;
        this.categories = categories;
    }

    @Override
    public CategoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.categorylist_singlecell, parent, false);
        CategoryHolder holder = new CategoryHolder(v, context, categories);
        return holder;
    }

我在创建新持有人时传递数据。

这很好用,我可以为ArrayList 中用于RecyclerView 的位置和任何数据敬酒。

我想做的是在我初始化 RecyclerView 和适配器的主要片段中使用它。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_nested_youtube_video_selection, container, false);

    //////////////////////////// CATEGORIES RECYCLER /////////////////////////////////////

    // Initialise the categories Recylerview
    LinearLayoutManager categoriesLayoutManger = new LinearLayoutManager(getActivity());
    categoriesLayoutManger.setOrientation(LinearLayoutManager.HORIZONTAL);
    categoriesRecyclerView = (RecyclerView) view.findViewById(R.id.youtubeAlarmCategoryRecyclerView);
    categoriesRecyclerView.setLayoutManager(categoriesLayoutManger);

    // Get the data for the categories RecyclerView
    categoryArraylist = CategoryCollection.getCategoryArrayList();

    // Initialse the categories RecyclerView Adapter
    categoriesAdapter = new CategoriesAdapter(getActivity(), categoryArraylist);

    // Bind the categories Adapter to the categories RecyclerView
    categoriesRecyclerView.setAdapter(categoriesAdapter);

我想我需要一个界面,但我不知道该怎么做,或者这是否是最好的方法。

【问题讨论】:

标签: java android android-fragments android-recyclerview onclicklistener


【解决方案1】:

以下应该可以工作:

  • 创建接口
  • 在您的片段中创建此接口的实例并将其传递给适配器
  • 让适配器将此接口传递给视图支架
  • 让视图持有者定义一个onClickListener,将事件传递到界面

这是一个例子:

界面

public interface ItemClickListener {

    void onItemClicked(ViewHolder vh, Object item, int pos);
}

public interface GenericItemClickListener<T, VH extends ViewHolder> {

    void onItemClicked(VH vh, T item, int pos);
}

ViewHolder

public class CategoryHolder extends RecyclerView.ViewHolder {

    public CategoryHolder(View itemView, Context context) {
        super(itemView);
        this.context = context;

        this.categoryImageView = (ImageView) itemView.findViewById(R.id.categoryImageView);
        this.categoryNameTextView = (TextView) itemView.findViewById(R.id.categoryNameTextView);
        this.categoryAmountTextView = (TextView) itemView.findViewById(R.id.categoryAmountTextView);
    }
}

适配器

Context context;
ArrayList<Category> categories;
ItemClickListener itemClickListener;

public CategoriesAdapter(Context context, ArrayList<Category> categories, ItemClickListener itemClickListener) {
    this.context = context;
    this.categories = categories;
    this.itemClickListener = itemClickListener;
}

// DON'T PASS YOUR DATA HERE, just create a ViewHolder
@Override
public CategoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.categorylist_singlecell, parent, false);
    CategoryHolder holder = new CategoryHolder(v, context);
    return holder;
}

//HERE you bind one item of your list to the view holder
@Override
public void onBindViewHolder(final CategoryHolder vh, final int i) {
    final Category category = categories.get(i);

    // set click listener
    vh.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            itemClickListener.onItemClicked(vh, category, i);
        }
    });

   // update images and texts...
}

编辑

更新了代码以向您展示,您不应该将一组项目传递给每个视图持有者...视图持有者被创建和重用,只更新 onBindViewHolder 中的视图持有者并将视图持有者实例绑定到那里的正确数据...

顺便说一句,我会做一个通用接口,这样更漂亮......我的例子只是一个简单的解决方案......

Edt 2 - 如何创建接口实例

ItemClickListener listener = new ItemClickListener(){
    @Override
    public void onItemClicked(RecyclerView.ViewHolder vh, Object item, int pos){
        Toast.makeText(getActivity(), "Item clicked: " + pos, Toast.LENGTH_SHORT).show();
    }
};

【讨论】:

  • 非常感谢您的帮助。似乎一切正常,直到我放入此行 itemClickListener.onItemClicked(holder, category, position);它说类别和持有者需要被宣布为最终的。如果值发生变化,这会导致问题吗?
  • 因为我想categoryi 不是最终版本。只需将它们设为final,它们也可以在内部类中使用
  • 我不确定如何创建接口实例并将其传递给适配器。即我如何在我的片段中接收 onclick。
  • 您可以删除onViewRecycled 中的点击侦听器... 但是RecyclerView 只会重用ViewHolder 并将它们重新绑定到新位置,因此点击侦听器也会更新
  • 一切都很好!谢谢。界面中的最后一件事是项目作为对象出现,我只需要将其转换回我的类别类型吗?
【解决方案2】:

抽象 YOURAdapter 类,然后添加类似的方法

void onLikeClicked(Object object, int position); void onItemClicked();

bindView 中调用它,就像

holder.btnLike.setOnclickListner(new OnClickListner){
onLikeClicked(list.get(position), position);
}

在活动类中 现在它会自动实现适配器的所有方法

YOURAdapter adapter=new YOURAdapter(){
    void onLikeClicked(Object object, int position){

    }
    void onItemClicked(){

    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-24
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多