android: using inflater only first item of the lis

2019-08-17 07:15发布

问题:

I have a layout to be inflated in another layout dinamically for each category:

LinearLayout l = (LinearLayout) findViewById(R.id.container);

        for (CategoryEB e :categoryList){
            LayoutInflater layoutInflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            LinearLayout linLayout = (LinearLayout)layoutInflater.inflate(R.layout.inflated_layout, l);
            TextView view = (TextView)linLayout.findViewById(R.id.lable);
            view.setText(e.getName());
        }

this is the xml to be inflated (inflated_layout.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:layout_width="wrap_content" android:layout_height="wrap_content"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView android:id="@+id/lable"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="xxx"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:paddingLeft="6dip"/>

</LinearLayout>

but in this way only the first item gets populated with the correct value. The other ones of the categoryList are shown as xxx (as described in the xml).

How can I display all the correct names in the list?

回答1:

The problem is that linLayout will point to your main layout container, l. So that you will only find the first instance of a view with id R.id.label.

One simple solution would be to change the id of the label once you've initialized it. Something like this:

LinearLayout l = (LinearLayout) findViewById(R.id.container);

    for (CategoryEB e :categoryList){
        LayoutInflater layoutInflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        LinearLayout linLayout = (LinearLayout)layoutInflater.inflate(R.layout.inflated_layout, l);
        TextView view = (TextView)linLayout.findViewById(R.id.lable);
        view.setText(e.getName());
        view.setId(0);  //this way you wont find the same view twice.
    }


回答2:

I ran into the same problem recently twice. First time I was using LinearLayout so the first answer worked out just fine - setting every view id to 0 was not an issue.

However the second time I was using RelativeLayout - setting ids to 0 just broke whole view, since it is positioned as "leftTo:some_id" and so on.

I tried a little and it turned out that adding the view to its container AFTER setting its all components solves the problem (we just need to inflate it with parameter that prevents adding inflated layout to its parent). The idea is to have the inflated view outside any other view, that contains components with the same id, so findViewById can find only the one we are interested in and not the ones inflated previously.

ViewGroup inflatedLayout = (ViewGroup) layoutInflater.inflate(R.layout.some_id, mDirectChildInScrollView, false);
ImageView imageView = (ImageView) inflatedLayout.findViewById(R.id.image_view);
... do your stuff here ...
mDirectChildInScrollView.addView(inflatedLayout);

You can use ViewHolder pattern to access desired element later wihtout calling findViewById.



回答3:

It seems to me you should be dynamically creating new TextViews in your loop rather than repeadetly trying to duplicate and edit the same view. Logically, this seems to be an issue. I would create an array of textviews the size of categoryList and use it to store references to new TextViews you create in your loop:

TextView textViewArray[] = new TextView[categoryList.length];

LinearLayout l = (LinearLayout) findViewById(R.id.container);
LinearLayout linLayout = (LinearLayout) findViewById(R.id.CREATE_A_LIN_LAYOUT_IN_YOUR_CONTAINER_XML);

int i = 0; //Used for array addressing

    for (CategoryEB e :categoryList){
        TextView view = new TextView(); //declare new TextView
        view.setText(e.getName()); //set Text
        textViewArray[i] = view; //Save into array for future reference
        linLayout.addView(view); //Add TextView to linearLayout
        i++;
    }