使用Palette获取图片的主调色

本文介绍了如何使用Android的Palette库从图片中获取主题色,并展示了如何将其应用于UI设计,如设置渐变背景。通过Palette的异步方法,避免了加载大图时阻塞主线程,提升用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.简单的实现效果

效果图.jpg

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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值