Skip to content Skip to sidebar Skip to footer

Listview: How To Access Item's Elements Programmatically From Outside?

I have the following situation. I have a ListView, each item of the ListView is comprised of different widgets (TextViews, ImageViews, etc...) inflated form a Layout in the getView

Solution 1:

When your event is triggered you should just call a notifyDataSetChanged on your adapter so that it will call again getView for all your visible elements.

Your getView method should take into account that some elements may have different background colors (and not forget to set it to normal color if the element doesn't need the changed background, else with recycling you would have many elements with changed background when you scroll)

edit :

I would try something like this :

@Overridepublic View getView(int position, View convertView, ViewGroup parent) {
    if(convertView == null)
    {
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.card, parent, false);
    }

    //This part should also be optimised with a ViewHolder//because findViewById is a costly operation, but that's not the point of this exampleCardViewcardView=(CardView)convertView .findViewById(R.id.card);

    //I suppose your card should be determined by your adapter, not a new one each timeCardcard= getItem(position);

    //here you should check sthg like the position presence in a map or a special state of your card objectif(mapCardWithSpecialBackground.contains(position))
    {
        card.setBackgroundResource(specialBackground);
    }
    else
    {
        card.setBackgroundResource(normalBackground);
    }
    cardView.setCard(card);

    return convertView;
}

And on the special event i would add the position of the item into the map and call notifyDataSetChanged.

Solution 2:

Use the onitemclicklistener which has method onclicksomething..that takes four or five parameters. (View parent, View view, int position, int id). Use the view parameter to customize your background.

Update Here's some of my code, If you don't understand I recommend to read about recycling and ViewHolder pattern.

@Overridepublic View getView(int position, View convertView, ViewGroup parent) {
    {
            ViewHolder viewHolder;
            // If convertView isn't a recycled view, create a new.if(convertView == null){
                LayoutInflaterinflater= (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.row_gallery_frame, parent, false);

                viewHolder = newViewHolder();
                // Here you must be able to find your Widget inside convertView and set a listener to it I guess?
                viewHolder.nameHolder = (TextView) convertView.findViewById(R.id.nameTv);
                // Set a reference to newly inflated view
                convertView.setTag(viewHolder);
            }
            // If it is, then get the ViewHolder by tagelse{
                viewHolder = (ViewHolder)convertView.getTag();
            }
            // Set the dataGalleryFramegalleryFrame= galleryFrameArrayList.get(position);

            viewHolder.nameHolder.setText(galleryFrame.getName());

            return convertView;
        }
    }
    // Viewholder pattern which holds all widgets usedpublicstaticclassViewHolder{
        public TextView nameHolder;
    }

Solution 3:

I assume you have a model object that you use to "draw" the list item , and for example the background color is determined based on a boolean or something.

All you need to do, is change the value on which you base your decision which background color should that TextView have.

Your getView() method should have code like that

if (myModelObj.isBrown()) {
    myTextView.setBackgroundResource(R.drawable.brown_bg);
else
    myTextView.setBackgroundResource(R.drawable.not_brown_bg);

All you should do when ur event is triggered, is set the value of the brown boolean in your model and call notifyDataSetChanged() on your adapter

EDIT

If for some reason you don't wanna call nofitfyDataSetChanged(), althought it won't move the scroll position of your list and with the right recyclying it won't cause bad performance

You can find the View object that represent the list item you want to edit-if it's visisble-, and simply change the background in it, without refreshing the list at all.

int wantedPosition = 10; // Whatever position you're looking for
int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount();
int wantedChild = wantedPosition - firstPosition
if (wantedChild < 0 || wantedChild >= listView.getChildCount()) {
    // Wanted item isn't displayed
    return;
}
View wantedView = listView.getChildAt(wantedChild);

then use wantedView to edit your background

This answer can be found here

Solution 4:

try this one:

View v=lv.getAdapter().getView(index, null, lv);
View card =(View)v.findViewById(R.id.card);
card.setBackgroundResource(R.drawable.pressed_background_card);
card.invalidate();
v.invalidate();

those function force your views to redraw itself and they will render again. look at invalidate()

Solution 5:

What I normally do is this:

publicstaticclassEventDetailsRenderer {

    private TextView title;

    private TextView description;

    private Event item;

    publicEventDetailsRenderer(View view) {
        extractFromView(view);
    }

    privatefinalvoidextractFromView(View view) {
        title = (TextView) view.findViewById(R.id.EventTitle);
        description = (TextView) view.findViewById(R.id.Description);
    }

    publicfinalvoidrender() {
            render(item);
    }

    publicfinalvoidrender(Event item) {
        this.item= item;
        title.setText(item.getTitle());
        description.setText(item.getDescription());
    }
}

privateclassEventsAdapterextendsArrayAdapter<Event> {

    publicEventsAdapter(Context context) {
        super(context, R.layout.list_node__event_details, 0);
    }

    publicvoidaddAllItems(Event... services) {
        for (inti=0; i < services.length; i++) {
            add(services[i]);
        }
    }

    @Overridepublic View getView(int position, View convertView, ViewGroup parent) {
        Eventevent= getItem(position);
        EventDetailsRenderer eventRenderer;

        if (convertView != null && convertView.getTag() != null) {
            eventRenderer = (EventDetailsRenderer) convertView.getTag();
        } else {
            convertView = getActivity().getLayoutInflater().inflate(R.layout.list_node__event_details, null);
            eventRenderer = newEventDetailsRenderer(convertView);
            convertView.setTag(eventRenderer);
        }

        eventRenderer.render(event);
        return convertView;
    }
}

NOTE: that this example might not compile I pasted it from some code I have and deleted some lines to show an example but the logic it the same.

And then when you want to render it, just get the children from the list, iterate over them, check if the renderer contains the card you want to flip and call its render method... then you render a specific item in the list without effecting the rest of the items.

Let me know if this works...

Adam.

Post a Comment for "Listview: How To Access Item's Elements Programmatically From Outside?"