【问题标题】:Set android shape color programmatically以编程方式设置 android 形状颜色
【发布时间】:2013-07-23 07:20:08
【问题描述】:

我正在编辑以使问题更简单,希望这有助于获得准确的答案。

假设我有以下oval 形状:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:angle="270"
           android:color="#FFFF0000"/>
    <stroke android:width="3dp"
            android:color="#FFAA0055"/>
</shape>

如何在活动类中以编程方式设置颜色?

【问题讨论】:

  • 你把这个drawable设置成什么?
  • drawable 是oval,是 ImageView 的背景。
  • 如果问的这个问题太难了,有没有办法在画布上绘制多个图像并将分层的最终产品设置为视图的背景?
  • 您可以通过扩展View 类并将其用作允许小部件重叠的布局中的base 视图(RelativeLayoutFrameLayout)来实现此目的。在这个扩展的View 类中,您可以draw multiple images onto a canvas。但是,在此之前,请先看看这个 --> Link(如果你还没有的话)。

标签: android android-layout shape


【解决方案1】:

这可能会有所帮助

1.初始设置形状颜色为透明

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
   <solid android:angle="270"
       android:color="@android:color/transparent"/>
   <stroke android:width="3dp"
        android:color="#FFAA0055"/>
</shape>
  1. 将形状设置为视图的背景

  2. 如下设置你喜欢的颜色:

    Drawable bg = view.getBackground();
    bg.setColorFilter(Color.parseColor("#Color"), PorterDuff.Mode.ADD);
    

【讨论】:

    【解决方案2】:

    更改自定义可绘制对象的纯色的最佳方法是 对于 Kotlin。

     (findViewById<TextView>(R.id.testing1).getBackground()).setColorFilter(Color.parseColor("#FFDE03"), PorterDuff.Mode.SRC_IN); 
    

    【讨论】:

      【解决方案3】:

      现在更简单的解决方案是使用您的形状作为背景,然后通过以下方式以编程方式更改其颜色:

      view.background.setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_ATOP)
      

      有关可用选项,请参阅 PorterDuff.Mode

      更新 (API 29):

      上述方法自 API 29 起已弃用,取而代之的是:

      view.background.colorFilter = BlendModeColorFilter(Color.parseColor("#343434"), BlendMode.SRC_ATOP)
      

      有关可用选项,请参阅 BlendMode

      【讨论】:

      • 正确的是:view.getBackground().setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_ATOP); 因为背景可能有边框或者圆角。
      • 不错的@BerkayTurancı 我的形状确实有圆角。我可以省略getBackground() 电话。我的 imageview.src 包含一个形状,我使用了:imageIndicator.setColorFilter(toggleColor, PorterDuff.Mode.SRC_ATOP); 其中toggleColor 只是一个以前存储 getColor() 的结果的 int
      • PorterDuff.Mode 用于BlendModeColorFilter 将无法编译,因为它需要BlendMode。所以对于 API 29,它应该是 view.background.colorFilter = BlendModeColorFilter(Color.parseColor("#343434"), BlendMode.SRC_ATOP)
      • 很好@Onik。我已经相应地更新了答案。谢谢!
      【解决方案4】:

      可能我来得太晚了。但是如果您使用的是 Kotlin。有这样的方法

      var gd = layoutMain.background as GradientDrawable
      
       //gd.setCornerRadius(10)
        gd.setColor(ContextCompat.getColor(ctx , R.color.lightblue))
        gd.setStroke(1, ContextCompat.getColor(ctx , R.color.colorPrimary)) // (Strokewidth,colorId)
      

      享受....

      【讨论】:

        【解决方案5】:

        对于任何使用 C# Xamarin 的人,这里有一个基于 Vikram 的 sn-p 的方法:

        private void SetDrawableColor(Drawable drawable, Android.Graphics.Color color)
        {
            switch (drawable)
            {
                case ShapeDrawable sd:
                    sd.Paint.Color = color;
                    break;
                case GradientDrawable gd:
                    gd.SetColor(color);
                    break;
                case ColorDrawable cd:
                    cd.Color = color;
                    break;
            }
        }
        

        【讨论】:

          【解决方案6】:

          我的 Kotlin 扩展功能版本基于上述答案与 Compat

          fun Drawable.overrideColor_Ext(context: Context, colorInt: Int) {
              val muted = this.mutate()
              when (muted) {
                  is GradientDrawable -> muted.setColor(ContextCompat.getColor(context, colorInt))
                  is ShapeDrawable -> muted.paint.setColor(ContextCompat.getColor(context, colorInt))
                  is ColorDrawable -> muted.setColor(ContextCompat.getColor(context, colorInt))
                  else -> Log.d("Tag", "Not a valid background type")
              }
          }
          

          【讨论】:

            【解决方案7】:

            没有什么对我有用,但是当我设置着色颜色时,它适用于 Shape Drawable

             Drawable background = imageView.getBackground();
             background.setTint(getRandomColor())
            

            需要安卓 5.0 API 21

            【讨论】:

            • 优雅的解决方案。简单且完美无瑕。
            • 不错的短解决方案!
            【解决方案8】:

            半径填充形状的简单方法是:

            (view.getBackground()).setColorFilter(Color.parseColor("#FFDE03"), PorterDuff.Mode.SRC_IN);
            

            【讨论】:

              【解决方案9】:

              这个问题不久前就得到了回答,但它可以通过重写为 kotlin 扩展函数来现代化。

              fun Drawable.overrideColor(@ColorInt colorInt: Int) {
                  when (this) {
                      is GradientDrawable -> setColor(colorInt)
                      is ShapeDrawable -> paint.color = colorInt
                      is ColorDrawable -> color = colorInt
                  }
              }
              

              【讨论】:

              • 不错的答案!谢谢你!
              【解决方案10】:

              注意:答案已更新以涵盖backgroundColorDrawable 实例的情况。感谢Tyler Pfaff 指出这一点。

              drawable 是一个椭圆,是 ImageView 的背景

              使用getBackground()imageView获取Drawable

              Drawable background = imageView.getBackground();
              

              检查通常的嫌疑人:

              if (background instanceof ShapeDrawable) {
                  // cast to 'ShapeDrawable'
                  ShapeDrawable shapeDrawable = (ShapeDrawable) background;
                  shapeDrawable.getPaint().setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
              } else if (background instanceof GradientDrawable) {
                  // cast to 'GradientDrawable'
                  GradientDrawable gradientDrawable = (GradientDrawable) background;
                  gradientDrawable.setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
              } else if (background instanceof ColorDrawable) {
                  // alpha value may need to be set again after this call
                  ColorDrawable colorDrawable = (ColorDrawable) background;
                  colorDrawable.setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
              }
              

              精简版:

              Drawable background = imageView.getBackground();
              if (background instanceof ShapeDrawable) {
                  ((ShapeDrawable)background).getPaint().setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
              } else if (background instanceof GradientDrawable) {
                  ((GradientDrawable)background).setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
              } else if (background instanceof ColorDrawable) {
                  ((ColorDrawable)background).setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
              }
              

              请注意,不需要检查空值。

              但是,如果在其他地方使用它们,您应该在修改它们之前在可绘制对象上使用mutate()。 (默认情况下,从 XML 加载的可绘制对象共享相同的状态。)

              【讨论】:

              • 感谢您的回答。 (+1)。我的代码遇到了其他错误,因此很难测试。但这仍然可能设置形状的solid 部分。 stroke 部分怎么样?
              • @TiGer 您应该在评论中添加@username 以确保向用户发送通知。顺便说一句,您需要继承ShapeDrawable 才能设置笔画部分。更多信息在这里:Link。查看评论,因为它提到了接受的答案存在问题。
              • android.graphics.drawable.GradientDrawable 无法转换为 android.graphics.drawable.ShapeDrawable 我的转换失败
              • @John 如果您的ImageView's 背景设置为GradientDrawablegetBackground() 将不会返回ShapeDrawable。相反,请使用返回的GradientDrawableGradientDrawable gradientDrawable = (GradientDrawable)imageView.getBackground();....gradientDrawable.setColors(new int[] { color1, color2 });
              • 谢谢 .. 拯救了我的世界。
              【解决方案11】:

              扩展Vikram's 答案,如果您正在为动态视图着色,例如回收器视图项目等......那么您可能想在设置颜色之前调用 mutate() 。如果您不这样做,任何具有公共可绘制对象(即背景)的视图也将更改/着色其可绘制对象。

              public static void setBackgroundColorAndRetainShape(final int color, final Drawable background) {
              
                  if (background instanceof ShapeDrawable) {
                      ((ShapeDrawable) background.mutate()).getPaint().setColor(color);
                  } else if (background instanceof GradientDrawable) {
                      ((GradientDrawable) background.mutate()).setColor(color);
                  } else if (background instanceof ColorDrawable) {
                      ((ColorDrawable) background.mutate()).setColor(color);
                  }else{
                      Log.w(TAG,"Not a valid background type");
                  }
              
              }
              

              【讨论】:

              • 需要和额外的检查和参数:if (background instanceof LayerDrawable) { background = ((LayerDrawable) background.mutate()).getDrawable(indexIfLayerDrawable); } if (background instanceof ShapeDrawable)[...] 来处理使用&lt;layer-list ... &lt;item ... 的背景布局。
              【解决方案12】:

              这是对我有用的解决方案......也在另一个问题中写了它: How to change shape color dynamically?

              //get the image button by id
              ImageButton myImg = (ImageButton) findViewById(R.id.some_id);
              
              //get drawable from image button
              GradientDrawable drawable = (GradientDrawable) myImg.getDrawable();
              
              //set color as integer
              //can use Color.parseColor(color) if color is a string
              drawable.setColor(color)
              

              【讨论】:

                【解决方案13】:

                希望这能帮助遇到同样问题的人

                GradientDrawable gd = (GradientDrawable) YourImageView.getBackground();
                //To shange the solid color
                gd.setColor(yourColor)
                
                //To change the stroke color
                int width_px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, youStrokeWidth, getResources().getDisplayMetrics());
                gd.setStroke(width_px, yourColor);
                

                【讨论】:

                • 最初我无法让它工作,我发现 yourColor 必须像这样提供:gd.setStroke(width_px, Color.parseColor("#FF5722"));
                【解决方案14】:

                这样做:

                    ImageView imgIcon = findViewById(R.id.imgIcon);
                    GradientDrawable backgroundGradient = (GradientDrawable)imgIcon.getBackground();
                    backgroundGradient.setColor(getResources().getColor(R.color.yellow));
                

                【讨论】:

                • @user3111850 在调用getBackground() 之前,您是否在xml 甚至setBackgroundin 活动中添加了android:background?如果你这样做了,它应该可以工作。
                • 工作就像一个魅力!
                【解决方案15】:

                试试这个:

                 public void setGradientColors(int bottomColor, int topColor) {
                 GradientDrawable gradient = new GradientDrawable(Orientation.BOTTOM_TOP, new int[]  
                 {bottomColor, topColor});
                 gradient.setShape(GradientDrawable.RECTANGLE);
                 gradient.setCornerRadius(10.f);
                 this.setBackgroundDrawable(gradient);
                 }
                

                更多详情请查看此链接this

                希望帮助。

                【讨论】:

                • 对该链接投赞成票。但这不是我问题的答案。
                猜你喜欢
                • 1970-01-01
                • 2015-07-01
                • 2015-09-20
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-02-17
                • 2016-11-07
                相关资源
                最近更新 更多