Jak ustawić odcień dla widoku obrazu programowo w Androidzie?

396

Muszę ustawić odcień dla widoku obrazu ... Używam go w następujący sposób:

imageView.setColorFilter(R.color.blue,android.graphics.PorterDuff.Mode.MULTIPLY);

Ale to się nie zmienia ...

Alexander Farber
źródło
15
Być może użyłeś identyfikatora zasobu liczby całkowitej zamiast wartości koloru całkowitego, spróbuj przekonwertować R.color.blue na getResources (). GetColor (R.color.blue)
milosmns
Wyciągany ciągnienia = ...; drawable.setColorFilter (ContextCompat.getColor (kontekst, R.color.biały), PorterDuff.Mode.DST); imageView.setImageDrawable (rysowany); // można tutaj użyć dowolnego koloru
flame3

Odpowiedzi:

916

Możesz zmienić odcień, dość łatwo w kodzie poprzez:

imageView.setColorFilter(Color.argb(255, 255, 255, 255)); // biały odcień

Jeśli chcesz odcień koloru, to

imageView.setColorFilter(ContextCompat.getColor(context, R.color.COLOR_YOUR_COLOR), android.graphics.PorterDuff.Mode.MULTIPLY);

Do rysowania wektorowego

imageView.setColorFilter(ContextCompat.getColor(context, R.color.COLOR_YOUR_COLOR), android.graphics.PorterDuff.Mode.SRC_IN);

AKTUALIZACJA :
@ADev ma nowsze rozwiązanie w swojej odpowiedzi tutaj , ale jego rozwiązanie wymaga nowszej biblioteki wsparcia - 25.4.0 lub wyższej.

Hardik
źródło
12
W xml android: tint = "@ color / blue"
Luis
1
Plus android: odcień to 21+
androidguy
8
android:tintdziała na wszystkich wersjach Androida. Może mówisz o drawableTint?
finstas,
11
PorterDuff.Mode.MULTIPLY nie działa w mojej sytuacji użyłem PorterDuff.Mode.SRC_IN i działa
Mohamed Nageh
234

Większość odpowiedzi odnosi się do używania, setColorFilterktóre nie jest tym, o co pierwotnie pytano.

Użytkownik @Tad ma swoją odpowiedź we właściwym kierunku, ale działa tylko na API 21+.

Aby ustawić odcień we wszystkich wersjach Androida, użyj ImageViewCompat:

ImageViewCompat.setImageTintList(imageView, ColorStateList.valueOf(yourTint));

Zauważ, że yourTintw tym przypadku musi być „int kolor”. Jeśli masz taki zasób koloru R.color.blue, musisz najpierw załadować kolor int:

ContextCompat.getColor(context, R.color.blue);
ADev
źródło
6
Powinna być zaakceptowana odpowiedź. Zauważ, że działa tylko na ImageViewinstancjach xml z kompozycją AppCompat lub na AppCompatImageViewpodklasach.
Louis
1
@ ADev doceniamy twoje rozwiązanie, ale pytanie zostało zadane w 2013 r. Oraz ImageViewCompat i AppCompatImageView wersja z obsługą v4 lib 25.4.0 odpowiednio w czerwcu 2017 r. I 25.1.0 grudnia 2016 r.
Hardik
1
@ ADev oczywiście, ale nie wspomniałeś o tym poprawnie w odpowiedzi, że twoje rozwiązanie jest nowe i wymaga nowszej biblioteki wsparcia 25.4.0 i wyższej, ponieważ przy niższej wersji lib wsparcia ta klasa nie jest dostępna, więc nikt nie mógł jej znaleźć !! !! tak przy okazji, zredagowałem odpowiedź :) dzień dobry ...
Hardik
To nie działa na API 16.
Tayyab Mazhar
49

To zadziałało dla mnie

mImageView.setColorFilter(ContextCompat.getColor(getContext(), R.color.green_500));
toobsco42
źródło
tak, pracowałem też dla mnie, bez drugiego parametru .. to też może pójśćmImageView.setColorFilter(getContext().getResources().getColor(R.color.green_500));
Biskrem Muhammad
pozytywnie oceniany i bez drugiego parametru działa jak urok. Dzięki @ toobsco42
Ravi Vaniya
35

@Hardik ma rację. Innym błędem w kodzie jest odniesienie do koloru zdefiniowanego w XML. Przekazałeś tylko identyfikator do setColorFiltermetody, kiedy powinieneś użyć identyfikatora do zlokalizowania zasobu kolorów i przekazać zasób do setColorFiltermetody. Przepisz swój oryginalny kod poniżej.

Jeśli ten wiersz mieści się w Twojej aktywności:

imageView.setColorFilter(getResources().getColor(R.color.blue), android.graphics.PorterDuff.Mode.MULTIPLY);

W przeciwnym razie musisz odwołać się do swojej głównej działalności:

Activity main = ...
imageView.setColorFilter(main.getResources().getColor(R.color.blue), android.graphics.PorterDuff.Mode.MULTIPLY);

Zauważ, że dotyczy to również innych rodzajów zasobów, takich jak liczby całkowite, boole, wymiary itp. Z wyjątkiem łańcucha, do którego możesz bezpośrednio użyć getString()w swojej aktywności bez konieczności pierwszego połączenia getResources()(nie pytaj mnie dlaczego) .

W przeciwnym razie kod wygląda dobrze. (Chociaż nie badałem setColorFilterzbytnio tej metody ...)

CrepeGoat
źródło
22

Po wypróbowaniu wszystkich metod i one nie działały dla mnie.

Otrzymuję rozwiązanie za pomocą innego PortDuff.MODE.

imgEstadoBillete.setColorFilter(context.getResources().getColor(R.color.green),PorterDuff.Mode.SRC_IN);
Catluc
źródło
14

Począwszy od Lollipop, istnieje również metoda odcień dla BitmapDrawables, która działa z nową klasą Palette:

public void setTintList (odcień ColorStateList)

i

public void setTintMode (PorterDuff.Mode tintMode)

W starszych wersjach Androida możesz teraz korzystać z biblioteki DrawableCompat

Berbeć
źródło
2
tak naprawdę biblioteka wsparcia to obsługuje. zobacz moją odpowiedź: stackoverflow.com/a/34479043/878126
programista Androida
12

Spróbuj tego. Powinien działać na wszystkich wersjach Androida obsługiwanych przez bibliotekę wsparcia:

public static Drawable getTintedDrawableOfColorResId(@NonNull Context context, @NonNull Bitmap inputBitmap, @ColorRes int colorResId) {
    return getTintedDrawable(context, new BitmapDrawable(context.getResources(), inputBitmap), ContextCompat.getColor(context, colorResId));
}

public static Drawable getTintedDrawable(@NonNull Context context, @NonNull Bitmap inputBitmap, @ColorInt int color) {
    return getTintedDrawable(context, new BitmapDrawable(context.getResources(), inputBitmap), color);
}

public static Drawable getTintedDrawable(@NonNull Context context, @NonNull Drawable inputDrawable, @ColorInt int color) {
    Drawable wrapDrawable = DrawableCompat.wrap(inputDrawable);
    DrawableCompat.setTint(wrapDrawable, color);
    DrawableCompat.setTintMode(wrapDrawable, PorterDuff.Mode.SRC_IN);
    return wrapDrawable;
}

Możesz użyć dowolnego z powyższych, aby to działało.

O ciekawszych funkcjach DrawableCompat można przeczytać w dokumentacji tutaj .

programista Androida
źródło
1
Musiałem także zrobić, imageView.getBackground()aby uzyskać możliwość losowania, ponieważ zwracał imageView.getDrawable()zero.
Rock Lee
@RockLee upewnij się, że użyłeś src w widoku obrazu xml lub setImageResource w kodzie
orelzion
jest to idealny sposób na ustawienie koloru odcienia tła
podglądu obrazu
12

Lepsza uproszczona funkcja rozszerzenia dzięki ADev

fun ImageView.setTint(@ColorRes colorRes: Int) {
    ImageViewCompat.setImageTintList(this, ColorStateList.valueOf(ContextCompat.getColor(context, colorRes)))
}

Stosowanie:-

imageView.setTint(R.color.tintColor)
Manohar Reddy
źródło
Czy istnieje podobny odcień tekstu przycisku / TextView?
programista Androida
masz na myśli kolor tekstu lub odcień tekstu w widoku tekstowym do rysowania?
Manohar Reddy
Mam na myśli „odcień tekstu”. Kolor tekstu. Ale myślę, że jest to dość problematyczne, ponieważ tekst ma kolor dla każdego stanu ... Z drugiej strony, jak to działa, kiedy ustawiam kolor akcentu ... Dziwne ... Czy to możliwe, że można ustawić kolor akcentu na konkretny przycisk (lub TextView), programowo?
programista Androida
11

Jeśli kolor ma przezroczystość szesnastkową, użyj poniższego kodu.

ImageViewCompat.setImageTintMode(imageView, PorterDuff.Mode.SRC_ATOP);
ImageViewCompat.setImageTintList(imageView, ColorStateList.valueOf(Color.parseColor("#80000000")));

Aby usunąć odcień

ImageViewCompat.setImageTintList(imageView, null);
Sai
źródło
jaki jest typ „img”
Beyaz
1
@Beyaz imgjest typu ImageView.
Sai
10

Prosta i jedna linia

imageView.setColorFilter(activity.getResources().getColor(R.color.your_color));
Gautam Surani
źródło
9

Ponieważ pierwsza odpowiedź nie zadziałała dla mnie:

//get ImageView
ImageView myImageView = (ImageView) findViewById(R.id.iv);

//colorid is the id of a color defined in values/colors.xml
myImageView.setImageTintList(ColorStateList.valueOf(ContextCompat.getColor(getApplicationContext(), R.color.colorid)));

Wydaje się, że działa to tylko w API 21+, ale dla mnie to nie był problem. Do rozwiązania tego problemu można użyć ImageViewCompat.

Mam nadzieję, że pomogłem komukolwiek :-)

Felix
źródło
7

Począwszy od Lollipop, istnieje metoda o nazwie ImageView#setImageTintList(), której można użyć ... zaletą jest to, że zajmuje ona ColorStateListzamiast jednego koloru, dzięki czemu odcień obrazu jest rozpoznawany przez stan.

Na urządzeniach z wersją wcześniejszą niż Lollipop można uzyskać takie samo zachowanie, odbarwiając obszar do rysowania, a następnie ustawiając go jako ImageViewobraz do rysowania:

ColorStateList csl = AppCompatResources.getColorStateList(context, R.color.my_clr_selector);
Drawable drawable = DrawableCompat.wrap(imageView.getDrawable());
DrawableCompat.setTintList(drawable, csl);
imageView.setImageDrawable(drawable);
Alex Lockwood
źródło
6
Random random=new Random;
ImageView imageView = (ImageView) view.findViewById(R.id.imageView);
ColorFilter cf = new PorterDuffColorFilter(Color.rgb(random.nextInt(255), random.nextInt(255), random.nextInt(255)),Mode.OVERLAY);

imageView.setImageResource(R.drawable.ic_bg_box);
imageView.setColorFilter(cf);
Pawan asati
źródło
6

Do ustawiania odcienia dla widoku obrazu programowo w Androidzie

Mam dwie metody dla Androida:

1)

imgView.setColorFilter(context.getResources().getColor(R.color.blue));

2)

 DrawableCompat.setTint(imgView.getDrawable(),
                     ContextCompat.getColor(context, R.color.blue));

Mam nadzieję, że pomogłem komukolwiek :-)

Abhign01
źródło
4

Dodając do ADev „s odpowiedź (co moim zdaniem jest najbardziej poprawne), od powszechnego przyjęcia Kotlin, a jej użytecznych funkcji rozszerzających:

fun ImageView.setTint(context: Context, @ColorRes colorId: Int) {
    val color = ContextCompat.getColor(context, colorId)
    val colorStateList = ColorStateList.valueOf(color)
    ImageViewCompat.setImageTintList(this, colorStateList)
}

Myślę, że jest to funkcja, która może być przydatna w każdym projekcie na Androida!

Cillian Myles
źródło
4

Zauważyłem, że możemy użyć selektora kolorów dla atrybutu tint:

mImageView.setEnabled(true);

activity_main.xml:

<ImageView
    android:id="@+id/image_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_arrowup"
    android:tint="@color/section_arrowup_color" />

section_arrowup_color.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@android:color/white" android:state_enabled="true"/>
    <item android:color="@android:color/black" android:state_enabled="false"/>
    <item android:color="@android:color/white"/>
</selector>
NickUnuchek
źródło
Cześć, to nie działa dla wektorowych drawables .. Jakieś obejście tego samego?
Manukumar
@Manukumar Użyj app:srcCompatzamiast android:srci dodaj vectorDrawables.useSupportLibrary = truedo defaultConfigczęści pliku build.gradle. Przetestowano pod kątem poprawnego działania na emulatorze KitKat.
programista Androida
3

Nie używaj PoterDuff.Mode, użyj setColorFilter()działa dla wszystkich.

ImageView imageView = (ImageView) listItem.findViewById(R.id.imageView);
imageView.setColorFilter(getContext().getResources().getColor(R.color.msg_read));
Vikash Sharma
źródło
2

Jak powiedział @mosmosmns, powinieneś użyć imageView.setColorFilter(getResouces().getColor(R.color.blue),android.graphics.PorterDuff.Mode.MULTIPLY);

Ten interfejs API wymaga wartości koloru zamiast identyfikatora zasobu koloru. Jest to główna przyczyna, dla której twoje polecenie nie działa.

Przystojniak
źródło
2

Jestem spóźniony na przyjęciu, ale nie widziałem powyżej mojego rozwiązania. Jesteśmy również w stanie ustawić kolor odcienia setImageResource()(moja minSdkVersion to 24).

Najpierw musisz utworzyć selektor i zapisać go w /drawablefolderze zasobów (nazywam to ic_color_white_green_search.xml)

<!-- Focused and not pressed -->
<item android:state_focused="true"
      android:state_pressed="false">

    <bitmap android:src="@drawable/ic_search"
            android:tint="@color/branding_green"/>
</item>

<!-- Focused and pressed -->
<item android:state_focused="true"
      android:state_pressed="true">

    <bitmap android:src="@drawable/ic_search"
            android:tint="@color/branding_green"/>
</item>

<!-- Default -->
<item android:drawable="@drawable/ic_search"/>

Następnie ustaw go w taki sposób:

val icon = itemView.findViewById(R.id.icon) as ImageButton
icon.setImageResource(R.drawable.ic_color_white_green_search)
Hesam
źródło
2

W przypadku, gdy chcesz ustawić selektor na swój odcień:

ImageViewCompat.setImageTintList(iv, getResources().getColorStateList(R.color.app_icon_click_color));
Yusril Maulidan Raji
źródło
0

Rozwiązanie Kotlin wykorzystujące funkcję rozszerzenia do ustawiania i wyłączania barwienia:

fun ImageView.setTint(@ColorInt color: Int?) {
    if (color == null) {
        ImageViewCompat.setImageTintList(this, null)
        return
    }
    ImageViewCompat.setImageTintMode(this, PorterDuff.Mode.SRC_ATOP)
    ImageViewCompat.setImageTintList(this, ColorStateList.valueOf(color))
}
programista Androida
źródło
-4

Nie dokładna odpowiedź, ale prostsza alternatywa:

  • Umieść inny widok na górze obrazu
  • Zmień wartość alfa widoku, jak chcesz (programowo), aby uzyskać pożądany efekt.

Oto fragment tego:

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="@dimen/height120"
        android:contentDescription="@string/my_description"
        android:scaleType="fitXY"
        android:src="@drawable/my_awesome_image"/>

    <View
        android:layout_width="match_parent"
        android:layout_height="@dimen/height120"
        android:alpha="0.5"
        android:background="@color/my_blue_color"/>
</FrameLayout>
Shubham Chaudhary
źródło
chodzi o odcień! nie alfa dla przejrzystości.
David
Ale to ostatecznie działa jak odcień. Powinieneś spróbować sam. To tylko jeden sposób patrzenia na rzeczy.
Shubham Chaudhary
@ShubhamChaudhary Wiem, że jest późno, ale co, jeśli obraz jest png. W takim razie tło się nie zmieni? Również alfa i odcień są bardzo różne. Odcień jest jak zamiana kolorów, jeśli się nie mylę. Żadne przestępstwo nie jest zamierzone. Próbuję tylko pomóc :)
KISHORE_ZE,
Ważny punkt Ta odpowiedź pomogła w moim przypadku. Nadzieja pasuje również do butów innych osób.
Shubham Chaudhary