Wybieranie kolorów za pomocą interfejsu Palette API

Dobry projekt wizualny to podstawa sukcesu aplikacji, a schematy kolorów to jej główny element. Biblioteka Palette to biblioteka Jetpack, która wyodrębnia wyraźne kolory z obrazów, aby tworzyć atrakcyjne wizualnie aplikacje.

Za pomocą biblioteki palet możesz zaprojektować motywy i zastosować niestandardowe kolory do elementów wizualnych w aplikacji. Za pomocą palety możesz na przykład utworzyć koordynowaną kolorowo kartę tytułową utworu na podstawie okładki albumu lub dostosować kolor paska narzędzi aplikacji, gdy zmieni się obraz tła. Obiekt Palette daje dostęp do kolorów obrazu Bitmap oraz udostępnia 6 głównych profili kolorów z bitmapy, które pozwalają wybrać projekt.

Konfigurowanie biblioteki

Aby korzystać z biblioteki palet, dodaj do build.gradle te pozycje:

Kotlin

android {
    compileSdkVersion(33)
    ...
}

dependencies {
    ...
    implementation("androidx.palette:palette:1.0.0")
}

Odlotowe

android {
    compileSdkVersion 33
    ...
}

dependencies {
    ...
    implementation 'androidx.palette:palette:1.0.0'
}

Utwórz paletę

Obiekt Palette zapewnia dostęp do kolorów podstawowych na obrazie oraz do odpowiadających im kolorów na potrzeby nakładanego tekstu. Użyj palet, aby zaprojektować styl aplikacji i dynamicznie zmieniać schemat kolorów aplikacji na podstawie danego obrazu źródłowego.

Aby utworzyć paletę, najpierw utwórz instancję Palette.Builder z Bitmap. Następnie możesz użyć Palette.Builder, aby dostosować paletę przed jej wygenerowaniem. W tej sekcji opisujemy generowanie palety i dostosowywanie ich z poziomu obrazu bitmapy.

Wygeneruj instancję palety

Wygeneruj instancję Palette za pomocą metody from(Bitmap bitmap), aby najpierw utworzyć Palette.Builder z Bitmap.

Kreator może generować paletę synchronicznie lub asynchronicznie. Synchroniczne generowanie palety pozwala utworzyć paletę w tym samym wątku co wywoływana metoda. Jeśli generujesz paletę asynchronicznie w innym wątku, użyj metody onGenerated(), aby uzyskać dostęp do palety natychmiast po jej utworzeniu.

W poniższym fragmencie kodu znajdziesz przykładowe metody dla obu typów generowania palet:

Kotlin

// Generate palette synchronously and return it.
fun createPaletteSync(bitmap: Bitmap): Palette = Palette.from(bitmap).generate()

// Generate palette asynchronously and use it on a different thread using onGenerated().
fun createPaletteAsync(bitmap: Bitmap) {
    Palette.from(bitmap).generate { palette ->
        // Use generated instance.
    }
}

Java

// Generate palette synchronously and return it.
public Palette createPaletteSync(Bitmap bitmap) {
  Palette p = Palette.from(bitmap).generate();
  return p;
}

// Generate palette asynchronously and use it on a different thread using onGenerated().
public void createPaletteAsync(Bitmap bitmap) {
  Palette.from(bitmap).generate(new PaletteAsyncListener() {
    public void onGenerated(Palette p) {
      // Use generated instance.
    }
  });
}

Jeśli musisz stale generować palety dla posortowanej listy obrazów lub obiektów, rozważ zapisanie w pamięci podręcznej instancji Palette, aby zapobiec spowolnieniu działania interfejsu. Nie twórz palet w wątku głównym.

Dostosuj paletę

Palette.Builder umożliwia dostosowanie palety przez wybranie, ile kolorów zawiera paleta wynikowa, obszaru obrazu używany przez kreator do wygenerowania palety oraz jakie kolory mają być uwzględnione w palecie. Możesz na przykład odfiltrować czarny lub użyć do wygenerowania palety tylko górnej połowy obrazu.

Dostosuj rozmiar i kolory palety za pomocą poniższych metod z klasy Palette.Builder:

addFilter()
Ta metoda dodaje filtr, który wskazuje, jakie kolory są dozwolone w palecie wynikowej. Prześlij własną Palette.Filter i zmodyfikuj jej metodę isAllowed(), aby określić, które kolory mają być odfiltrowywane z palety.
maximumColorCount()
Ta metoda pozwala ustawić maksymalną liczbę kolorów w palecie. Wartość domyślna to 16, a optymalna zależy od obrazu źródłowego. W przypadku krajobrazu optymalne wartości mieszczą się w przedziale od 8 do 16, a zdjęcia przedstawiające twarze mają zwykle wartości z przedziału 24–32. Wygenerowanie palet z większą liczbą kolorów w funkcji Palette.Builder trwa dłużej.
setRegion()
Ta metoda wskazuje obszar bitmapy, którego kreator używa podczas tworzenia palety. Tej metody możesz używać tylko podczas generowania palety na podstawie bitmapy. Nie ma ona wpływu na oryginalny obraz.
addTarget()
Ta metoda pozwala na własne dopasowywanie kolorów przez dodanie profilu kolorów Target do kreatora. Jeśli domyślna Target nie jest wystarczająca, zaawansowani programiści mogą utworzyć własne Target za pomocą Target.Builder.

Wyodrębnij profile kolorów

Na podstawie standardów Material Design biblioteka Palette wyodrębnia najczęściej używane profile kolorów z obrazu. Każdy profil jest definiowany przez element Target, a kolory wyodrębnione z obrazu bitmapy są przedstawiane względem każdego profilu na podstawie nasycenia, luminancji i populacji (liczby pikseli na bitmapie reprezentowanej przez kolor). W przypadku każdego profilu kolor z najlepszym wynikiem określa profil kolorów danego zdjęcia.

Domyślnie obiekt Palette zawiera 16 kolorów podstawowych z danego obrazu. Podczas generowania palety możesz dostosować liczbę jej kolorów za pomocą komponentu Palette.Builder. Wyodrębnienie większej liczby kolorów zapewnia więcej potencjalnych dopasowań dla każdego profilu kolorów, ale powoduje też wydłużenie czasu generowania palety przez Palette.Builder.

Biblioteka palet próbuje wyodrębnić sześć następujących profili kolorów:

  • Jasny żywy
  • Barwny
  • Ciemny żywy
  • Przygaszone światło
  • wyciszone,
  • Ciemny wyciszony

Każda z metod get<Profile>Color() w Palette zwraca kolor z palety powiązanej z danym profilem, przy czym <Profile> jest zastępowany nazwą jednego z 6 profili kolorów. Na przykład metodą uzyskania profilu kolorów ciemnych żywych jest getDarkVibrantColor(). Ponieważ nie wszystkie obrazy zawierają wszystkie profile kolorów, podaj kolor domyślny do zwrócenia.

Na ilustracji 1 przedstawiono zdjęcie i odpowiadające mu profile kolorów z metod get<Profile>Color().

Obraz przedstawiający zachód słońca po lewej stronie i wyodrębnioną paletę kolorów po prawej.
Rysunek 1. Przykładowy obraz i jego wyodrębnione profile kolorów z domyślną maksymalną liczbą kolorów (16) dla palety.

Używaj próbek do tworzenia schematów kolorów

Klasa Palette generuje też obiekty Palette.Swatch dla każdego profilu kolorów. Obiekty Palette.Swatch zawierają powiązany kolor z tym profilem oraz jego wypełnianie w pikselach.

Próbki mają dodatkowe metody uzyskiwania dostępu do dodatkowych informacji o profilu kolorów, np. wartości HSL czy wypełniania pikseli. Dzięki próbkom możesz tworzyć bardziej kompleksowe schematy kolorów i motywy aplikacji za pomocą metod getBodyTextColor() i getTitleTextColor(). Te metody zwracają kolory odpowiednie do użycia zamiast koloru próbki.

Każda metoda get<Profile>Swatch() z Palette zwraca próbkę powiązaną z danym profilem, przy czym <Profile> jest zastępowana nazwą jednego z 6 profili kolorów. Chociaż metody get<Profile>Swatch() palety nie wymagają domyślnych parametrów wartości, zwracają wartość null, jeśli danego profilu nie ma na obrazie. Dlatego przed użyciem próbki upewnij się, że nie ma ona wartości null. Na przykład poniższy kod pobiera kolor tekstu tytułu z palety, jeśli próbka koloru Kolorowa nie ma wartości null:

Kotlin

val vibrant = myPalette.vibrantSwatch
// In Kotlin, check for null before accessing properties on the vibrant swatch.
val titleColor = vibrant?.titleTextColor

Java

Palette.Swatch vibrant = myPalette.getVibrantSwatch();
if(vibrant != null){
    int titleColor = vibrant.getTitleTextColor();
    // ...
}

Aby uzyskać dostęp do wszystkich kolorów z palety, metoda getSwatches() zwraca listę wszystkich próbek wygenerowanych z obrazu, w tym 6 standardowych profili kolorów.

Poniższy fragment kodu wykorzystuje metody z poprzednich fragmentów kodu, aby synchronicznie wygenerować paletę, pobrać próbkę barwnej i zmienić kolory paska narzędzi, tak aby pasował do obrazu bitmapy. Rysunek 2 przedstawia obraz i pasek narzędzi.

Kotlin

// Set the background and text colors of a toolbar given a bitmap image to
// match.
fun setToolbarColor(bitmap: Bitmap) {
    // Generate the palette and get the vibrant swatch.
    val vibrantSwatch = createPaletteSync(bitmap).vibrantSwatch

    // Set the toolbar background and text colors.
    // Fall back to default colors if the vibrant swatch isn't available.
    with(findViewById<Toolbar>(R.id.toolbar)) {
        setBackgroundColor(vibrantSwatch?.rgb ?:
                ContextCompat.getColor(context, R.color.default_title_background))
        setTitleTextColor(vibrantSwatch?.titleTextColor ?:
                ContextCompat.getColor(context, R.color.default_title_color))
    }
}

Java

// Set the background and text colors of a toolbar given a bitmap image to
// match.
public void setToolbarColor(Bitmap bitmap) {
    // Generate the palette and get the vibrant swatch.
    // See the createPaletteSync() method from the preceding code snippet.
    Palette p = createPaletteSync(bitmap);
    Palette.Swatch vibrantSwatch = p.getVibrantSwatch();

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

    // Load default colors.
    int backgroundColor = ContextCompat.getColor(getContext(),
        R.color.default_title_background);
    int textColor = ContextCompat.getColor(getContext(),
        R.color.default_title_color);

    // Check that the Vibrant swatch is available.
    if(vibrantSwatch != null){
        backgroundColor = vibrantSwatch.getRgb();
        textColor = vibrantSwatch.getTitleTextColor();
    }

    // Set the toolbar background and text colors.
    toolbar.setBackgroundColor(backgroundColor);
        toolbar.setTitleTextColor(textColor);
}
Obraz przedstawiający zachód słońca i pasek narzędzi z tekstem TitleTextColor w środku
Rysunek 2. Przykładowy obraz z paskiem narzędzi w żywych kolorach oraz odpowiednim kolorem tekstu tytułu.