Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change a RecyclerView item attribute programmaticaly, particularly a custom view inside the recyclerview item

I am doing some homework and want to do the following: my objects in a list have a value Tag. And I want to show/hide a custom view inside the recyclerview item layout depending on the Tag value. The idea is to use this to draw a line over the recyclerview items to mark them connected regardless of position with that line based on Tag value.

I used setVisibility(View.GONE) in previous projects and it worked on simple views, but no matter where and how I put the code, it is not working in this example.

These are the custom views in recyclerview item view that get inflated (the lineTextViewTopHalf and lineTextViewBottomHalf )

    <LinearLayout

        android:layout_width="2dp"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.example.taskmodel.view.LineTextView
            android:id="@+id/lineTextViewTopHalf"
            android:layout_width="2dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            />

        <com.example.taskmodel.view.LineTextView
            android:id="@+id/lineTextViewBottomHalf"
            android:layout_width="2dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            />
    </LinearLayout>

The lineTextViewTop/BottomHalf draws as expected


public class LineTextView extends AppCompatTextView {

    private Paint paint = new Paint();
    //constructors

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setColor(Color.parseColor("#000000"));
        paint.setStrokeWidth(2);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawLine(0, 0, 0, getHeight(), paint);
    }
}

And this is from the adapter class where I am trying so get it to show/hide, but it doesn't (//where code does nothing)


@Override
    public void onBindViewHolder(@NonNull final ElementHolder holder, final int position) {

        holder.tv1.setText(elementModels.get(position).getB());
        holder.tv2.setText(String.valueOf(elementModels.get(position).getA()));
        holder.tv3.setText(String.valueOf(elementModels.get(position).getC()));

        //this code does nothing, tested to be 1
        if(elementModels.get(position).getTag().equals("1")) {
            holder.lineTextViewTopHalf.setVisibility(View.GONE);

        }
    }

Even when I move the code around the adapter class, I am not getting anything.

class ElementHolder extends RecyclerView.ViewHolder {

        TextView tv1;
        TextView tv2;
        TextView tv3;
        LineTextView lineTextViewTopHalf;
        LineTextView lineTextViewBottomHalf;


        public ElementHolder(@NonNull View itemView, List<ElementModel> elementModels) {

            super(itemView);

            int position = itemView.getVerticalScrollbarPosition();
            tv1 = itemView.findViewById(R.id.tvNaziv);
            tv2 = itemView.findViewById(R.id.tvPocetak);
            tv3 = itemView.findViewById(R.id.tvKraj);
            lineTextViewTopHalf = itemView.findViewById(R.id.lineTextViewTopHalf);
            lineTextViewBottomHalf = itemView.findViewById(R.id.lineTextViewBottomHalf);


            //this code does nothing, and position is tested to be 0
            if(position == 0) {
                lineTextViewTopHalf.setVisibility(View.GONE);
            } else if (position == elementModels.size()) {
                lineTextViewBottomHalf.setVisibility(View.GONE);
            }
        }
    }

I was expecting the code to behave as intended and make the views show/hide, but I am stuck. Any help would be appreciated. If the syntax highlights are not showing, please forgive me, first question ever (but i did use xml,java tags when posting, will try to edit if wrong)

EDIT: I have managed to find out why it's not updating as expected. My adapter class is implementing a callback and I need a Handler to update the UI, it can't be done from a callback implementation. Thank you all for contributions!

like image 617
JVN Avatar asked Sep 05 '19 00:09

JVN


People also ask

Can we use RecyclerView inside RecyclerView in android?

A nested RecyclerView is an implementation of a RecyclerView within a RecyclerView. An example of such a layout can be seen in a variety of apps such as the Play store where the outer (parent) RecyclerView is of Vertical orientation whereas the inner (child) RecyclerViews are of horizontal orientations.

What is ViewHolder in RecyclerView?

A ViewHolder describes an item view and metadata about its place within the RecyclerView. Adapter implementations should subclass ViewHolder and add fields for caching potentially expensive findViewById results. While LayoutParams belong to the LayoutManager , ViewHolders belong to the adapter.


1 Answers

In your first approached, trying to hide the lineTextView in onBindViewHolder is the correct way. It wasn't worked because somehow your condition was never matched

if(elementModels.get(position).getTag().equals("1")) 

Then the code to GONE the lineTextViewTopHalf never touched

Please try with the simple condition and check if the lineTextView able to hide or not first, then check your condition again

if(position == 0) {
        holder.lineTextViewTopHalf.setVisibility(View.GONE);
} else if ((position == 1) {
       holder.lineTextViewBottomHalf.setVisibility(View.GONE);    
}
like image 156
KinhKha Avatar answered Oct 13 '22 11:10

KinhKha