Android şekil rengini programlı olarak ayarlama


168

Doğru cevaba yardımcı olacağını umarak soruyu daha basit hale getirmek için düzenliyorum.

Aşağıdaki ovalşekle sahip olduğumu söyle :

<?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>

Bir aktivite sınıfının içinden rengi programlı olarak nasıl ayarlarım?


Bu çekmeceyi ne olarak ayarlıyorsunuz?
Vikram

Çekilebilir bir ovalve bir ImageView arka planıdır.
Cote Mounyo

Sorulduğu gibi bu soru çok zorsa, bir tuval üzerine birden fazla resim çizmenin ve katmanlı son ürünü bir görünümün arka planı olarak ayarlamanın bir yolu var mı?
Cote Mounyo

ViewSınıfı genişleterek ve basewidget'ların çakışmasına izin veren bir mizanpajda görünüm olarak kullanarak bunu başarabilirsiniz ( RelativeLayout, FrameLayout). Bu genişletilmiş Viewsınıfın içinde yapabilirsiniz draw multiple images onto a canvas. Ancak bunu yapmadan önce şuna bir göz atın -> Bağlantı (henüz yapmadıysanız).
Vikram

Yanıtlar:


266

Not : Yanıt, backgroundörneğinin bulunduğu senaryoyu kapsayacak şekilde güncellendi ColorDrawable. Bunu gösterdiğin için teşekkürler Tyler Pfaff .

Çekilebilir oval ve ImageView öğesinin arka planıdır

Get Drawablegelen imageViewkullanılarak getBackground():

Drawable background = imageView.getBackground();

Olağan şüphelilere karşı kontrol edin:

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));
}

Kompakt versiyon:

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));
}

Boş denetimin gerekli olmadığını unutmayın.

Ancak, mutate()başka bir yerde kullanılıyorlarsa, değiştirilmeden önce çekmeceleri kullanmalısınız . (Varsayılan olarak, XML'den yüklenen çekilebilirler aynı durumu paylaşır.)


3
Cevapladığınız için teşekkürler. (1). Kodumda başka hatalar var, bu yüzden test etmek zor. Ama yine de bu solidşeklin bir kısmını ayarlayabilir . Peki ya strokekısmı?
Cote Mounyo

1
@TiGer @usernameKullanıcıya bir bildirim gönderildiğinden emin olmak için yorumunuzu eklemelisiniz . Bu arada, ShapeDrawablekontur bölümünü ayarlamak için alt sınıfa ihtiyacınız olacaktır . Daha fazla bilgi burada: Bağlantı . Yoruma, kabul edilen cevapla ilgili bir sorundan bahsederken bakın.
Vikram

3
android.graphics.drawable.GradientDrawable android.graphics.drawable.ShapeDrawable artığını olamaz döküm üzerime başarısız
John

3
Senin Eğer @John ImageView'sarka plan bir ayarlandığında GradientDrawable, getBackground()bir döndürmez ShapeDrawable. Bunun yerine, kullanmak GradientDrawable: döndürülen GradientDrawable gradientDrawable = (GradientDrawable)imageView.getBackground();.... gradientDrawable.setColors(new int[] { color1, color2 });.
Vikram

2
Teşekkürler .. dünyamı kurtardım.
sid_09

43

Şunu yapın:

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

1
@ user3111850 Aramadan önce xml'nize android:backgroundhatta setBackgroundetkinliğinize eklediniz mi getBackground()? Bunu yapmış olsaydınız işe yarayacaktır.
Lee Yi Hong

41

Günümüzde daha basit bir çözüm, şeklinizi arka plan olarak kullanmak ve daha sonra rengini program aracılığıyla değiştirmek olacaktır:

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

Kullanılabilir seçenekler için PorterDuff.Mode'a bakın .

GÜNCELLEME (API 29):

Yukarıdaki yöntem API 29'dan beri kullanımdan kaldırılmıştır ve aşağıdaki ile değiştirilmiştir:

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

Kullanılabilir seçenekler için BlendMode'a bakın .


4
Doğru olan: view.getBackground().setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_ATOP);Arka planda veya yuvarlak kuryelarda bir sınır olabileceğinden.
Berkay Turancı

1
Güzel bir @ @ BerkayTurancı Şeklimin köşeleri yuvarlatılmıştı. getBackground()Aramayı ihmal edebilirim. Benim imageview.src bir şekil içerdiği ve ben kullandı: imageIndicator.setColorFilter(toggleColor, PorterDuff.Mode.SRC_ATOP);nerede toggleColordaha önce GetColor () sonucunu saklanan bu sadece bir int
Birisi bir yerde

1
Having PorterDuff.Modeiçin BlendModeColorFiltergerek duyduğu derlemek olmaz BlendMode. Dolayısıyla API 29 için olması gerekir view.background.colorFilter = BlendModeColorFilter(Color.parseColor("#343434"), BlendMode.SRC_ATOP).
Onik

İyi yakalama @Onik. Cevabı buna göre güncelledim. Teşekkür ederim!
Georgios

14

Bunu dene:

 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);
 }

Daha fazla ayrıntı için bu bağlantıyı kontrol bu

umut yardım.


bağlantı için oy verin. Ama bu sorumun cevabı değil.
Cote Mounyo

13

Umarım bu aynı sorunu olan birine yardımcı olur

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);

1
Başlangıçta bu işe yaramadı, ben senin renk böyle sağlanmalıdır anladım :gd.setStroke(width_px, Color.parseColor("#FF5722"));
pwnsauce

12

Vikram'ın cevabını genişleterek, geri dönüşümcü görünüm öğeleri gibi dinamik görünümleri renklendiriyorsanız .... O zaman muhtemelen rengi ayarlamadan önce mutate () öğesini çağırmak istersiniz. Bunu yapmazsanız, ortak bir çekilebilir (yani bir arka plan) olan görünümlerin de çekilebilir / renkli olması gerekir.

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");
    }

}

3
ihtiyaçları ve ekstra kontrol ve parametre: if (background instanceof LayerDrawable) { background = ((LayerDrawable) background.mutate()).getDrawable(indexIfLayerDrawable); } if (background instanceof ShapeDrawable)[...]kullanılan arka plan düzenleri ile başa çıkmak için <layer-list ... <item ....
Johny

11

Bu soru bir süre önce cevaplandı, ancak bir kotlin uzatma fonksiyonu olarak yeniden yazılarak modernize edilebilir.

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

7

benim için çalışan çözüm ... başka bir soruya da yazdı: Şekil rengini dinamik olarak nasıl değiştirebilirim?

//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)

4

Benim için hiçbir şey işe yaramaz ama renk tonunu ayarladığımda Shape Drawable'da çalışır

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

android 5.0 API 21 gerektirir


3

Benim Kotlin uzatma fonksiyonu ile yukarıdaki yanıtlara dayalı versiyon 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")
    }
}

1

Şekli Yarıçap ile doldurmanın basit yolu :

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

1

Belki çok geç kaldım ama Kotlin kullanıyorsanız. Böyle bir yol var

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)

Zevk almak....


0

C # Xamarin kullanan herkes için, burada Vikram'ın snippet'ine dayanan bir yöntem vardır:

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;
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.