简体   繁体   中英

RecylerView onClick get position of item

I have a RecyclerView that holds a bunch of cards (fetches data from the web, then populates cards) . I have the cards forming properly after data is fetched, but now I would now like the set a listener for when each card is clicked. Ideally, after each card is clicked , a new intent will be called with further details about that card's data.

Here is where I initialize the adapter. arrList is an ArrayList that has already been filled from another class

private void initializeAdapter() {
    RecycleViewAdapter adapter = new RecycleViewAdapter(arrList);
    rv.setAdapter(adapter);
    }

This is another class that holds the cards:

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

        CardView cv;
        TextView crimeName,crimeID, crimeAddress, crimeDate, crimeWeapon;
        ImageView crimePhoto;

        PersonViewHolder(View itemView) {
            super(itemView);
            cv = (CardView)itemView.findViewById(R.id.cv);

            crimeName = (TextView) itemView.findViewById(R.id.crime_name);
            crimeID = (TextView) itemView.findViewById(R.id.crime_id);
            crimeAddress = (TextView) itemView.findViewById(R.id.crime_address);
            crimeDate = (TextView) itemView.findViewById(R.id.crime_date);
            crimeWeapon = (TextView) itemView.findViewById(R.id.crime_weapon);
            crimePhoto = (ImageView)itemView.findViewById(R.id.crime_photo);

            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            // WHAT DO I CALL HERE TO GET THE INDEX OF THE ITEM CLICKED ON ?? //
            Log.d("app", "clicked");

        }
    }

the onClick from above should go to this class (by an intent) and pass the index along with it:

    import android.support.v4.app.Fragment;
    import android.support.v7.app.ActionBarActivity;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;


    public class CrimeDetails extends ActionBarActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_crime_details);
            if (savedInstanceState == null) {
                getSupportFragmentManager().beginTransaction()
                        .add(R.id.container, new PlaceholderFragment())
                        .commit();
            }
        }


        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.crime_details, menu);
            return true;
        }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {

        public PlaceholderFragment() {
        }

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

            View rootView = inflater.inflate(R.layout.fragment_crime_details, container, false);
            return rootView;
        }
        }
     }

How can I get the Clicked Position of the Card ?

Thanks

Do net set the onClickListener in your onCreateVH method but in onBindViewHolder

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    ((PersonViewHolder)holder).yourRootLayout.setOnClickListener(getPersonClickListener(position));
}

View.OnClickListener getPersonClickListener(final int position) {
    return new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //TODO whatever you want with position
        }
    };
}

EDIT: tyczj is right. Binding the Clicklistener in the onBindViewHolder is a very easy but maybe not the best Solution - however it will work!

Another way is to use the getAdapterPosition() method from Viewholder itself and bind it in the onCreateViewHolder:

@Override
public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
    final View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.yourLayoutXml, parent, false);
    final ViewHolder holder = new PersonViewHolder(view);
    view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            final int position = holder.getAdapterPosition();
            //check if position exists
            if (position != RecyclerView.NO_POSITION) {
                //TODO whatever you want
            }
        }
    });
    return holder;
}

您在ViewHolder使用getAdapterPosition()

I am doing this slightly different, using a different onClick call, then I can use the

getAdapterPosition()

method to determine which item was clicked.

    public static class MyViewHolder extends RecyclerView.ViewHolder {
    ...

        RelativeLayout myLayout = (RelativeLayout) v.findViewById(R.id.device_adap_layout);
        myLayout.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Context cxt = myLayout.getContext();                        
                        final Intent i = new Intent(cxt, NextActivity.class);
                        i.putExtra("ITEMNAME", mAdapterList.get(getAdapterPosition()));
                        cxt.startActivity(i, options.toBundle());
                    }
                });
    ...
    }

Create adapter class which extend Recycle view and override needed method:

public class Adapter extends RecyclerView.Adapter "<"Adapter.AdapterViewHolder">" {

public List<Object> Items;
private Context context;

public Adapter(List<Object> items, Context context) {
    Items = items;
    this.context = context;
}

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

@Override
public void onBindViewHolder(final AdapterViewHolder hd, int position) {
   int indexOfCard = position;
hd.itemText.setText("pos: "+ position);
}


@Override
public AdapterViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View itemView = LayoutInflater.
            from(viewGroup.getContext()).
            inflate(R.layout.item_layout, viewGroup, false);

    return new AdapterViewHolder(itemView);
}

public static class AdapterViewHolder extends RecyclerView.ViewHolder {
    protected TextView itemText;
    public AdapterViewHolder(View v) {
        super(v);
  itemText = (TextView)v.findViewById(R.id. itemText);   
  }
}

}

You should set the onClickListener in onBindViewHolder where you already have the position:

@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (listener != null) {
                listener.onItemSelected(position);
            }
        }
    });
}

EDIT: Like @tyczj says, for the RecyclerView it's better to use getAdapterPosition in ViewHolder .

When you populate the cardView with your data, you can also use the View's setTag() method to store the position. Since you will get the View when onClick is called, you can simply call getTag() on the View to retrieve the position.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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