开发者

Need help in using android layout trick #1

I have read this blog entry about using relative layout to optimize layout in ListView: http://android-developers.blogspot.com/2009/02/android-layout-tricks-1.html

I have used this layout for my ListView Item (with a slight modification of the example):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"

    android:padding="6dip">

    <ImageView
        android:id="@+id/icon"

        android:layout_width="wrap_content"
        android:layout_height="fill_parent"

        android:layout_alignParentTop="true"
        android:layout_alignParentBottom="true"
        android:layout_marginRight="6dip"

        android:src="@drawable/icon" />

    <TextView
        android:id="@+id/secondLine"

        android:layout_width="fill_parent"
        android:layout_height="26dip" 

        android:layout_toRightOf="@id/icon"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"

        android:singleLine="true"
        android:ellipsize="marquee"/>

    <TextView
        android:id="@+id/text"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"

        android:layout_toRightOf="@id/icon"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_above="@id/secondLine"
        android:layout_alignWithParentIfMissing="true"

        android:gravity="center_vertical" />

</RelativeLayout>

And I have modified the List14.java in APIDemo to use that ListItem View. But when I run it on emulator, I only see the icon, the text is blank. And when I open HierarchyViewer for the text View's height is 0. Can someone please tell me why?

public class TestListView extends ListActivity {

     private static class EfficientAdapter extends BaseAdapter {
            private LayoutInflater mInflater;
            private Bitmap mIcon1;
            private Bitmap mIcon2;

            public EfficientAdapter(Context context) {
                // Cache the LayoutInflate to avoid asking for a new one each time.
                mInflater = LayoutInflater.from(context);

                // Icons bound to the rows.
                mIcon1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon48x48_1);
                mIcon2 = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon48x48_2);
            }

            /**
             * The number of items in the list is determined by the number of speeches
             * in our array.
             *
             * @see android.widget.ListAdapter#getCount()
             */
            public int getCount() {
                return DATA.length;
            }

            /**
             * Since the data comes from an array, just returning the index is
             * sufficent to get at the data. If we were using a more complex data
             * structure, we would return whatever object represents one row in the
             * list.
             *
             * @see android.widget.ListAdapter#getItem(int)
             */
            public Object getItem(int position) {
                return position;
            }

            /**
             * Use the array index as a unique id.
             *
             * @see android.widget.ListAdapter#getItemId(int)
             */
            public long getItemId(int position) {
                return position;
            }

            /**
             * Make a view to hold each row.
             *
             * @see android.widget.ListAdapter#getView(int, android.view.View,
             *      android.view.ViewGroup)
             */
            public View getView(int position, View convertView, ViewGroup parent) {
                // A ViewHolder keeps references to children views to avoid unneccessary calls
                // to findViewById() on each row.
                ViewHolder holder;

                // When convertView is not null, we can reuse it directly, there is no need
                // to reinflate it. We only inflate a new View when the convertView supplied
                // by ListView is null.
                if (convertView == null) {
                    convertView = mInflater.inflate(R.layout.list_item_icon_text, null);

                    // Creates a ViewHolder and store references to the two children views
                    // we want to bind data to.
                    holder = new ViewHolder();
                    holder.text = (TextView) convertView.findViewById(R.id.text);
                    holder.icon = (ImageView) convertView.findViewById(R.id.icon);

                    convertView.setTag(holder);
                } else {
                    // Get the ViewHolder back to get fast access to the TextView
                    // and the ImageView.
                    holder = (ViewHolder) convertView.getTag();
           开发者_如何学编程     }

                // Bind the data efficiently with the holder.
                holder.text.setText(DATA[position]);
                holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);

                return convertView;
            }

            static class ViewHolder {
                TextView text;
                ImageView icon;
            }
        }

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setListAdapter(new EfficientAdapter(this));
        }

        private static final String[] DATA = {
                "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam",

                "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano"};
}

}


I found a solution.

Instead of:

convertView = mInflater.inflate(R.layout.list_item_icon_text, null);

You have to use:

convertView = mInflater.inflate(R.layout.list_item_icon_text, parent, false);

I found this tip on https://groups.google.com/forum/#!msg/android-developers/E-32MfKeyA4/BtTBF3kfw-YJ, and it works.


Can't tell you exactly why the Blog's example won't run (anymore?). It doesn't run on my emulator either (1.5 & 1.6). I finally got it to run by switching the two TextViews and getting rid of layout_above. Like this:

  <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"

    android:id="@+id/text"
    android:layout_alignWithParentIfMissing="true"
    android:layout_toRightOf="@id/icon"
    android:layout_alignParentRight="true"
    android:layout_alignParentTop="true"
    />

<TextView  
    android:id="@+id/secondLine"

    android:layout_width="fill_parent"
    android:layout_height="26dip" 
    android:layout_below="@id/text" 

    android:layout_toRightOf="@id/icon"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"
    />


Looks like your layout is a bit muddled. With RelativeLayouts you need to be careful not to contradict yourself with alignmentst, else all sorts of unexpected things happen.

android:layout_alignParentTop="true"
    android:layout_alignParentBottom="true"

Above is an example.

I haven't tried this out and you didn't explain what you wanted to achieve with yout layout, but try the following.

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip"
>

<ImageView
    android:id="@+id/icon"
    android:src="@drawable/icon"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_marginRight="6dip"
    />

<TextView
    android:id="@+id/text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/icon"
    android:layout_alignParentRight="true"
    android:layout_alignParentTop="true"
    />

<TextView
    android:id="@+id/secondLine"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" 
    android:layout_toRightOf="@id/icon"
    android:layout_below="@id/text"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"
    android:singleLine="true"
    android:ellipsize="marquee"
    />

Try to keep your layout definitions in a logical order, it will help with debugging later.

Also have a look at your getView method, it can be a lot simpler.

    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        LayoutInflater vi = 

(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    v = vi.inflate(R.layout.list_item_icon_text, null);

    TextView text = (TextView) convertView.findViewById(R.id.text);
    ImageView icon = (ImageView) convertView.findViewById(R.id.icon);

    icon.setText(DATA[position]);
    icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);

    return v;
}

These examples may not be 100% perfect, but they should get you along the right path.


I had the same problem, and all I had to do was change the android:layout_toRightOf="@id/icon" to android:layout_toRightOf="@+id/icon"; note the "+" before "id" and viola! Worked like a charm.

-Sree

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜