Android Görünümlerinde Temel Renk Uyumu

1. Başlamadan önce

Bu codelab'de, özel renklerinizi dinamik bir temayla oluşturulan renklerle uyumlu hale getirmeyi öğreneceksiniz.

Ön koşullar

Geliştiriciler ise

  • Android'deki temel tema oluşturma kavramlarına aşinayım.
  • Android widget Görünümleri ve özellikleriyle çalışma

Neler öğreneceksiniz?

  • Birden fazla yöntem kullanarak uygulamanızda renk uyumunu kullanma
  • Uyumun işleyiş şekli ve rengi değiştirme şekli

Gerekenler

  • Android yüklü bir bilgisayarla ilgili talimatları uygulayabilirsiniz.

2. Uygulamaya Genel Bakış

Voyaĝi, halihazırda dinamik tema kullanan bir toplu taşıma uygulamasıdır. Birçok toplu taşıma sisteminde renk, tren, otobüs veya tramvay için önemli bir göstergedir ve bunlar, mevcut dinamik birincil, ikincil veya üçüncül renklerle değiştirilemez. Çalışmamızda renkli toplu taşıma kartlarının RecyclerView üzerinde yoğunlaşacağız.

62ff4b2fb6c9e14a.png

3. Tema Oluşturma

Material3 teması oluşturmak için ilk durağınız olarak Material Theme Builder aracımızı kullanmanızı öneririz. Özel sekmede artık temanıza daha fazla renk ekleyebilirsiniz. Sağ tarafta, bu renkler için renk rolleri ve ton paletleri gösterilir.

Genişletilmiş renk bölümünde, renkleri kaldırabilir veya yeniden adlandırabilirsiniz.

20cc2cf72efef213.png

Dışa aktarma menüsünde çeşitli dışa aktarma seçenekleri gösterilir. Bu yazının yazıldığı sırada, Material Theme Builder'ın uyum ayarlarını özel olarak işleme özelliği yalnızca Android Görünümleri'nde kullanılabiliyor.

6c962ad528c09b4.png

Yeni dışa aktarma değerlerini anlama

Uyumlaştırmayı tercih edip etmemenizden bağımsız olarak bu renkleri ve ilişkili renk rollerini temalarınızda kullanabilmeniz için, dışa aktarılan indirme artık her özel rengin renk rolü adlarını içeren bir attrs.xml dosyası içeriyor.

<resources>
   <attr name="colorCustom1" format="color" />
   <attr name="colorOnCustom1" format="color" />
   <attr name="colorCustom1Container" format="color" />
   <attr name="colorOnCustom1Container" format="color" />
   <attr name="harmonizeCustom1" format="boolean" />

   <attr name="colorCustom2" format="color" />
   <attr name="colorOnCustom2" format="color" />
   <attr name="colorCustom2Container" format="color" />
   <attr name="colorOnCustom2Container" format="color" />
   <attr name="harmonizeCustom2" format="boolean" />
</resources>

temalar.xml dosyasında her bir özel renk (color<name>, colorOn<name>, color<name>Container, and colorOn<nameContainer>) için dört renk rolü oluşturduk. harmonize<name> özellikleri, geliştiricinin Materyal Tema Oluşturucu'da ilgili seçeneği belirleyip belirlemediğini yansıtır. Temel temanın rengini kaydırmaz.

<resources>
   <style name="AppTheme" parent="Theme.Material3.Light.NoActionBar">
       <!--- Normal theme attributes ... -->

       <item name="colorCustom1">#006876</item>
       <item name="colorOnCustom1">#ffffff</item>
       <item name="colorCustom1Container">#97f0ff</item>
       <item name="colorOnCustom1Container">#001f24</item>
       <item name="harmonizeCustom1">false</item>

       <item name="colorCustom2">#016e00</item>
       <item name="colorOnCustom2">#ffffff</item>
       <item name="colorCustom2Container">#78ff57</item>
       <item name="colorOnCustom2Container">#002200</item>
       <item name="harmonizeCustom2">false</item>
   </style>
</resources>

colors.xml dosyasında, yukarıda listelenen renk rollerini oluşturmak için kullanılan çekirdek renkler ve rengin paletinin değiştirilip kaydırılmayacağına ilişkin Boole değerleri belirtilir.

<resources>
   <!-- other colors used in theme -->

   <color name="custom1">#1AC9E0</color>
   <color name="custom2">#32D312</color>
</resources>

4. Özel Rengi inceleme

Material Theme Builder'ın yan paneline baktığımızda, özel bir renk eklendiğinde, açık ve koyu bir paletteki dört temel renk rolünün yer aldığı bir panelin gösterildiğini görebiliyoruz.

c6ee942b2b93cd92.png

Android Görünümlerinde bu renkleri sizin için dışa aktarırız ancak perde arkasında ColorRoles nesnesinin bir örneğiyle temsil edilebilirler.

ColorRoles sınıfının dört özelliği vardır: accent, onAccent, accentContainer ve onAccentContainer. Bu özellikler, dört onaltılık rengin tam sayı gösterimidir.

public final class ColorRoles {

  private final int accent;
  private final int onAccent;
  private final int accentContainer;
  private final int onAccentContainer;

  // truncated code

}

getColorRoles adlı MaterialColors sınıfında getColorRoles kullanarak çalışma zamanında rastgele bir renkten dört temel renk rolünü alabilirsiniz. Bu rol, belirli bir çekirdek rengi verildiğinde çalışma zamanında dört renk rolü grubunu oluşturmanıza olanak tanır.

public static ColorRoles getColorRoles(
    @NonNull Context context,
    @ColorInt int color
) { /* implementation */ }

Benzer şekilde, çıkış değerleri de gerçek renk değerleridir, bunları işaret etmez.**

5. Renk Uyumu nedir?

Material'ın yeni renk sistemi, belirli bir çekirdek renginden birincil, ikincil, üçüncül ve nötr renkler oluşturarak algoritmik bir tasarıma sahiptir. Şirket içi ve şirket dışı iş ortaklarıyla konuşurken en çok karşılaştığımız konulardan biri, bazı renkler üzerinde kontrol sahibi olurken dinamik renklerin benimsenmesiydi.

Bu renkler genellikle uygulamada belirli bir anlam veya bağlam taşır ve rastgele bir renkle değiştirilmeleri durumunda kaybolur. Alternatif olarak, bu renkler olduğu gibi bırakıldığında, görsel olarak rahatsız edici veya alakasız görünebilir.

Material You'daki renk özelliği ton, renk ve tonla tanımlanır. Bir rengin tonu, kişinin o rengin bir başka renk aralığının üyesi olarak algılanmasıyla ilgilidir. Ton, rengin ne kadar açık veya koyu göründüğünü belirtir. Renk ise renk yoğunluğunu ifade eder. Ton algısı, kültürel ve dilsel faktörlerden etkilenebilir. Örneğin, antik kültürlerde mavi için çok az kelime kullanılması, mavi için yeşil olarak aynı ailede görülmesi gibi.

57c46d9974c52e4a.pngTon spektrumunda bulunduğu yere bağlı olarak belirli bir ton sıcak veya soğuk olarak kabul edilebilir. Kırmızı, turuncu veya sarı tonlara geçiş yapmak genellikle rengi daha sıcak, mavi, yeşil veya mor tonlara geçmek rengin daha serin olduğu kabul edilir. Sıcak veya soğuk renklerde bile sıcak ve soğuk tonlar kullanılır. Altında, "sıcaklık" sarı daha turuncu, "soğutucu" ise daha tonludur. sarı, yeşilden daha fazla etkilenir. 597c6428ff6b9669.png

Renk uyumlaştırma algoritması, uyumlu olan ancak temel renk niteliklerini değiştirmeyen bir tonu bulmak için, değişmemiş rengin ve uyumlu hale getirilmesi gereken rengin tonunu inceler. İlk grafikte, spektrumda çizilmiş daha az uyumlu yeşil, sarı ve turuncu tonlar var. Bir sonraki grafikte yeşil ve turuncu renk, sarı renkle uyumlu hale getirilmiş. Yeni yeşil daha sıcak, yeni turuncu ise daha havalı.

Turuncu ve yeşilin tonları değişmiştir ancak yine de turuncu ve yeşil olarak algılanabilir.

766516c321348a7c.png

Tasarımla ilgili bazı kararlar, keşifler ve dikkat edilmesi gereken noktalar hakkında daha fazla bilgi edinmek isterseniz meslektaşlarım Ayan Daniels ve Andrew Lu, bu bölümden biraz daha ayrıntılı bir blog yayını yazmışlar.

6. Rengi manuel olarak uyumlu hale getirme

Tek bir tonu uyumlu hale getirmek için MaterialColors, harmonize ve harmonizeWithPrimary olmak üzere iki işlevden yararlanabilirsiniz.

harmonizeWithPrimary, mevcut temaya ve ardından da temadaki birincil renge erişmek için bir araç olarak Context kullanır.

@ColorInt
public static int harmonizeWithPrimary(@NonNull Context context, @ColorInt int colorToHarmonize) {
    return harmonize(
        colorToHarmonize,
        getColor(context, R.attr.colorPrimary, MaterialColors.class.getCanonicalName()));
  }


@ColorInt
  public static int harmonize(@ColorInt int colorToHarmonize, @ColorInt int colorToHarmonizeWith) {
    return Blend.harmonize(colorToHarmonize, colorToHarmonizeWith);
  }

Dört tonlu seti almak için biraz daha işlem yapmamız gerekiyor.

Kaynak rengi zaten mevcut olduğundan, şunları yapmamız gerekir:

  1. uyumlu hale getirilmesi gerekip gerekmediğini
  2. koyu modda olup olmadığımızı belirlemeli
  3. uyumlulaştırılmış veya uyumlu olmayan ColorRoles nesnesini döndürür.

Uyum sağlayıp sağlamayacağını belirleme

Material Theme Builder'dan dışa aktarılan temada, harmonize<Color> terminolojisini kullanan boole özellikleri ekledik. Bu değere erişmek için kullanılan bir kolaylık işlevi aşağıda verilmiştir.

Bulunursa değerini döndürür; aksi takdirde rengi uyumlu hale getirmemesi gerektiğini belirler.

// Looks for associated harmonization attribute based on the color id
// custom1 ===> harmonizeCustom1
fun shouldHarmonize(context: Context, colorId: Int): Boolean {
   val root = context.resources.getResourceEntryName(colorId)
   val harmonizedId = "harmonize" + root.replaceFirstChar { it.uppercaseChar() }
   
   val identifier = context.resources.getIdentifier(
           harmonizedId, "bool", context.packageName)
   
   return if (identifier != 0) context.resources.getBoolean(identifier) else false
}

Uyumlaştırılmış ColorRoles nesnesi oluşturma

retrieveHarmonizedColorRoles, yukarıda belirtilen tüm adımları birleştiren başka bir kolaylık işlevidir: adlandırılmış bir kaynağın renk değerini alma, harmonizasyonu belirlemek için bir boole özelliğini çözümlemeye çalışır ve orijinal veya karma renkten (açık veya koyu şema) türetilen bir ColorRoles nesnesini döndürür.

fun retrieveHarmonizedColorRoles(
   view: View,
   customId: Int,
   isLight: Boolean
): ColorRoles {
   val context = view.context
   val custom = context.getColor(customId);
  
   val shouldHarmonize = shouldHarmonize(context, customId)
   if (shouldHarmonize) {
       val blended = MaterialColors.harmonizeWithPrimary(context, custom)
       return MaterialColors.getColorRoles(blended, isLight)
   } else return MaterialColors.getColorRoles(custom, isLight)
}

7. Toplu taşıma kartları dolduruluyor

Daha önce de belirtildiği gibi, toplu taşıma kartı koleksiyonunu doldurmak ve renklendirmek için bir RecyclerView ve adaptör kullanacağız.

e4555089b065b5a7.png

Toplu taşıma verilerini depolama

Toplu taşıma kartlarıyla ilgili metin verilerini ve renk bilgilerini depolamak için adı, hedefi ve renk kaynağı kimliğini depolayan bir veri sınıfı kullanıyoruz.

data class TransitInfo(val name: String, val destination: String, val colorId: Int)

/*  truncated code */

val transitItems = listOf(
   TransitInfo("53", "Irvine", R.color.custom1),
   TransitInfo("153", "Brea", R.color.custom1),
   TransitInfo("Orange County Line", "Oceanside", R.color.custom2),
   TransitInfo("Pacific Surfliner", "San Diego", R.color.custom2)
)

İhtiyacımız olan tonları gerçek zamanlı olarak oluşturmak için bu rengi kullanacağız.

Aşağıdaki onBindViewHolder işleviyle çalışma zamanında uyumlu hale getirebilirsiniz.

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
   val transitInfo = list.get(position)
   val color = transitInfo.colorId
   if (!colorRolesMap.containsKey(color)) {

       val roles = retrieveHarmonizedColorRoles(
           holder.itemView, color,
           !isNightMode(holder.itemView.context)
       )
       colorRolesMap.put(color, roles)
   }

   val card = holder.card
   holder.transitName.text = transitInfo.name
   holder.transitDestination.text = transitInfo.destination

   val colorRoles = colorRolesMap.get(color)
   if (colorRoles != null) {
       holder.card.setCardBackgroundColor(colorRoles.accentContainer)
       holder.transitName.setTextColor(colorRoles.onAccentContainer)
       holder.transitDestination.setTextColor(colorRoles.onAccentContainer)
   }
}

8. Renkleri otomatik olarak uyumlu hale getirme

Uyumlaştırmayı manuel olarak ele almaya alternatif olarak, sizin yerinize halledebilirsiniz. HarmonizedColorOptions, şu ana kadar elde ettiğimiz işlemlerin çoğunu belirtmenize olanak tanıyan bir oluşturucu sınıfıdır.

Geçerli dinamik şemaya erişebilmek için geçerli bağlamı aldıktan sonra, uyumlu hale getirmek istediğiniz temel renkleri belirtmeniz ve HarmonizedColorOptions nesnesine ve DynamicColors'ın etkinleştirildiği bağlama dayalı yeni bir bağlam oluşturmanız gerekir.

Bir rengi uyumlu hale getirmek istemiyorsanız, rengi harmonizedOptions'a dahil etmeyin.

val newContext = DynamicColors.wrapContextIfAvailable(requireContext())


val harmonizedOptions = HarmonizedColorsOptions.Builder()
 .setColorResourceIds(intArrayOf(R.color.custom1, R.color.custom2))
 .build();

harmonizedContext =
 HarmonizedColors.wrapContextIfAvailable(dynamicColorsContext, harmonizedOptions)

Uyumlaştırılmış temel renk işlenmiş durumdayken onBindViewHolder'ınızı MaterialColors.getColorRoles çağrısı yapacak şekilde güncelleyebilir ve döndürülen rollerin açık mı yoksa koyu mu olacağını belirtebilirsiniz.

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
   /*...*/
   val color = transitInfo.colorId
   if (!colorRolesMap.containsKey(color)) {

       val roles = MaterialColors.getColorRoles(context.getColor(color), !isNightMode(context))

       )
       colorRolesMap.put(color, roles)
   }

   val card = holder.card
   holder.transitName.text = transitInfo.name
   holder.transitDestination.text = transitInfo.destination

   val colorRoles = colorRolesMap.get(color)
   if (colorRoles != null) {
       holder.card.setCardBackgroundColor(colorRoles.accentContainer)
       holder.transitName.setTextColor(colorRoles.onAccentContainer)
       holder.transitDestination.setTextColor(colorRoles.onAccentContainer)
   }
}

9. Tema özelliklerini otomatik olarak uyumlu hale getirme

Şimdiye kadar gösterilen yöntemler, tek bir renkten renk rollerinin alınmasına dayanıyor. Bu, gerçek bir üslup oluşturulduğunu ancak mevcut uygulamaların çoğuna göre gerçekçi olmadığını göstermek için harika bir uygulamadır. Muhtemelen renk türünü doğrudan türetmek yerine mevcut bir tema özelliğini kullanırsınız.

Bu codelab'in önceki bölümlerinde tema özelliklerini dışa aktarma hakkında konuşmuştuk.

<resources>
   <style name="AppTheme" parent="Theme.Material3.Light.NoActionBar">
       <!--- Normal theme attributes ... -->

       <item name="colorCustom1">#006876</item>
       <item name="colorOnCustom1">#ffffff</item>
       <item name="colorCustom1Container">#97f0ff</item>
       <item name="colorOnCustom1Container">#001f24</item>
       <item name="harmonizeCustom1">false</item>

       <item name="colorCustom2">#016e00</item>
       <item name="colorOnCustom2">#ffffff</item>
       <item name="colorCustom2Container">#78ff57</item>
       <item name="colorOnCustom2Container">#002200</item>
       <item name="harmonizeCustom2">false</item>
   </style>
</resources>

İlk otomatik yönteme benzer şekilde, HarmonizedColorOptions'a değerler sağlayabilir ve uyumlu renklerle Bağlam bilgisi almak için HarmonizedColors'ı kullanabiliriz. İki yöntem arasında temel bir fark vardır. Ayrıca, uyumlu hale getirilecek alanları içeren bir tema yer paylaşımı sağlamamız gerekir.

val dynamicColorsContext = DynamicColors.wrapContextIfAvailable(requireContext())

// Harmonizing individual attributes
val harmonizedColorAttributes = HarmonizedColorAttributes.create(
 intArrayOf(
   R.attr.colorCustom1,
   R.attr.colorOnCustom1,
   R.attr.colorCustom1Container,
   R.attr.colorOnCustom1Container,
   R.attr.colorCustom2,
   R.attr.colorOnCustom2,
   R.attr.colorCustom2Container,
   R.attr.colorOnCustom2Container
 ), R.style.AppTheme_Overlay
)
val harmonizedOptions =
 HarmonizedColorsOptions.Builder().setColorAttributes(harmonizedColorAttributes).build()

val harmonizedContext =
 HarmonizedColors.wrapContextIfAvailable(dynamicColorsContext, harmonizedOptions)

Bağdaştırıcınız uyumlulaştırılmış bağlamı kullanır. Tema yer paylaşımındaki değerler, uyumlu olmayan açık veya koyu varyanta başvurmalıdır.

<style name="AppTheme.Overlay" parent="AppTheme">
   <item name="colorCustom1">@color/harmonized_colorCustom1</item>
   <item name="colorOnCustom1">@color/harmonized_colorOnCustom1</item>
   <item name="colorCustom1Container">@color/harmonized_colorCustom1Container</item>
   <item name="colorOnCustom1Container">@color/harmonized_colorOnCustom1Container</item>

   <item name="colorCustom2">@color/harmonized_colorCustom2</item>
   <item name="colorOnCustom2">@color/harmonized_colorOnCustom2</item>
   <item name="colorCustom2Container">@color/harmonized_colorCustom2Container</item>
   <item name="colorOnCustom2Container">@color/harmonized_colorOnCustom2Container</item>
</style>

XML düzen dosyasında, bu uyumlu özellikleri normal şekilde kullanabiliriz.

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   style="?attr/materialCardViewFilledStyle"
   android:id="@+id/card"
   android:layout_width="80dp"
   android:layout_height="100dp"
   android:layout_marginStart="8dp"
   app:cardBackgroundColor="?attr/colorCustom1Container"
   >

   <androidx.constraintlayout.widget.ConstraintLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_margin="8dp">

       <TextView
           android:id="@+id/transitName"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:textSize="28sp"
           android:textStyle="bold"
           android:textColor="?attr/colorOnCustom1Container"
           app:layout_constraintTop_toTopOf="parent" />

       <TextView
           android:id="@+id/transitDestination"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_marginBottom="4dp"
           android:textColor="?attr/colorOnCustom1Container"
           app:layout_constraintBottom_toBottomOf="parent" />
   </androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>

10. Kaynak Kodu

package com.example.voyagi.harmonization.ui.dashboard

import android.content.Context
import android.content.res.Configuration
import android.graphics.Typeface
import android.os.Bundle
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.voyagi.harmonization.R
import com.example.voyagi.harmonization.databinding.FragmentDashboardBinding
import com.example.voyagi.harmonization.ui.home.TransitCardAdapter
import com.example.voyagi.harmonization.ui.home.TransitInfo
import com.google.android.material.card.MaterialCardView
import com.google.android.material.color.ColorRoles
import com.google.android.material.color.DynamicColors
import com.google.android.material.color.HarmonizedColorAttributes
import com.google.android.material.color.HarmonizedColors
import com.google.android.material.color.HarmonizedColorsOptions
import com.google.android.material.color.MaterialColors


class DashboardFragment : Fragment() {

 enum class TransitMode { BUS, TRAIN }
 data class TransitInfo2(val name: String, val destination: String, val mode: TransitMode)

 private lateinit var dashboardViewModel: DashboardViewModel
 private var _binding: FragmentDashboardBinding? = null

 // This property is only valid between onCreateView and
 // onDestroyView.
 private val binding get() = _binding!!

 override fun onCreateView(
   inflater: LayoutInflater,
   container: ViewGroup?,
   savedInstanceState: Bundle?
 ): View? {
   dashboardViewModel =
     ViewModelProvider(this).get(DashboardViewModel::class.java)

   _binding = FragmentDashboardBinding.inflate(inflater, container, false)
   val root: View = binding.root


   val recyclerView = binding.recyclerView

   val transitItems = listOf(
     TransitInfo2("53", "Irvine", TransitMode.BUS),
     TransitInfo2("153", "Brea", TransitMode.BUS),
     TransitInfo2("Orange County Line", "Oceanside", TransitMode.TRAIN),
     TransitInfo2("Pacific Surfliner", "San Diego", TransitMode.TRAIN)
   )
  
   val dynamicColorsContext = DynamicColors.wrapContextIfAvailable(requireContext())

   // Harmonizing individual attributes
   val harmonizedColorAttributes = HarmonizedColorAttributes.create(
     intArrayOf(
       R.attr.colorCustom1,
       R.attr.colorOnCustom1,
       R.attr.colorCustom1Container,
       R.attr.colorOnCustom1Container,
       R.attr.colorCustom2,
       R.attr.colorOnCustom2,
       R.attr.colorCustom2Container,
       R.attr.colorOnCustom2Container
     ), R.style.AppTheme_Overlay
   )
   val harmonizedOptions =
     HarmonizedColorsOptions.Builder().setColorAttributes(harmonizedColorAttributes).build()

   val harmonizedContext =
     HarmonizedColors.wrapContextIfAvailable(dynamicColorsContext, harmonizedOptions)


   val adapter = TransitCardAdapterAttr(transitItems, harmonizedContext)
   recyclerView.adapter = adapter
   recyclerView.layoutManager =
     LinearLayoutManager(harmonizedContext, RecyclerView.HORIZONTAL, false)

   return root
 }

 override fun onDestroyView() {
   super.onDestroyView()
   _binding = null
 }
}

class TransitCardAdapterAttr(val list: List<DashboardFragment.TransitInfo2>, context: Context) :
 RecyclerView.Adapter<RecyclerView.ViewHolder>() {
 val colorRolesMap = mutableMapOf<Int, ColorRoles>()
 private var harmonizedContext: Context? = context

 override fun onCreateViewHolder(
   parent: ViewGroup,
   viewType: Int
 ): RecyclerView.ViewHolder {
   return if (viewType == DashboardFragment.TransitMode.BUS.ordinal) {
     BusViewHolder(LayoutInflater.from(harmonizedContext).inflate(R.layout.transit_item_bus, parent, false))
   } else TrainViewHolder(LayoutInflater.from(harmonizedContext).inflate(R.layout.transit_item_train, parent, false))
 }

 override fun getItemCount(): Int {
   return list.size
 }

 override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
   val item = list[position]
   if (item.mode.ordinal == DashboardFragment.TransitMode.BUS.ordinal) {
     (holder as BusViewHolder).bind(item)
     (holder as TransitBindable).adjustNameLength()
   } else {
       (holder as TrainViewHolder).bind(item)
       (holder as TransitBindable).adjustNameLength()
   }
 }

 override fun getItemViewType(position: Int): Int {
   return list[position].mode.ordinal
 }

 interface TransitBindable {
   val card: MaterialCardView
   var transitName: TextView
   var transitDestination: TextView

   fun bind(item: DashboardFragment.TransitInfo2) {
     transitName.text = item.name
     transitDestination.text = item.destination
   }
   fun Float.toDp(context: Context) =
     TypedValue.applyDimension(
       TypedValue.COMPLEX_UNIT_DIP,
       this,
       context.resources.displayMetrics
     )
   fun adjustNameLength(){
     if (transitName.length() > 4) {
       val layoutParams = card.layoutParams
       layoutParams.width = 100f.toDp(card.context).toInt()
       card.layoutParams = layoutParams
       transitName.setTypeface(Typeface.DEFAULT_BOLD);

       transitName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16.0f)
     }
   }
 }

 inner class BusViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), TransitBindable {
   override val card: MaterialCardView = itemView.findViewById(R.id.card)
   override var transitName: TextView = itemView.findViewById(R.id.transitName)
   override var transitDestination: TextView = itemView.findViewById(R.id.transitDestination)
 }
 inner class TrainViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), TransitBindable {
   override val card: MaterialCardView = itemView.findViewById(R.id.card)
   override var transitName: TextView = itemView.findViewById(R.id.transitName)
   override var transitDestination: TextView = itemView.findViewById(R.id.transitDestination)
 }
}

11. Örnek kullanıcı arayüzleri

Uyumlaştırmadan Varsayılan Tema Oluşturma ve Özel Renkler

a5a02a72aef30529.png

Uyumlaştırılmış Özel Renkler

4ac88011173d6753.png d5084780d2c6b886.png

dd0c8b90eccd8bef.png c51f8a677b22cd54.png

12. Özet

Bu codelab'de şunları öğrendiniz:

  • Renk uyumlaştırma algoritmamızın temelleri
  • Görülen belirli bir renkten renk rolleri oluşturma.
  • Kullanıcı arayüzünde belirli bir rengi seçerek uyumlu hale getirme.
  • Bir temada özellik grubunu uyumlu hale getirme.

Sorularınız varsa Twitter'da@MaterialDesign hesabını kullanarak dilediğiniz zaman bize sorabilirsiniz.

youtube.com/MaterialDesign adresinden daha fazla tasarım içeriği ve eğitici içerik için bizi takip etmeye devam edin.