简体   繁体   English

如何在片段中实现recyclerview onClick?

[英]How to do you implement a recyclerview onClick in a Fragment?

My question is similar to this one. 我的问题与此类似。

Best approach to communicate between Fragment/Activity and RecyclerView.Adapter? 在Fragment / Activity和RecyclerView.Adapter之间进行通信的最佳方法?

I know how to implement an onClickListener, an Interface and an OnItemSelected method in the corresponding activity when the user clicks on a button in a Fragment. 我知道当用户单击Fragment中的按钮时,如何在相应的活动中实现onClickListener,Interface和OnItemSelected方法。 I have a fragment with an array list. 我有一个带有数组列表的片段。 By clicking on each item in the array list in the fragment, an ExoPlayer will open in a new activity or a fragment. 通过单击片段中数组列表中的每个项目,ExoPlayer将在新活动或片段中打开。 As I understand it, onItemClickListener doesn't work with Recyclerview. 据我了解,onItemClickListener不适用于Recyclerview。 How do I set the onClick method to the items in the list? 如何将onClick方法设置为列表中的项目? Also, do I set onClick outside of RecyclerView? 另外,我是否在RecyclerView之外设置onClick? This is my RecyclerView adapter class. 这是我的RecyclerView适配器类。 Should the interface take additional parameters? 接口是否应该使用其他参数? Thank you in advance. 先感谢您。

public class StepsAdapter extends RecyclerView.Adapter { 公共类StepsAdapter扩展了RecyclerView.Adapter {

private static final String TAG = StepsAdapter.class.getSimpleName();
private ArrayList<Steps> stepsList = new ArrayList<Steps>();
private StepsAdapter.StepsAdapterOnClickHandler mClickHandler;

/**
 * The interface that receives onClick messages.
 */
public interface StepsAdapterOnClickHandler {
    void onClick(Steps stepClick);
}

/**
 * Creates a StepsAdapter.
 *
 * @param clickHandler The on-click handler for this adapter. This single handler is called
 *                     when an item is clicked.
 */
public StepsAdapter(StepsAdapterOnClickHandler clickHandler,ArrayList<Steps> stepsList) {
    mClickHandler = clickHandler;
    this.stepsList = stepsList;
}

/**
 * Cache of the children views for a steps list item.
 */
public class StepsAdapterViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    @BindView(R.id.step_short_desc)
    public TextView stepShortDescription;

    @BindView(R.id.step_description)
    public TextView stepDescription;

    public StepsAdapterViewHolder(View view) {
        super(view);
        ButterKnife.bind(this, view);
        view.setOnClickListener(this);
    }

    /**
     * This gets called by the child views during a click.
     *
     * @param v The View that was clicked
     */
    @Override
    public void onClick(View v) {
        int adapterPosition = getAdapterPosition();
        Steps stepClick = stepsList.get(adapterPosition);
        mClickHandler.onClick(stepClick);
    }
}

@Override
public StepsAdapter.StepsAdapterViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
    Context context = viewGroup.getContext();
    int layoutIdForListItem = R.layout.steps_list_item;
    LayoutInflater inflater = LayoutInflater.from(context);
    boolean shouldAttachToParentImmediately = false;
    View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
    return new StepsAdapter.StepsAdapterViewHolder(view);
}

@Override
public void onBindViewHolder(StepsAdapter.StepsAdapterViewHolder holder, int position) {

    //Binding data
    final Steps stepsView = stepsList.get(position);

    holder.stepShortDescription.setText(stepsView.getStepShortDescription());
    holder.stepDescription.setText(stepsView.getStepDescription());
}

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

public void setStepsList(ArrayList<Steps> mStepsList) {
    this.stepsList = mStepsList;
    notifyDataSetChanged();
}

} }

The corresponding fragment. 相应的片段。 Is the click method implemented correctly? click方法是否正确实施?

public class StepsListFragment extends Fragment implements StepsAdapter.StepsAdapterOnClickListener {

    // Tag for logging
    private final String TAG = StepsListFragment.class.getSimpleName();

    @BindView(R.id.recyclerview_steps)
    RecyclerView mRecyclerView;

    ArrayList<Steps> stepsArrayList;

    Recipes recipes;

    // Final Strings to store state information about the list of steps and list index
    public static final String STEPS_LIST_INDEX = "list_index";


    // Define a new interface OnStepsClickListener that triggers a callback in the host activity
    OnStepClickListener mCallback;

    // OnStepsClickListener interface, calls a method in the host activity named onStepSelected
    public interface OnStepClickListener {
        void onClick(Steps stepClick);
    }

    // Override onAttach to make sure that the container activity has implemented the callback
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

//        // This makes sure that the host activity has implemented the callback interface
//        // If not, it throws an exception
        try {
            mCallback = (OnStepClickListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString()
                    + " must implement OnStepSelectedListener");
        }
    }

   /**
     * Mandatory empty constructor for the fragment manager to instantiate the fragment
     */
    public StepsListFragment() {
    }

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

//        //Inflate the Steps fragment layout
        View rootView = inflater.inflate(R.layout.fragment_steps, container, false);
//        // Bind the views
        ButterKnife.bind(this, rootView);

        Bundle bundle = this.getArguments();
        if (bundle != null) {
            recipes = getArguments().getParcelable("Recipes");

            stepsArrayList = new ArrayList<>();
            stepsArrayList = recipes.getRecipeSteps();
        }
        if (savedInstanceState != null) {
            //Restore the fragment's state here
            stepsArrayList = savedInstanceState.getParcelableArrayList(STEPS_LIST_INDEX);
        }

        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getContext());
        mRecyclerView.setLayoutManager(mLayoutManager);
        Log.i("listSteps", stepsArrayList.size() + "");

        StepsAdapter stepsAdapter = new StepsAdapter(this, stepsArrayList);
        mRecyclerView.setAdapter(stepsAdapter);

        // Return the root view
        return rootView;
}

public void onClick(Steps stepClick){
        mCallback.onClick(stepClick);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveIn`enter code here`stanceState(outState);

        //Save the fragment's state here
        outState.putParcelableArrayList(STEPS_LIST_INDEX, stepsArrayList);
        super.onSaveInstanceState(outState);
    }  }

The best way to implement click function on each item of recyclerview is initialise onClickListener when the view is populated inside in the recyclerview viewholder. 在recyclerview Viewholder中填充视图时,在recyclerview的每个项目上实现点击功能的最佳方法是初始化onClickListener。 Then in the onClick method, use a custom interface/listener to catch the click activity in your parent fragment/activity. 然后在onClick方法中,使用自定义界面/监听器来捕获父片段/活动中的点击活动。

eg: create a custom interface like this; 例如:创建一个这样的自定义界面;

public interface RecyclerviewOnClickListener{
void recyclerviewClick(int position);
}

Now implement this interface in your parent activity/fragment containing the recyclerview. 现在,在包含recyclerview的父活动/片段中实现此接口。 Suppose your fragment name is ChatFragment. 假设您的片段名称是ChatFragment。 Then, 然后,

public class ChatFragment extends Fragment implements RecyclerviewOnClickListener{
.
.
}

This will implement the function onClick(int position) in your fragment. 这将在片段中实现onClick(int position)函数。 In your adapter constructor, you should create a field for the RecyclerviewOnClickListener. 在您的适配器构造函数中,您应该为RecyclerviewOnClickListener创建一个字段。 Suppose your adapter name is ChatAdapter, then 假设您的适配器名称是ChatAdapter,然后

Adapter Constructor. 适配器构造函数。

public ChatAdapter(RecyclerviewClickListener listener, .....<other params>){
this.listener = listener;
}

In your fragment, you can initialise your adapter like the following 在片段中,您可以像下面那样初始化适配器

ChatAdapter adapter = new ChatAdapter(this, <any additional params>);

You should pass the same instance of 'listener' to your viewholder also, and initialise the listener there also 您还应该将相同的“侦听器”实例传递给您的观看者,并在那里也初始化监听器

Now in your recyclerview ViewHolder, you can set view.setOnClickListener(new OnClickListener{ this.listener.recyclerviewClick(getAdapterPosition()) }); 现在,您可以在recyclerview ViewHolder中设置view.setOnClickListener(new OnClickListener{ this.listener.recyclerviewClick(getAdapterPosition()) });

The getAdapterPosition() function returns the position of the click in the recyclerview, which will get a callback in the recyclerviewClick() function in your fragment. getAdapterPosition()函数返回单击在recyclerview中的位置,这将在片段的recyclerviewClick()函数中获得回调。

About the number of parameter you are passing, you can use as much as you want, but for a click function in recyclerview, the ideal way is to use only one param which the position. 关于要传递的参数数量,可以根据需要使用任意数量,但是对于recyclerview中的click函数,理想的方法是仅使用该位置的一个参数。 Now you can modify the contents in the list that you are passing from your fragment to adapter and call notifyDataSetChanged() which will update the recyclerview. 现在,您可以修改从片段传递到适配器的列表中的内容,并调用notifyDataSetChanged()来更新recyclerview。 Hope it's clear. 希望清楚。

Try this inside OnBindviewHolder 在OnBindviewHolder中尝试一下

 holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
              //code here

        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM