Android Study Material Design 八 之 玩转Palette调色板
LZ-Says: 大风把烈酒吹醒 方知拥有过的都是梦
前言
Hello,伙伴们,大家好哈~
又到了LZ装逼时刻~
今天继续为大家带来Material Design之Palette Study。
首先,还是老规矩,瞅一波效果图~
本文效果
千说百说,不如瞅下效果来的实际,如下:
本文目标
阅读完本文,你能收获如下技能:
1) 通过阅读本文,掌握Palette用法;
2) 通过对实际开发中的拓展思考,希望对你撸码之路更上一层楼~
Palette简述及撸码实现
那么,到这里,你就会问了,Palette是什么鬼?它能干什么?
LZ这里简述下:
Palette,存在于v7包中,他主要作用就是可以为我们分析图片中色彩相关信息,例如:图片中鲜艳的颜色值、暗沉的颜色值等等等一系列相关属性。
那么这时候,小伙伴就会疑惑了,我特么的要他干嘛?没卵用啊?
伙计,话不要说太满哦~看我开车带你飞~
首先,我们来介绍下,它提供的获取颜色值得Api所代表的含义:
1) int getDarkMutedColor(@ColorInt int defaultColor): 获取图片中较暗且较为柔和的颜色值,如果分析不出来,则返回设定的颜色值;
2) int getLightMutedColor(@ColorInt int defaultColor):获取图片中较为明亮且较为柔和的颜色值,同样如果分析不出来,则返回设定的颜色值;
3) int getDarkVibrantColor(@ColorInt int defaultColor):获取图片中较为暗且较为鲜艳(鲜活、明亮)颜色值,如分析失败,返回默认;
4) int getLightVibrantColor(@ColorInt int defaultColor):获取图片中较为明亮且较为鲜艳(鲜活、明亮)颜色值,如分析失败,返回默认;
5) int getMutedColor(@ColorInt int defaultColor):获取图片中较为鲜艳(鲜活、明亮)颜色值,如分析失败,返回默认。
以上五点,即为关键Api,下面,我们将依次为大家呈现几种不同的效果。
上面说过,Palette包含在v7包内,但实际使用时,我们依然需要单独引入Palette远程依赖,如下:
compile ‘com.android.support:palette-v7:23.0.0’
首先,布局方面的代码直接略过,没什么东西,我们直接来看具体如何使用:
第一步:拿到当前要分析的图片
BitmapDrawable drawable = (BitmapDrawable) mImageView.getDrawable();
Bitmap bitmap = drawable.getBitmap();
第二步:初始化Palette,开始进行图片分析
Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
//拿到分析后的结果 进行处理
}
});
关于初始化,以及拿到分析结果,我们看下源码里面,看看谷歌的工程师是如何思考问题,看看我们能不能有些属于我们的收获?
public AsyncTask<Bitmap, Void, Palette> generate(final PaletteAsyncListener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener can not be null");
}
return AsyncTaskCompat.executeParallel(
new AsyncTask<Bitmap, Void, Palette>() {
@Override
protected Palette doInBackground(Bitmap... params) {
return generate();
}
@Override
protected void onPostExecute(Palette colorExtractor) {
listener.onGenerated(colorExtractor);
}
}, mBitmap);
}
AsyncTask,异步处理。这里大家想下,我分析一个问题,基本流程是,拿到问题后进行思考,思考完成后开始解决问题,那么相应的转化为这里,就是我们将图片提交给Palette,通知他去处理,处理过程中可能耗时1秒,也可能耗时10秒,那么这期间会不会阻塞UI线程呢?
所以,这里我们需要思考的问题就是,如果让你去写这么一个东西,你会如何写?这些细节能想到么?
没关系,让我们慢慢来,一口吃不成胖子~继续走起
当Palette分析完图片颜色信息后,我们进行详细处理,也就是设置我们TextView背景色。
// 分析图片中 较暗、柔和的颜色
// 分析不出来显示默认
int darkMutedColor = palette.getDarkMutedColor(Color.BLUE);
// 分析图片中 比较暗、柔和的颜色
int lightMutedColor = palette.getLightMutedColor(Color.BLUE);
// 分析图片中 比较暗、鲜艳的颜色
int darkVibrantColor = palette.getDarkVibrantColor(Color.BLUE);
// 分析图片中 比较亮、鲜艳的颜色
int lightVibrantColor = palette.getLightVibrantColor(Color.BLUE);
// 柔和
int mutedColor = palette.getMutedColor(Color.BLUE);
// 载体
Palette.Swatch lightVibrantSwatch = palette.getLightMutedSwatch();
// 获取谷歌提供推荐颜色 RGB
int rgb = lightVibrantSwatch.getRgb();
// 谷歌推荐作为 图片标题颜色(基于图片对比度所呈现的颜色值)
int titleColor = lightVibrantSwatch.getTitleTextColor();
// 谷歌推荐作为 图片中间文字颜色
int bodyColor = lightVibrantSwatch.getBodyTextColor();
// 颜色向量
float[] hsl = lightVibrantSwatch.getHsl();
// 分析颜色在图片所占的像素值
int population = lightVibrantSwatch.getPopulation();
关于代码中载体部分,这里简单为大家描述下:
载体,说白了就是Palette中一个内部类,此类的作用就是为我们封装了一些谷歌推荐的内容,简单附上部分常量。
private final int mRed, mGreen, mBlue;
private final int mRgb;
private final int mPopulation;
private boolean mGeneratedTextColors;
private int mTitleTextColor;
private int mBodyTextColor;
private float[] mHsl;
鉴名其意,不比多说,下面简单看下效果:
观察上图,有个半透明颜色值,这个该如何实现呢?
很easy,思路就是,拿到分析出的rgb以及需要透明的度数,通过改变alpha值去改变实际透明度。
/**
* 1101 0111 1000 1011
* 依次代表 a r g b 通过位移 得出实际结果
*
* @param percent 百分比 比例
* @param rgb
* @return
*/
private int getTranslucentColor(float percent, int rgb) {
// 方式一:使用谷歌推荐方式 效率更高
// 关于运算 可以直接源码查看
// int alpha = rgb >>> 24;
// int red = rgb >> 16 & 0xff;
// int green = rgb >> 8 & 0xff;
// int blue = rgb & 0xff;
// 方式二:使用提供Api
int alpha = Color.alpha(rgb);
int blue = Color.blue(rgb);
int red = Color.red(rgb);
int green = Color.green(rgb);
alpha = Math.round(alpha * percent);
return Color.argb(alpha, red, green, blue);
}
而基于以上内容,我们如何实现如下图效果呢?
先为大家讲述下思路:
1. 拿到Palette对图片分析结果,动态设置颜色值即可。
嗯哼,就是这么esay:
private void initImg1() {
ImageView iv = (ImageView) findViewById(R.id.id_image_test1);
BitmapDrawable drawable = (BitmapDrawable) iv.getDrawable();
Bitmap bitmap = drawable.getBitmap();
// 拿到图片 生成调色板
Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
// 载体
Palette.Swatch lightVibrantSwatch = palette.getLightMutedSwatch();
TextView tv = (TextView) findViewById(R.id.id_text1);
tv.setTextColor(lightVibrantSwatch.getTitleTextColor());
tv.setBackgroundColor(getTranslucentColor(0.5f, palette.getLightVibrantColor(Color.BLUE)));
}
});
}
而关于Palette调色板介绍到此结束,下面开启新篇章。
实际项目拓展
不知道大家还对微信、支付宝等等设置到绑定银行卡的界面还有没有印象?
为大家手绘一图,较为恶心,勿吐槽~
这个界面,大家想想怎么做?
首先,银行的Logo是我们后台返回,因为我们本地不可能保存所有银行的Logo;
其次,当前item的背景色和当前的Logo中颜色相近,而我们首先想到的就是,后台继续返回。
最后,我们基于本文,重新回顾下,现在的我们,拿到这个界面的时候,是如何玩转。
通过获取到当前item的银行Logo,我们调用Palette进行分析其中包含颜色值,最后拿到分析结果,赋值item背景即可。
关于代码设置圆角弧度以及渐变,提供如下方式:
/**
* 设置圆角弧度以及渐变
*
* @param startRGB
* @param endRGB
* @return
*/
private Drawable getImageViewShape(int startRGB, int endRGB) {
GradientDrawable shape = new GradientDrawable(GradientDrawable.Orientation.TL_BR
, new int[]{startRGB, endRGB});
shape.setShape(GradientDrawable.RECTANGLE);
shape.setGradientType(GradientDrawable.LINEAR_GRADIENT);
shape.setCornerRadius(8);
return shape;
}
部分代码如下:
private void initZS() {
ImageView iv=(ImageView) findViewById(R.id.iv_zs);
Bitmap bitmap = ((BitmapDrawable) iv.getDrawable()).getBitmap();
Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
// 载体
Palette.Swatch lightVibrantSwatch = palette.getLightMutedSwatch();
LinearLayout ll = (LinearLayout) findViewById(R.id.ll_zs);
((TextView) findViewById(R.id.tv_zs)).setTextColor(lightVibrantSwatch.getTitleTextColor());
ll.setBackgroundColor(palette.getDarkVibrantColor(Color.BLUE));
}
});
}
private void initYZ() {
BitmapDrawable drawable = (BitmapDrawable) ((ImageView) findViewById(R.id.iv_yz)).getDrawable();
Bitmap bitmap = drawable.getBitmap();
Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
// 载体
Palette.Swatch lightVibrantSwatch = palette.getLightMutedSwatch();
LinearLayout ll = (LinearLayout) findViewById(R.id.ll_yz);
((TextView) findViewById(R.id.tv_yz)).setTextColor(lightVibrantSwatch.getTitleTextColor());
ll.setBackgroundColor(palette.getDarkVibrantColor(Color.BLUE));
}
});
}
那么一起来看下效果:
其实,该给个间距的,不过这些对于老铁们简直分分钟,是吧?
这样做的好处在于一点,避免apk包含无用图标从而占用不必要的资源大小。
GitHub查看地址
赞赏
阅读到此,如觉得有所收获,不妨请LZ喝瓶水,一分也是爱呀~
The End
当年,刚刚撸码时,我们想的会写就好~
而今,撸了一次又一次码,我们想的如何写的更好~
未来,没有准确性,但是,只要努力,加油,未来,不会亏待~
推荐阅读
-
Android Study Material Design 十三 之CoordinatorLayout交互动画
-
Android Study Material Design 九 之 Hello TabLayout
-
Android Study Material Design 十二 之 FloatingActionButton初识
-
Android Study Material Design 五 番外篇 之:深入分析SnackBar源码
-
Android Study Material Design 十七 之 转场动画
-
Android Study Material Design 八 之 玩转Palette调色板
-
Android Study Material Design 七 之 谈谈ToolBar以及SearchView
-
Android Study Material Design 二 之:这可能是RecyclerView最全解析 初级使用(一)
-
Android Study Material Design 六 之:TextInputLayout学习及分析部分源码