Rohan Williams
Rohan Williams

Reputation: 15

How do I get the index from my adapter using a view?

Sorry if this is convoluted...

I'm trying to create an Async Task that updates a value in a recycler view adapter when it's clicked. My problem is I can't get a specific row from the trains LiastArray from the view that's being returned onClick of one of the RecyclerView rows.

public void ArrivalTimeOnClickListener(View view) {
    pbArrivalTime = (ProgressBar)view.findViewById(R.id.pbArrivalTime);
    tvArrivalTime = (TextView)view.findViewById(R.id.tvArrivalTime);

    /**
     * GET ADAPTER INDEX HERE
     *
     * TRIED:
     * int trainIndex = rvTrainTimetable.getChildAdapterPosition(view.findViewById(R.id.rlTrainRoot));
     */

    new RefreshSingleArrivalTime().execute(view);
}

Essentially, I have a Train class with basic Platform, arrival time, destination etc. fields with getters and setters. I am then setting an adapter with an ArrayList of the Train class, and in ruen assigning the adapter to my RecyclerView:

private void InitializeTrainTimetable() {
    trains = new ArrayList<Train>();
    trains.add(new Train("Artarmion Platform 3", 7, "On time", "Ahfield", "15:01"));
    trains.add(new Train("TEST", 97, "TEST", "TEST", "TEST"));

    trainAdapter = new TrainAdapter(this, trains);

    rvTrainTimetable = (RecyclerView) findViewById(R.id.rvTrainTimetable);

    rvTrainTimetable.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
    rvTrainTimetable.setItemAnimator(new DefaultItemAnimator());
    rvTrainTimetable.setAdapter(trainAdapter);
}

My TrainAdapter is defined as follows:

public class TrainAdapter extends RecyclerView.Adapter<TrainAdapter.ViewHolder> {
    private ArrayList<Train> mTrains;

    public TrainAdapter(Context context, ArrayList<Train> trains){
        mTrains = trains;
    }

    /** Inflates xml layout file */
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.train_item, parent, false);

        return new ViewHolder(itemView);
    }

    /** Initialise and assign values for eah row in recycler view */
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Train train = mTrains.get(position);

        holder.mArrivalTime.setText(String.format(Constants.REMAINING_MINS, train.getArrivalTime()));
        holder.mPlatform.setText(train.getPlatform());
        // TOODO: get actual time
        holder.mTime.setText("14:14");
        holder.mStatus.setText(train.getStatus());
        holder.mDestinationTime.setText(train.getDestinationTime());
        holder.mDestination.setText(train.getDestination());
    }

    /** Returns number of items in list */
    @Override
    public int getItemCount() {
        return mTrains.size();
    }

    /** Initialises xml elements */
    class ViewHolder extends RecyclerView.ViewHolder {
        public TextView mArrivalTime;
        public TextView mPlatform;
        public TextView mTime;
        public TextView mStatus;
        public TextView mDestinationTime;
        public TextView mDestination;

        /** Initialises xml elements */
        public ViewHolder(View itemView) {
            super(itemView);
            mArrivalTime = (TextView) itemView.findViewById(R.id.tvArrivalTime);
            mPlatform = (TextView) itemView.findViewById(R.id.tvPlatform);
            mTime = (TextView) itemView.findViewById(R.id.tvTime);
            mStatus = (TextView) itemView.findViewById(R.id.tvStatus);
            mDestinationTime = (TextView) itemView.findViewById(R.id.tvDestinationTime);
            mDestination = (TextView) itemView.findViewById(R.id.tvDestination);
        }
    }
}

My Train Item layout is defined inside a Relative Layout with 3 LinearLayouts:

<RelativeLayout
android:id="@+id/rlTrainRoot"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
    android:id="@+id/llArrivalTime"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:orientation="vertical"
    android:layout_marginBottom="8dp"
    android:layout_marginRight="15dp"
    android:layout_marginEnd="15dp"
    android:background="@color/ArrivalTimeGreen"
    android:onClick="ArrivalTimeOnClickListener">

Upvotes: 1

Views: 2829

Answers (2)

Leonid Veremchuk
Leonid Veremchuk

Reputation: 1963

You can create custom interface for click handling.

Look my example

public interface RecyclerViewClickListener{
    void onItemClick(View view, int position);
}

public class TrainAdapter extends RecyclerView.Adapter<TrainAdapter.ViewHolder> {
    private ArrayList<Train> mTrains;
    private RecyclerViewClickListener mListener;

    public TrainAdapter(Context context, ArrayList<Train> trains, RecyclerViewClickListener listener){
        mTrains = trains;
        mListener = listener;
    }

....

public ViewHolder(final View itemView) {
        super(itemView);
        mArrivalTime = (TextView) itemView.findViewById(R.id.tvArrivalTime);
        mPlatform = (TextView) itemView.findViewById(R.id.tvPlatform);
        mTime = (TextView) itemView.findViewById(R.id.tvTime);
        mStatus = (TextView) itemView.findViewById(R.id.tvStatus);
        mDestinationTime = (TextView) itemView.findViewById(R.id.tvDestinationTime);
        mDestination = (TextView) itemView.findViewById(R.id.tvDestination);
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mListener.onItemClick(itemView, getAdapterPosition());
            }
        });

.....

in class:

trains.add(new Train("Artarmion Platform 3", 7, "On time", "Ahfield", "15:01"));
trains.add(new Train("TEST", 97, "TEST", "TEST", "TEST"));

trainAdapter = new TrainAdapter(this, trains, new RecyclerViewClickListener(){
   @Overide
   void onItemClick(View view, int position){
       ArrivalTimeOnClickListener(view,position);
  }
});

Upvotes: 1

Mr Quattro
Mr Quattro

Reputation: 341

You can tag your view with its position:

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    ...
    holder.someClickableElement.setTag(position);
    ...
}

Then in ArrivalTimeOnClickListener:

public void ArrivalTimeOnClickListener(View view) {
    int position = (int) view.getTag();
    adapter.mTrains.get(position); // make mTrains public first, or provide getter
    ...
}

Upvotes: 2

Related Questions