TextView的setCompoundDrawables方法不改变或显示图标

3
我有一个带自定义列表项的ListView。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >    
    <ImageView
        android:id="@android:id/icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/app_name"
        android:maxWidth="32dp" />

    <TextView
        android:id="@android:id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center|left"
        android:paddingBottom="4dp"
        android:paddingTop="4dp"
        android:textIsSelectable="true"
        android:textSize="24sp" >

    </TextView>
</LinearLayout>

现在Eclipse给我警告:此标记及其子元素可以被一个<TextView/>和复合绘图替代。虽然一切正常,但我不喜欢警告,所以我把视图改成了这样。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >
    <TextView
        android:id="@android:id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center|left"
        android:paddingBottom="4dp"
        android:paddingTop="4dp"
        android:textIsSelectable="true"
        android:textSize="24sp"
        android:drawableLeft="@drawable/unstarred" >

    </TextView>
</LinearLayout>

但是图片没有显示出来,您能告诉我布局有什么问题吗?这是我的适配器。
public class CategoryAdapter extends ArrayAdapter<Category> {

    private Context mContext;
    private int mLayoutResourceId;
    private Category mCategories[] = null;

    public CategoryAdapter(Context context, int layoutResourceId, Category[] data) {
        super(context, layoutResourceId, data);

        mContext = context;
        mCategories = data;
        mLayoutResourceId = layoutResourceId;
    }

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

        View row = convertView;
        Holder holder = null;

        if(null == row) {               
            row = LayoutInflater.from(mContext).inflate(mLayoutResourceId, parent, false);
            holder = new Holder();
            holder.mIcon = (ImageView)row.findViewById(android.R.id.icon);
            holder.mTitle = (TextView)row.findViewById(android.R.id.title);

            row.setTag(holder);
        } else {
            holder = (Holder) row.getTag();
        }

       // obviously only one is used at a time
       // First layout
       final Category category = mCategories[position];
       holder.mTitle.setText(category.getName());
       holder.mIcon
          .setImageResource(category.getStarred() == 1 ? R.drawable.starred : R.drawable.unstarred);            

       // Second layout
       final Category category = mCategories[position];
       final Drawable icon = getResources().getDrawable(category.getStarred() == 1 ? R.drawable.starred : R.drawable.unstarred);
       holder.mTitle.setText(category.getName());
       holder.mTitle.setCompoundDrawables(icon, null, null, null);

        return row;
    }       
}

public static class Holder {
    ImageView mIcon;
    TextView mTitle;        
}

问题是:图片无法显示。
3个回答

30

我将setCompoundDrawables更改为setCompoundDrawablesWithIntrinsicBounds,最终生效。


6

我知道这是一个老问题,但仍然相关(至少对于我而言;-)),所以也许其他人正在寻找答案。

尽管用户4294815的答案已经非常接近,但没有一个答案实际上描述了问题是什么。

之所以会出现这种情况,是因为您的图标尚未调用#setBounds(),因此它除了width = 0height = 0之外永远不会有任何大小。

此外,如果您查看#setCompoundDrawables()的文档,它实际上声明您需要在设置Drawable之前调用#setBounds()

/**
 * Sets the Drawables (if any) to appear to the left of, above, to the
 * right of, and below the text. Use {@code null} if you do not want a
 * Drawable there. The Drawables must already have had
 * {@link Drawable#setBounds} called.
 * <p>
 * Calling this method will overwrite any Drawables previously set using
 * {@link #setCompoundDrawablesRelative} or related methods.
 *
 * @attr ref android.R.styleable#TextView_drawableLeft
 * @attr ref android.R.styleable#TextView_drawableTop
 * @attr ref android.R.styleable#TextView_drawableRight
 * @attr ref android.R.styleable#TextView_drawableBottom
 */
现在要解决这个问题,你可以在Drawable上调用#setBounds(),或者如果你不直接使用Drawable,则必须使用#setCompoundDrawablesWithIntrinsicBounds()#setCompoundDrawablesRelativeWithIntrinsicBounds()。后者更为适当,因为它不使用leftright的命名,而是使用startend,因此图标将根据阅读方向进行设置。
我知道rkmax自己的答案回答了这个问题,或者至少提供了解决方案,但有时候光有答案还不够-解释问题的文字更为恰当并可以为下一个查看此问题的人提供澄清。

2
非常棒的答案,虽然setCompoundDrawablesWithIntrinsicBounds在我的设备上能够正常工作,但在Android 4.4上却不行。当我阅读了您的解释后,对于相对边界确实有了更深刻的理解。谢谢。 - Murtaza Khursheed Hussain

4

添加:

icon.setBounds(0, 0, your icon width, your icon height);

之前:

holder.mTitle.setCompoundDrawables(icon, null, null, null);

或者:

holder.mTitle.setCompoundDrawablesWithIntrinsicBounds(category.getStarred() == 1 ? R.drawable.starred : R.drawable.unstarred, null, null, null);

相反。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接