简体   繁体   中英

Get value of textview in cardview from recycleview

I have a RecycleView that has cards inside of it. Each card has a list of companies and prices.

In my onBindViewHolder I have a click event where I would like to get the price of the TextView in that row inside of the Cardview .

Every time I click I always get the value/price of the top item inside of the individual card and never get the price of the item I am clicking.

The data param of the bindData method is what I am using to create the list of items inside of the Cardview .

Any help would be greatly appreciated. I just need to get the value of the correct TextView where I am clicking.

public class StockCardAdapter extends RecyclerView.Adapter<StockCardAdapter.ViewHolder> {

 public static class ViewHolder extends RecyclerView.ViewHolder   {

    protected RelativeLayout mCardBodyLayout;
    protected TextView mTitleTextView; 

    public ViewHolder(View v) {
        super(v);
        mCardBodyLayout = (RelativeLayout) v.findViewById(R.id.card_body);
        mTitleTextView = (TextView) v.findViewById(R.id.card_title); 
    }

    public void bindData(StockCategoryModel data, Context ctx) {
        this.mTitleTextView.setText(data.getCategoryName());

        TableLayout tableLayout = new TableLayout(ctx);

        int rows = data.getStockList().size();

        for (int r = 0; r < rows; r++) {
            TableRow row = new TableRow(ctx);

            TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams (TableLayout.LayoutParams.MATCH_PARENT,TableLayout.LayoutParams.WRAP_CONTENT);
            rowParams.setMargins(0, 0, 0, 16);
            row.setLayoutParams(rowParams);

            LinearLayout rl = new LinearLayout(ctx);
            rl.setOrientation(LinearLayout.VERTICAL);

            Integer priceColor = SharedUtilities.getColor(data.getStockList().get(r).priceChange, ctx);

            //price row
            LinearLayout priceLayout = new LinearLayout(ctx);
            priceLayout.setOrientation(LinearLayout.HORIZONTAL);
            priceLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
            priceLayout.setWeightSum(4);

            LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f);

            final TextView price_text = new TextView(ctx);
            price_text.setTag("priceTag");
            price_text.setText(data.getStockList().get(r).price);
            price_text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
            price_text.setTextColor(Color.BLACK);
            price_text.setLayoutParams(textViewParams);
            priceLayout.addView(price_text);

            //company row
            final TextView name_text = new TextView(ctx);
            name_text.setText(data.getStockList().get(r).company); 
            name_text.setTextColor(Color.GRAY);
            name_text.setLayoutParams( new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
            name_text.setMaxWidth(700);
            name_text.setEllipsize(TextUtils.TruncateAt.END);
            name_text.setMaxLines(1);
            name_text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);

            rl.addView(priceLayout);
            rl.addView(name_text);
            row.addView(rl);

            tableLayout.setStretchAllColumns(true);
            tableLayout.addView(row);
        }
        mCardBodyLayout.addView(tableLayout);
    }

}

private List<StockCategoryModel> mDataset;
private Context mContext;

// Constructor
public StockCardAdapter(List<StockCategoryModel> dataset, Context ctx) {
    this.mDataset = dataset;
    this.mContext = ctx;
}

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
 }

// Create new views (invoked by the layout manager)
@Override
public StockCardAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup,
                                                      int viewType) {
    // create a new view
    View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_layout, viewGroup, false);

    ViewHolder vh = new ViewHolder(v);
    return vh;
}

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {

    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override public void onClick(View v2) {
            final TextView textViewName = (TextView) v2.findViewWithTag("priceTag"); ;
            final String priceTag = textViewName.getText().toString();
        }
    });

    holder.bindData(mDataset.get(position), mContext);
}

// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
    return mDataset.size();
}

}

What you need to do is to set a click listener to every row separately.

Why do you always get the first row value?

This code,

holder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v2) {
        final TextView textViewName = (TextView) v2.findViewWithTag("priceTag"); ;
        final String priceTag = textViewName.getText().toString();
    }
});

Sets a click listener to every list item - the whole card. This means that every time the user clicks inside the card view bounds - this callback will be fired. BUT , who will be v2 ? It will always be the view to which we set the listener to - in this case - the whole card.

This means that every time you call v2.findViewWithTag("priceTag"); you are searching the first child of the entire card that has the tag "priceTag" - which is the "top" item in the card.

How to solve this issue?

If you want to identify which child is being clicked - you will have to set a click listener to each child directly.

As an example, try this code (see ADDED comments):

public class StockCardAdapter extends 

RecyclerView.Adapter<StockCardAdapter.ViewHolder> {

 public static class ViewHolder extends RecyclerView.ViewHolder   {

    protected RelativeLayout mCardBodyLayout;
    protected TextView mTitleTextView; 

    public ViewHolder(View v) {
        super(v);
        mCardBodyLayout = (RelativeLayout) v.findViewById(R.id.card_body);
        mTitleTextView = (TextView) v.findViewById(R.id.card_title); 
    }

    public void bindData(StockCategoryModel data, Context ctx, View.OnClickListener listener) {
        this.mTitleTextView.setText(data.getCategoryName());

        TableLayout tableLayout = new TableLayout(ctx);

        int rows = data.getStockList().size();

        for (int r = 0; r < rows; r++) {
            TableRow row = new TableRow(ctx);

            TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams (TableLayout.LayoutParams.MATCH_PARENT,TableLayout.LayoutParams.WRAP_CONTENT);
            rowParams.setMargins(0, 0, 0, 16);
            row.setLayoutParams(rowParams);

            LinearLayout rl = new LinearLayout(ctx);
            rl.setOrientation(LinearLayout.VERTICAL);

            Integer priceColor = SharedUtilities.getColor(data.getStockList().get(r).priceChange, ctx);

            //price row
            LinearLayout priceLayout = new LinearLayout(ctx);
            priceLayout.setOrientation(LinearLayout.HORIZONTAL);
            priceLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
            priceLayout.setWeightSum(4);

            LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f);

            final TextView price_text = new TextView(ctx);
            price_text.setTag("priceTag");
            price_text.setText(data.getStockList().get(r).price);
            price_text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
            price_text.setTextColor(Color.BLACK);
            price_text.setLayoutParams(textViewParams);
            priceLayout.addView(price_text);

            //company row
            final TextView name_text = new TextView(ctx);
            name_text.setText(data.getStockList().get(r).company); 
            name_text.setTextColor(Color.GRAY);
            name_text.setLayoutParams( new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
            name_text.setMaxWidth(700);
            name_text.setEllipsize(TextUtils.TruncateAt.END);
            name_text.setMaxLines(1);
            name_text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);

            rl.addView(priceLayout);
            rl.addView(name_text);
            row.addView(rl);

            tableLayout.setStretchAllColumns(true);
            tableLayout.addView(row);

            // *ADDED* set the listener directly to each row
            row.setOnClickListener(listener);

        }
        mCardBodyLayout.addView(tableLayout);
    }

}

private List<StockCategoryModel> mDataset;
private Context mContext;

// Constructor
public StockCardAdapter(List<StockCategoryModel> dataset, Context ctx) {
    this.mDataset = dataset;
    this.mContext = ctx;
}

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
 }

// Create new views (invoked by the layout manager)
@Override
public StockCardAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup,
                                                      int viewType) {
    // create a new view
    View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_layout, viewGroup, false);

    ViewHolder vh = new ViewHolder(v);
    return vh;
}

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
    // *ADDED* Send the callback to the bind method
    holder.bindData(mDataset.get(position), mContext, new View.OnClickListener() {
        @Override public void onClick(View v2) {
            final TextView textViewName = (TextView) v2.findViewWithTag("priceTag"); ;
            final String priceTag = textViewName.getText().toString();
        }
    }));
}

// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
    return mDataset.size();
}

}

NOTE:

This is NOT the proper way to handle a RecyclerView - You never want to create a new object (in this case new View.OnClickListener() {} ) inside the data binding - that will reduce performance. But this is another issue :)

The tag of textView is same in all the cases and that's why it is repeating, only the value of first item. Assign unique tag usually by concatenating "priceTag" with position. Make changes in your code as follows:

public void bindData(StockCategoryModel data, Context ctx, int position) {
 //All your code
  //..
 //...


 final TextView price_text = new TextView(ctx);
 price_text.setTag("priceTag"+String.valueOf(position));
}

and in your onBindViewHolder:

final TextView textViewName = (TextView) v2.findViewWithTag("priceTag"+String.valueOf(position)); 


holder.bindData(mDataset.get(position), mContext,position);

Find child view from Tag please call it.

TextView priceTagTextView =(TextView)getViewsByTag(mCardBodyLayout, "priceTag").get(0);  



private ArrayList<View> getViewsByTag(ViewGroup root, String tag){
    ArrayList<View> views = new ArrayList<View>();
    final int childCount = root.getChildCount();
    for (int i = 0; i < childCount; i++) {
        final View child = root.getChildAt(i);
        if (child instanceof ViewGroup) {
            getViewsByTag((ViewGroup) child, tag));
        }

        final Object tagObj = child.getTag();
        if (tagObj != null && tagObj.equals(tag)) {
            views.add(child);
        }

    }
    return views;
}

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