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.