使用Palette获取图片的主调色
Palette
Palette:翻译过来就是调色板的意思,会根据传入的bitmap,提取出主体颜色(分六种特性可选)。我们可以调用 Palette 从一张图片中提取出某种特性颜色并将颜色融入到UI中。比如,我们可以设置给ActionBar、布局做背景颜色,这样ActionBar和布局的颜色就会随着显示图片的变化而变化,这样可以使整个App看起来风格统一一点。
1.Palette主要方法
方法 | 介绍 |
---|---|
Palette.Builder | 生成器类,生成 Palette 实例 |
Palette.PaletteAsyncListener | 异步加载监听 |
from(Bitmap bitmap) | 通过返回 Palette.Builder 实例来构建 Palette |
palette.getMutedColor(Color.BLUE) | 获取图片中一个最柔和的颜色(若无法取到相对应特性的颜色值,则返回默认值Color.BLUE) |
palette.getDarkMutedColor(Color.BLUE) | 获取到柔和的深色的颜色(同上) |
palette.getDarkVibrantColor(Color.BLUE) | 获取到活跃的深色的颜色(同上) |
palette.getVibrantColor(Color.BLUE) | 获取图片中最活跃的颜色(也可以说整个图片出现最多的颜色)(同上) |
palette.getLightMutedColor(Color.BLUE) | 获取到柔和的明亮的颜色(同上) |
palette.getLightVibrantColor(Color.BLUE) | 获取到活跃的明亮的颜色(同上) |
2.基本使用
1.导入依赖包
implementation 'androidx.palette:palette:1.0.0'
2.Palette 创建并传入bitmap
Palette提供了四个方法来生成对象:
- Palette generate(Bitmap bitmap)
- Palette generate(Bitmap bitmap, int numColors)
- generateAsync(Bitmap bitmap, PaletteAsyncListener listener)
- generateAsync(Bitmap bitmap, int numColors, final PaletteAsyncListener listener)
生成方法分为generate(同步)和generateAsync(异步)两种,如果图片过大使用generate方法,可能会阻塞主线程,我们更倾向于使用generateAsync的方法,其实内部就是创建了一个AsyncTask。generateAsync方法需要一个PaletteAsyncListener对象用于监听生成完毕的回调。除了必须的Bitmap参数外,还可以传入一个numColors参数指定颜色数,默认是 16。
3.拿到提取到的颜色值
- Palette.getVibrantSwatch()
- Palette.getDarkVibrantSwatch()
- Palette.getLightVibrantSwatch()
- Palette.getMutedSwatch()
- Palette.getDarkMutedSwatch()
- Palette.getLightMutedSwatch()
4.简单的实现效果
5.主要代码
5.1 PaletteUitls类
public class PaletteUtils {
/**
* Vibrant (有活力的)
* Vibrant dark(有活力的 暗色)
* Vibrant light(有活力的 亮色)
* Muted (柔和的)
* Muted dark(柔和的 暗色)
* Muted light(柔和的 亮色)
*
*/
public static Target vibrant = Target.VIBRANT;
public static Target vibrantDark = Target.DARK_VIBRANT;
public static Target vibrantLight = Target.LIGHT_VIBRANT;
public static Target muted = Target.MUTED;
public static Target mutedDark = Target.DARK_MUTED;
public static Target mutedLight = Target.LIGHT_MUTED;
//结果颜色值
private int resultColor = -1;
private static PaletteUtils instance;
private PaletteUtils(){};
public static PaletteUtils getInstance(){
if (instance == null) {
instance = new PaletteUtils();
}
return instance;
}
private Bitmap mBitmapCover;
public void generateAsync(final View main_view, Context context, String string, final Target target){
//Glide通过uri获取drawable,再转换为bitmap
Glide.with(context)
.load(string)
.error(R.mipmap.fun_bg) //获取失败
.placeholder(R.mipmap.fun_bg) //占位
.into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
Log.e("lee", "onResourceReady: " + (resource == null));
mBitmapCover = DrawableToBitmap(resource);
if (null != mBitmapCover){
startPalette(mBitmapCover,main_view,target);
}
}
});
}
private void startPalette(Bitmap mBitmapCover,View main_view,Target target) {
resultColor = -1;
Palette.from(mBitmapCover).generate(new Palette.PaletteAsyncListener() {
//异步回调
@Override
public void onGenerated(@Nullable Palette palette) {
if (vibrant.equals(target)) {
resultColor = palette.getVibrantColor(Color.BLUE);
Log.e("lee", "onGenerated: getVibrantColor" + resultColor);
} else if (vibrantDark.equals(target)) {
resultColor = palette.getDarkVibrantColor(Color.BLUE);
Log.e("lee", "onGenerated: getDarkVibrantColor" + resultColor);
} else if (vibrantLight.equals(target)) {
resultColor = palette.getLightVibrantColor(Color.BLUE);
Log.e("lee", "onGenerated: getLightVibrantColor" + resultColor);
} else if (muted.equals(target)) {
resultColor = palette.getMutedColor(Color.BLUE);
Log.e("lee", "onGenerated: getMutedColor" + resultColor);
} else if (mutedDark.equals(target)) {
resultColor = palette.getDarkMutedColor(Color.BLUE);
Log.e("lee", "onGenerated: getDarkMutedColor" + resultColor);
} else if (mutedLight.equals(target)) {
resultColor = palette.getLightMutedColor(Color.BLUE);
Log.e("lee", "onGenerated: getLightMutedColor" + resultColor);
}else{
resultColor = palette.getVibrantColor(Color.BLUE);
Log.e("lee", "onGenerated: getVibrantColor" + resultColor);
}
//获取到了颜色
if (resultColor != -1 && resultColor != Color.BLUE) {
main_view.setBackgroundColor(resultColor);
} else {
main_view.setBackgroundResource(R.mipmap.fun_bg);
}
}
});
}
//drawable->bitmap转换
public static Bitmap DrawableToBitmap(Drawable drawable) {
// 获取 drawable 长宽
int width = drawable.getIntrinsicWidth();
int heigh = drawable.getIntrinsicHeight();
drawable.setBounds(0, 0, width, heigh);
// 获取drawable的颜色格式
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565;
// 创建bitmap
Bitmap bitmap = Bitmap.createBitmap(width, heigh, config);
// 创建bitmap画布
Canvas canvas = new Canvas(bitmap);
// 将drawable 内容画到画布中
drawable.draw(canvas);
return bitmap;
}
}
5.2 调用
/**第一个参数:需要改变颜色的控件view
* 第二个 参数:context
* 第三个参数:uri
* 第四个参数:Palette获取颜色特性target
*/
PaletteUtils.getInstance().generateAsync(activity_search,SearchActivity.this,contentInfo.poster,PaletteUtils.mutedDark)
5.3 利用获取到的主题色做渐变背景(Update:2022.3.31)
通常开发中需要通过网络加载图片,因此可以用Glide处理,添加RequestListener,在资源加载完成之后再做接下来的处理。
Glide.with(context).load(item.getPoster()).listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
Bitmap bitmap =((BitmapDrawable)resource).getBitmap();
Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
Palette.Swatch swatch = palette.getDarkVibrantSwatch();
// swatch.getRgb() => 得到获取到的主题色的rbg值
if (swatch != null) {
int[] colors = new int[]{
swatch.getRgb() & 0x00FFFFFF, // 与一个全透明白色,做startColor
swatch.getRgb() & 0xD1FFFFFF, // 与一个 82% 不透明的白色,做centerColor
swatch.getRgb()
};
//GradientDrawable 支持渐变色的drawable
GradientDrawable drawable = new GradientDrawable();
drawable.setGradientType(GradientDrawable.LINEAR_GRADIENT); //设置线性渐变
drawable.setOrientation(GradientDrawable.Orientation.TOP_BOTTOM); //方向从上往下
drawable.setColors(colors);// 设置颜色数组(类似 startColor, centerColor, endColor)
shadowView.setBackgroundDrawable(drawable); // 设置drawable
}
}
});
return false;
}
}).error(R.drawable.placeholder_1372x560).into(poster);