Search code examples
androidandroid-listviewlistadapter

Assigning unique tag to list item in a list


I need help with setting tags in my viewHolder object. I have a list that is longer than the screen (on a phone) and i need to set a different tag for each view. As you can see in my preview app (link below)in the exterior fragment that the first item and last item are binded together. I dont' want that, i want every views to be unique. How can I do that.

https://drive.google.com/file/d/0B2xlu23GjnfvTEgtbkprOThtMmM/edit?usp=sharing

thanks

my InspectionListAdapter

public class InspectionListAdapter extends ArrayAdapter<String> {

private final Activity context;
private final String[] inspectionTitles;
private final String[] description;

public InspectionListAdapter(Activity context, String[] inspectionTitles,
        String[] description) {
    super(context, R.layout.inspection_item_layout, inspectionTitles);
    this.context = context;
    this.inspectionTitles = inspectionTitles;
    this.description = description;
}

public static class ViewHolder {
    public ImageView imageView, expandButton;
    public TextView txtTitle;
    public TextView txtDescription;
    public RelativeLayout expandLayout;
    public EditText ownDesc, estCost;
    public LayerDrawable listItem;
    public GradientDrawable color;
    public CheckBox checkRepair, checkDone;
    public RelativeLayout mainLayout;

}

@Override
public View getView(int position, View view, ViewGroup parent) {

    final ViewHolder viewHolder;

    View rowView = view;

    if (rowView == null) {
        LayoutInflater inflater = context.getLayoutInflater();
        rowView = inflater.inflate(R.layout.inspection_item_layout, null,
                true);

        viewHolder = new ViewHolder();



        viewHolder.mainLayout = (RelativeLayout) rowView
                .findViewById(R.id.item_layout_main);

        viewHolder.txtTitle = (TextView) rowView
                .findViewById(R.id.textViewItemTitle);

        viewHolder.txtDescription = (TextView) rowView
                .findViewById(R.id.textViewTip);

        viewHolder.listItem = (LayerDrawable) rowView.getResources()
                .getDrawable(R.drawable.layer_car_background);

        viewHolder.color = (GradientDrawable) (viewHolder.listItem
                .findDrawableByLayerId(R.id.item_list_background));

        viewHolder.imageView = (ImageView) rowView
                .findViewById(R.id.imageViewItem);

        viewHolder.expandButton = (ImageView) rowView
                .findViewById(R.id.imageViewTitle);

        viewHolder.ownDesc = (EditText) rowView
                .findViewById(R.id.editTextDescription);

        viewHolder.estCost = (EditText) rowView
                .findViewById(R.id.editTextEstCost);

        viewHolder.checkRepair = (CheckBox) rowView
                .findViewById(R.id.checkBox2);

        viewHolder.checkDone = (CheckBox) rowView
                .findViewById(R.id.checkBox1);

        viewHolder.checkRepair
                .setOnCheckedChangeListener(new OnCheckedChangeListener() {

                    @Override
                    public void onCheckedChanged(CompoundButton view,
                            boolean arg1) {
                        // TODO Auto-generated method stub

                        if (view.isChecked()) {
                            viewHolder.checkDone.setChecked(false);
                        }
                    }
                });
        viewHolder.checkDone
                .setOnCheckedChangeListener(new OnCheckedChangeListener() {

                    @Override
                    public void onCheckedChanged(CompoundButton view,
                            boolean arg1) {
                        // TODO Auto-generated method stub

                        if (view.isChecked()) {
                            viewHolder.checkRepair.setChecked(false);

                        }
                    }
                });

        viewHolder.expandLayout = (RelativeLayout) rowView
                .findViewById(R.id.relativeLayoutExpandable);

        viewHolder.expandLayout.setVisibility(View.GONE);

        viewHolder.expandButton
                .setOnClickListener(new OnClickListener() {

                    public void onClick(View v) {
                        // TODO Auto-generated method stub

                        if (viewHolder.expandLayout.getVisibility() == View.VISIBLE) {
                            viewHolder.expandButton
                                    .setImageResource(R.drawable.ic_action_expand);
                            viewHolder.expandLayout
                                    .setVisibility(View.GONE);
                            if (viewHolder.checkDone.isChecked()) {

                                viewHolder.mainLayout
                                        .setBackgroundResource(R.drawable.layer_car_background_green);

                            }
                            if (viewHolder.checkRepair.isChecked()) {

                                viewHolder.mainLayout
                                        .setBackgroundResource(R.drawable.layer_car_background_red);
                            }

                        } else {
                            viewHolder.expandButton
                                    .setImageResource(R.drawable.ic_action_collapse);
                            viewHolder.expandLayout
                                    .setVisibility(View.VISIBLE);

                            viewHolder.mainLayout
                                    .setBackgroundResource(R.drawable.layer_car_background);

                        }
                    }
                });


        rowView.setTag(viewHolder);

    } else {

        viewHolder = (ViewHolder) rowView.getTag();
    }


    viewHolder.txtTitle.setText(inspectionTitles[position]);
    viewHolder.txtDescription.setText("Tip: \n" + description[position]);
    viewHolder.imageView.setImageResource(R.drawable.ic_launcher);
    viewHolder.expandButton
            .setImageResource(R.drawable.ic_action_expand);

    return rowView;
}

}


Solution

  • The mistake is in the onClick of the OnClickListener for viewHolder.expandbutton. There you start immedeately with 'if (viewHolder.....)`. But that is the wrong viewHolder as at the moment the user clicks the view many viewHolders may have been created and died. So you have to obtain the right viewHolder first. something like (untested)

                    View rowView = (View)v.getParent();
    
                    ViewHolder viewHolder =(ViewHolder) rowView.getTag();
    

    You put it IN the onClick() method. final ViewHolder viewHolder; You made it final in order to use it in onClick() and onCheckedChanged. Remove the final. Unfortunately the getParent() does not work in onCheckedChanged. So we do it different.

        viewHolder.checkDone.setTag(viewHolder.checkRepair);
        viewHolder.checkDone
                .setOnCheckedChangeListener(new OnCheckedChangeListener() {
    
                    @Override
                    public void onCheckedChanged(CompoundButton view,
                            boolean arg1) {
    
                        CheckBox checkBox = (CheckBox)view.getTag();
    
                        if (view.isChecked()) {
                            //viewHolder.checkRepair.setChecked(false);
                            checkBox.setChecked(false);
                        }
                    }
                });
    

    Do the same for the other checkbox.

    Now the color expands over another view. The reason is that you should set the default color at the same time as you set new txtTitle, txtDescription and so on. So add there viewHolder.mainLayout.setBackgroundResource(R.drawable.layer_car_background);.

    For the rest your code misses keeping state. If an item is expanded and the user scrolls the list up and down (i added much more items to be able to scroll more) then the expanded state vanishes. Also checkboxes don't stay checked and color vanishes (add much more items to see). You should add some boolean arrrays (at least three) in which you keep the state. Update those arrays in the events. In getView() read the arrays and put colors and checkboxes checked accordingly. It is not much work to add those arrays you will see...