如何在Android按钮上以编程方式设置drawableLeft?

535

我正在动态创建按钮。首先使用XML对其进行样式设置,现在我正在尝试使用下面的XML以编程方式创建它们。

<Button
    android:id="@+id/buttonIdDoesntMatter"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:text="buttonName"
    android:drawableLeft="@drawable/imageWillChange"
    android:onClick="listener"
    android:layout_width="fill_parent">
</Button>

这是我目前的进展。除了drawable之外,我什么都可以做。

linear = (LinearLayout) findViewById(R.id.LinearView);
Button button = new Button(this);
button.setText("Button");
button.setOnClickListener(listener);
button.setLayoutParams(
    new LayoutParams(
        android.view.ViewGroup.LayoutParams.FILL_PARENT,         
        android.view.ViewGroup.LayoutParams.WRAP_CONTENT
    )
);      

linear.addView(button);
14个回答

1219

您可以使用setCompoundDrawables方法来实现此操作。请参见此处的示例。我在不使用setBounds的情况下使用了它,它起作用了。你可以尝试任何一种方式。

更新:如果链接失效,这里复制代码

Drawable img = getContext().getResources().getDrawable(R.drawable.smiley);
img.setBounds(0, 0, 60, 60);
txtVw.setCompoundDrawables(img, null, null, null);

或者

Drawable img = getContext().getResources().getDrawable(R.drawable.smiley);
txtVw.setCompoundDrawablesWithIntrinsicBounds(img, null, null, null);

或者

txtVw.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);

@Varun,@Tigger:我有一个问题:我的文件管理器使用文本视图和文件夹图标作为drawableLeft在列表视图中显示文件夹。我尝试了你们在这里的建议,在单击没有读取权限的文件夹时设置“禁止图标”,它有效。但是,当你更改文件夹并重新加载适配器时,禁止图标仍然存在(即drawableLeft没有重新绘制)。你们知道如何将notifyDataSetChanged应用于drawableLeft,而不需要进行循环吗?谢谢! - Luis A. Florit
@LuisA.Florit,听起来你有一个关于数据更改时重新绘制Listview项的问题——这与此问题或答案没有真正的关系。我建议你发一个问题而不是评论。 - Tigger
@Tigger:好的,我也使用了你的技巧将图标恢复到原来的状态,并循环遍历了禁止访问的目录。也许这比重新绘制所有ListView项目更好...无论如何,谢谢! - Luis A. Florit
4
我在我的应用程序中看到了一些奇怪的东西。如果我在layout.xml中定义了drawableRight,那么setCompoundDrawablesWithIntrinsicBounds (0, 0, R.drawable.money, 0)将不起作用。如果我在onCreate()中设置原始图标,则更改会生效。这可能与API 19有关吗? - injecteer
1
drawableStartdrawableEnd 怎么样? - MHSaffari
显示剩余5条评论

132

你也可以简单地尝试这个。

txtVw.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);

4
应将R.drawable.smiley放在第一个0的位置,而不是最后一个,因为该方法的定义是:{public void setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom)}。 - arniotaki
我该如何添加填充?这种方式在可绘制对象和文本之间没有太多填充。 - AdamMc331

39

Kotlin版本

使用以下代码片段为按钮添加左侧Drawable:

val drawable = ContextCompat.getDrawable(context, R.drawable.ic_favorite_white_16dp)
button.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)

Android矢量图的重要使用点

当您使用Android矢量图形并希望向后兼容API低于21时,请添加以下代码:

在应用级别的build.gradle中:

android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

在 Application 类中:

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
    }

}

一个更简单的方法,也适用于我:button.setCompoundDrawablesWithIntrinsicBounds(getDrawable(R.drawable.ic_favorite_white_16dp), null, null, null) - juangalf
2
你是对的,但是Context#.getDrawable(resId)已经被弃用了,所以使用它可能会导致一些问题。 - aminography
可以在不添加Application类的情况下工作,因为我没有这个类。 - Mark Delphi

29
myEdtiText.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);

24

对我来说,它起了作用:

button.setCompoundDrawablesWithIntrinsicBounds(com.example.project1.R.drawable.ic_launcher, 0, 0, 0);

10

对我很有用。将可绘制设置为右侧

tvBioLive.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_close_red_400_24dp, 0)

9

如果你正在使用 drawableStart, drawableEnd, drawableTop 或者 drawableBottom; 你必须使用 "setCompoundDrawablesRelativeWithIntrinsicBounds"

edittext.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.anim_search_to_close, 0)

6
我做了这件事:
 // Left, top, right, bottom drawables.
            Drawable[] drawables = button.getCompoundDrawables();
            // get left drawable.
            Drawable leftCompoundDrawable = drawables[0];
            // get new drawable.
            Drawable img = getContext().getResources().getDrawable(R.drawable.ic_launcher);
            // set image size (don't change the size values)
            img.setBounds(leftCompoundDrawable.getBounds());
            // set new drawable
            button.setCompoundDrawables(img, null, null, null);

4

正如@Jérémy Reynaud指出的那样,如此描述在这个答案中,最安全的方法来设置左侧drawable而不改变其他drawables(顶部,右侧和底部)的值是通过使用按钮以前的值与setCompoundDrawablesWithIntrinsicBounds

Drawable leftDrawable = getContext().getResources()
                          .getDrawable(R.drawable.yourdrawable);

// Or use ContextCompat
// Drawable leftDrawable = ContextCompat.getDrawable(getContext(),
//                                        R.drawable.yourdrawable);

Drawable[] drawables = button.getCompoundDrawables();
button.setCompoundDrawablesWithIntrinsicBounds(leftDrawable,drawables[1],
                                               drawables[2], drawables[3]);

因此,您之前的所有可绘制内容都将被保留。


4
可能会有帮助:
TextView location;
location=(TextView)view.findViewById(R.id.complain_location);
//in parameter (left,top,right,bottom) any where you wnat to put
location.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.arrow,0);

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