Zmień programowo kolor do rysowania

149

Próbuję zmienić kolor na obrazie z białym znacznikiem za pomocą kodu. Wyczytałem, że poniższy kod powinien zmienić kolor, ale mój marker pozostaje biały.

Drawable.setColorFilter( 0xffff0000, Mode.MULTIPLY )

Przegapiłem coś? Czy istnieje inny sposób zmiany kolorów w moich elementach do rysowania znajdujących się w folderze res?

Johan
źródło
zaakceptowana odpowiedź nie działa dla mnie .. użyłem tego Jak odpowiedzieć [1], [1]: stackoverflow.com/questions/5940825/…
sham.y
Myślę, że wszystkie odpowiedzi tutaj zmieniają kolor tła, ale nie kolor obrazu. Mam rację? czy ktoś może mi powiedzieć, proszę? Wypróbowałem wszystkie rozwiązania tutaj, a także te same pytania dotyczące stackoverflow, ale w maju zmieniają one tylko kolor tła. Myślę więc, że możemy zmienić tylko kolor tła, ale nie kolor obrazu. Mam rację
Shirish Herwade

Odpowiedzi:

275

Spróbuj tego:

Drawable unwrappedDrawable = AppCompatResources.getDrawable(context, R.drawable.my_drawable); 
Drawable wrappedDrawable = DrawableCompat.wrap(unwrappedDrawable);
DrawableCompat.setTint(wrappedDrawable, Color.RED);    

Używanie DrawableCompatjest ważne, ponieważ zapewnia kompatybilność wsteczną i poprawki błędów na urządzeniach z interfejsem API 22 i wcześniejszych.

ρяσѕρєя K
źródło
Hmm, kolor pozostaje biały. Czy może to mieć coś wspólnego z OverlayItemsklasą hello mapview, która może powodować problem? To zwykły wyciąg z mojego folderu res, nic specjalnego ...
Johan
więc jakie było rozwiązanie?
speedynomads
30
Możesz preferować PorterDuff.Mode.SRC_IN, jeśli chcesz, aby działał z szerszą gamą kolorów źródłowych.
Lorne Laliberte
1
Konstruktor PorterDuffColorFilter przyjmuje format kolorów ARGB
RichX
1
będzie interesujące zmutować element do rysowania za pomocą #mutate (), aby uniknąć dzielenia jego stanu z jakimkolwiek innym elementem do rysowania, w przeciwnym razie, jeśli ponownie użyjesz rysunku, może mieć niewłaściwy kolor.
Ricard
130

Możesz spróbować tego w przypadku rysowania wektorów svg

DrawableCompat.setTint(
    DrawableCompat.wrap(myImageView.getDrawable()),
    ContextCompat.getColor(context, R.color.another_nice_color)
);
amorenew
źródło
4
Najlepszy sposób, jaki widziałem dla svg.
apSTRK
1
wolę tę od zaakceptowanej odpowiedzi, chociaż obie będą działać, ale z tą nie muszę się martwić o to, co można narysować, po prostu mam tę, która już tam jest i jest również kompatybilna wstecz, świetnie!
RJFares
1
Najlepsza odpowiedź, gdy nic nie działało, nie działa jak urok! Wielkie dzięki! Uwaga: To działa również, gdy masz rozciągliwej xml w ImageView / AppCompatImageView
SJD
1
Jak usunąć to programowo?
Hardik Joshi
1
@HardikJoshi Dokumentacja mówi: Aby usunąć odcień, przejdź nulldoDrawable#setTintList(ColorStateList)
arekolek
26

Konieczne może być wywołanie mutate () na rysowalnym lub wpłynie to na wszystkie ikony.

Drawable icon = ContextCompat.getDrawable(getContext(), R.drawable.ic_my_icon).mutate();
TypedValue typedValue = new TypedValue();
getContext().getTheme().resolveAttribute(R.attr.colorIcon, typedValue, true);
icon.setColorFilter(typedValue.data, PorterDuff.Mode.SRC_ATOP);
chytry
źródło
21

Innym sposobem na zrobienie tego w Lollipop, Android 5. + jest ustawienie odcienia na mapie bitowej, którą można narysować, na przykład:

<?xml version="1.0" encoding="utf-8"?>
<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/ic_back"
    android:tint="@color/red_tint"/>

To zadziała, jeśli masz ograniczoną liczbę kolorów, których chcesz użyć na swoich rysunkach. Sprawdź mój post na blogu, aby uzyskać więcej informacji .

MinceMan
źródło
2
Ładny! Przy okazji, wydaje się, że działa dobrze również w wersji pre-Lollipop. (Właśnie przetestowałem to na urządzeniu z minSdkVersion 16Androidem 4.1.1.)
Jonik
Podczas tworzenia mapy bitowej w ten sposób nie rozciąga się, aby dopasować ją do układu, tak jak podczas używania android:background="...". Dość dziwne!
Książę
Myślę, że to dlatego, że nie tworzysz tutaj dziewiątki.
MinceMan
Przepraszamy, ta strona nie istnieje = (
Phan Van Linh
@Jonik Odpowiedzi w zadanym pytaniu są nieistotne. To pytanie dotyczy sposobu zmiany koloru Drawable , a nie ImageView.
Antony.H
19

Możesz spróbować tego ImageView. za pomocą setColorFilter().

imageViewIcon.setColorFilter(ContextCompat.getColor(context, R.color.colorWhite));
Jaydip Meghapara
źródło
10

Możesz wypróbować ColorMatrixColorFilter, ponieważ Twoim kluczowym kolorem jest biały:

// Assuming "color" is your target color
float r = Color.red(color) / 255f;
float g = Color.green(color) / 255f;
float b = Color.blue(color) / 255f;

ColorMatrix cm = new ColorMatrix(new float[] {
        // Change red channel
        r, 0, 0, 0, 0,
        // Change green channel
        0, g, 0, 0, 0,
        // Change blue channel
        0, 0, b, 0, 0,
        // Keep alpha channel
        0, 0, 0, 1, 0,
});
ColorMatrixColorFilter cf = new ColorMatrixColorFilter(cm);
myDrawable.setColorFilter(cf);
tiguchi
źródło
Działa, gdy docelowy kolor nie jest przezroczysty
Malachiasz
10

Napisałem ogólną funkcję, w której można przekazać kontekst, ikona jest ikoną do rysowania / mipmap i nowy kolor, którego potrzebujesz dla tej ikony.

Ta funkcja zwraca drawable.

public static Drawable changeDrawableColor(Context context,int icon, int newColor) {
    Drawable mDrawable = ContextCompat.getDrawable(context, icon).mutate(); 
    mDrawable.setColorFilter(new PorterDuffColorFilter(newColor, PorterDuff.Mode.SRC_IN)); 
    return mDrawable;
} 

changeDrawableColor(getContext(),R.mipmap.ic_action_tune, Color.WHITE);
Sachin Tanpure
źródło
7

To zadziałało dla mnie. Upewnij się, że pomiędzy 0x a kodem koloru wpisałeś „ff”. W ten sposób 0xff2196F3

Drawable mDrawable = ContextCompat.getDrawable(MainActivity.this,R.drawable.ic_vector_home);
                    mDrawable.setColorFilter(new
                            PorterDuffColorFilter(0xff2196F3,PorterDuff.Mode.SRC_IN));
Bek
źródło
Cześć @Bek, witamy w stackoverflow. Jeśli to zadziałało, bardzo pomocne byłoby dołączenie pliku jsfiddle z minimalnym rozwiązaniem, aby to pokazać. Pomoże to osobie, która wysłała pytanie, właściwie zrozumieć.
Arjun Chaudhary
6

Taka sama, jak przyjęta odpowiedź, ale prostsza i wygodniejsza metoda:

val myDrawable = ContextCompat.getDrawable(context, R.drawable.my_drawable)
myDrawable.setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN)
setCompoundDrawablesWithIntrinsicBounds(myDrawable, null, null, null)

Uwaga, kod tutaj to Kotlin.

CorayThan
źródło
3

Możesz spróbować Mode.LIGHTENlub Mode.DARKEN. Javadoki z Androidem są okropne w wyjaśnianiu, co robią tryby PorterDuff. Możesz je obejrzeć tutaj: PorterDuff | Android

Proponuję rozejrzeć się po Compositing na stronie Mozilli tutaj. (Nie mają wszystkich trybów, które ma Android, ale mają ich dużo)

sebsebmc
źródło
3

Użyj tego: dla java

view.getBackground().setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_OVER)

dla Kotlin

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

możesz użyć PorterDuff.Mode.SRC_ATOP, jeśli twoje tło ma zaokrąglone rogi itp.

Ravi.Dudi
źródło
1

Składnia

"your image name".setColorFilter("your context".getResources().getColor("color name"));

Przykład

myImage.setColorFilter(mContext.getResources().getColor(R.color.deep_blue_new));
Om Prakash Sharma
źródło
1

Dla tych, którzy używają Kotlin prostej funkcji rozszerzenia:

fun Drawable.tint(context: Context,  @ColorRes color: Int) {
    DrawableCompat.setTint(this, context.resources.getColor(color, context.theme))
}

a potem po prostu zrób

background.tint(context, R.color.colorPrimary)
Chapz
źródło
0

Oto co zrobiłem:

public static Drawable changeDrawableColor(int drawableRes, int colorRes, Context context) {
    //Convert drawable res to bitmap
    final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), drawableRes);
    final Bitmap resultBitmap = Bitmap.createBitmap(bitmap, 0, 0,
            bitmap.getWidth() - 1, bitmap.getHeight() - 1);
    final Paint p = new Paint();
    final Canvas canvas = new Canvas(resultBitmap);
    canvas.drawBitmap(resultBitmap, 0, 0, p);

    //Create new drawable based on bitmap
    final Drawable drawable = new BitmapDrawable(context.getResources(), resultBitmap);
    drawable.setColorFilter(new
            PorterDuffColorFilter(context.getResources().getColor(colorRes), PorterDuff.Mode.MULTIPLY));
    return drawable;
}
Edwin
źródło
0

Po prostu użyj

    android:drawableTint="@color/primary_color"

w Twoim pliku XML. Zastąp podstawowy_kolor na niestandardowy kolor

Arvina Kori
źródło
0

Utwórz metodę w następujący sposób:

//CHANGE ICON COLOR
private void changeIconColor(Context context ,int drawable){
    Drawable unwrappedDrawable = AppCompatResources.getDrawable(context, drawable);
    assert unwrappedDrawable != null;
    Drawable wrappedDrawable = DrawableCompat.wrap(unwrappedDrawable);
    DrawableCompat.setTint(wrappedDrawable, getResources().getColor(R.color.colorAccent));
}

i używaj go tak:

    changeIconColor(this,R.drawable.ic_home);
sana ebadi
źródło
0

Najłatwiej to zrobić:

imageView.setColorFilter(Color.rgb(r, g b));

lub

imageView.setColorFilter(Color.argb(a, r, g, b));

a, r, g, b: wartości koloru argb.

Anubhav
źródło
Będzie to działać tylko wtedy, gdy OP użyje imageViews zamiast rysunków.
SowingFiber