在Android中使用调色板API从图像中提取颜色
开发Android应用程序时,用户界面(UI)非常重要。许多开发者往往忽视了这一方面。一个好的用户界面会给用户带来良好的体验。应用程序中的颜色选择对于使其成功非常关键。
在本教程中,我们将从图片中提取用于我们应用程序的颜色。
前提条件
要跟上本教程,读者应该。
- 安装有
Android Studio,并知道如何创建Android项目。 - 对Kotlin编程语言有良好的理解。
- 对
XML有良好的了解。 - 能够使用ViewBinding。
- 有关于
Android Toolbar的基本知识。
目标
在本教程结束时,读者应该。
- 了解什么是
Palette API。 - 知道如何设置调色板API库。
- 知道如何使用Palette API从图像中提取颜色。
什么是Palette?
Palette是Android中的一个支持库。它从位图图像中提取突出的颜色。我们可以在应用程序中的视图组件的造型中使用它。
视图与图像中的突出颜色相匹配。例如,工具栏、背景,甚至是文本颜色。
使用调色板API的优点
- 它提供了一个辅助类来从图像中提取突出的颜色。
- 我们可以使用获得的颜色来制作优雅的应用程序UI设计。
- 我们可以使用内置的方法来定制调色板。例如,添加过滤器和更多。
第1步:创建一个新的Android项目
启动Android Studio,选择New Project ,然后选择Empty Activity 。将其命名为Palette Demo 。点击完成,等待它的构建。

第2步:设置调色板库
在app-module级别的build.gradle 文件中添加以下依赖关系。
implementation("com.android.support:palette-v7:28.0.0")
第3步:为我们的项目设置布局
在这一步,我们将设计UI。这将包含一个ToolBar ,一个ImageView ,一个Button ,和TextViews 。
ActivityMain.xml文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Theme.MyApplication.AppBarOverlay"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/Theme.MyApplication.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="250dp"
android:src="@drawable/index"
app:layout_constraintTop_toBottomOf="@+id/appBarLayout"
tools:layout_editor_absoluteX="26dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change Toolbar Color"
android:textSize="18sp"
android:layout_marginTop="8dp"
android:textAllCaps="false"
android:id="@+id/change_toolbar_color_btn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView"/>
<TextView
android:id="@+id/lightVibrant"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="Light Vibrant"
android:textAllCaps="false"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/change_toolbar_color_btn" />
<TextView
android:id="@+id/vibrant"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="Vibrant"
android:textAllCaps="false"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lightVibrant" />
<TextView
android:id="@+id/lightMuted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="Light Muted"
android:textAllCaps="false"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/vibrant" />
<TextView
android:id="@+id/muted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="Muted"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lightMuted" />
<TextView
android:id="@+id/darkMuted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="Dark Muted"
android:textAllCaps="false"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/muted" />
<TextView
android:id="@+id/darkVibrant"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="Dark Vibrant"
android:textAllCaps="false"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/darkMuted" />
</androidx.constraintlayout.widget.ConstraintLayout>
第4步:创建一个调色板对象
调色板对象允许我们访问图像位图中突出的颜色。我们使用调色板通过基于图像位图改变应用程序的配色方案来设计我们的应用程序。
为了创建一个调色板,我们使用from(bitmap: Bitmap) 方法生成一个实例。这将从一个位图创建一个Builder 。
这个构建器可以生成同步或异步调色板。为了在与我们正在调用的方法相同的线程上创建调色板,我们使用同步调色板。为了在另一个线程上创建调色板,我们使用异步调色板。
onGenerated() 方法是用来访问调色板的。
要创建一个同步的调色板,我们使用。
// Synchronous Palette generated and returned
fun createPaletteSync(bitmap: Bitmap): Palette = Palette.from(bitmap).generate()
要创建一个异步调色板,我们使用:。
// Palette created asynchronously. We use it on another thread using onGenerated() method
fun createPaletteAsync(bitmap: Bitmap) {
Palette.from(bitmap).generate { palette ->
// Use the generated instance
}
}
要生成一个调色板,我建议使用异步技术。同步生成可能不会产生流畅的体验。这在旧设备上或位图对象相对较大时很明显。
第5步:提取颜色配置文件
一个Target ,定义了每个提取的颜色。我们根据配置文件对颜色进行评分。这是根据饱和度和位图图像中的像素数量来完成的。
调色板使用各自的方法提取了以下六个颜色配置文件。
- 浅色鲜艳度:浅色鲜艳度是指在一个特定的时间段内,在一个特定的时间段内,在一个特定的时间段内,在一个特定的时间段内,在一个特定的时间段内。
Palette.getLightVibrantSwatch() - 深色鲜艳。
Palette.getDarkVibrantSwatch() - 鲜艳的。
Palette.getVibrantSwatch() - 淡淡的柔和。
Palette.getLightMutedSwatch() - 暗淡:暗淡。
Palette.getDarkMutedSwatch() - 静音。
Palette.getMutedSwatch()
我们将使用色板从位图图像中获取颜色。我们使用Palette.Swatch 对象来获取每个颜色配置文件。调色板还有其他方法来获取更多关于颜色配置文件的信息。
它们包括。
getPopulation获取此色板所代表的像素数量。getRgb获得颜色的RGB值。getBodyTextColor和 获得文本颜色的RGB值,用于色板的颜色。getTitleTextColor
get<Profile>Swatch 方法通常不需要参数。但是,如果一个特定的配置文件不存在于位图图像中,它可能返回空。在访问swatch之前,首先要检查它是否为空,以防止你的应用程序崩溃。
下面的代码检查色板是否存在于图像位图中。否则,默认的背景颜色被设置为灰色。
if(palette?.lightMutedSwatch != null){
setBackgroundColor(palette?.lightMutedSwatch!!.rgb
}
else{
setBackgroundColor(Color.GRAY)
}
下面是主活动的代码。
ActivityMain.kt文件
// Press Alt + Enter to import the libraries
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.toolbar)
createPaletteAsync((ContextCompat.getDrawable(this,R.drawable.index) as BitmapDrawable).bitmap)
}
private fun createPaletteAsync(bitmap: Bitmap) {
Palette.from(bitmap).generate(){ palette ->
// Change toolbar background color
binding.changeToolbarColorBtn.setOnClickListener {
binding.toolbar.setBackgroundColor(palette?.vibrantSwatch!!.rgb)
}
binding.lightVibrant.apply {
setBackgroundColor(palette?.lightVibrantSwatch!!.rgb)
}
binding.vibrant.apply {
setBackgroundColor(palette?.vibrantSwatch!!.rgb)
}
binding.lightMuted.apply {
if(lightVibrantSwatch != null ){
setBackgroundColor(palette?.lightMutedSwatch!!.rgb)
}
else{
setBackgroundColor(Color.Grey)
}
}
binding.muted.apply {
setBackgroundColor(palette?.mutedSwatch!!.rgb)
}
binding.darkMuted.apply {
setBackgroundColor(palette?.darkMutedSwatch!!.rgb)
}
binding.darkVibrant.apply {
setBackgroundColor(palette?.darkVibrantSwatch!!.rgb)
}
}
}
}
演示屏幕
运行该应用程序后,可以看到这样的画面。


结论
调色板库是一个强大的工具,我们可以用它来在Android应用程序中进行优雅的UI设计。当涉及到颜色和主题的设置时,它为无限的可能性打开了大门。
在你继续探索和学习的过程中,使用这个工具来实现你的应用程序。