Google设计了一个color palette。给定一种颜色,我想在Android中动态创建调色板。
Graphic Design site和an open source javascript solution中存在类似的问题,会生成类似的调色板。找到每种颜色的因子here,用于创建颜色的函数可在this stackoverflow answer中找到。
我用这个答案和项目来生成一个类似于谷歌的调色板。但是,我想要一个能够返回Google生成的确切值的算法(参见第一个链接)。
问题:Google如何计算材料设计的调色板颜色?
根据上面的信息,我创建了这个例子,以展示我是如何生成类似的调色板的。同样,我想要准确的值。
import android.app.Activity;
import android.app.AlertDialog;
import android.graphics.Color;
import android.os.AsyncTask;
import android.view.Gravity;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.List;
/**
* @author Jared Rummler <jared.rummler@gmail.com>
*/
public class PaletteTask extends AsyncTask<Integer, Void, List<PaletteTask.Shade>> {
private static int shadeColor(int color, double percent) {
return shadeColor(String.format("#%06X", (0xFFFFFF & color)), percent);
}
private static int shadeColor(String color, double percent) {
long f = Long.parseLong(color.substring(1), 16);
double t = percent < 0 ? 0 : 255;
double p = percent < 0 ? percent * -1 : percent;
long R = f >> 16;
long G = f >> 8 & 0x00FF;
long B = f & 0x0000FF;
int red = (int) (Math.round((t - R) * p) + R);
int green = (int) (Math.round((t - G) * p) + G);
int blue = (int) (Math.round((t - B) * p) + B);
return Color.rgb(red, green, blue);
}
private final WeakReference<Activity> activityWeakReference;
private final List<Shade> shades = new LinkedList<>();
{
shades.add(new Shade(0.9, "50"));
shades.add(new Shade(0.7, "100"));
shades.add(new Shade(0.5, "200"));
shades.add(new Shade(0.333, "300"));
shades.add(new Shade(0.166, "400"));
shades.add(new Shade(0, "500"));
shades.add(new Shade(-0.125, "600"));
shades.add(new Shade(-0.25, "700"));
shades.add(new Shade(-0.375, "800"));
shades.add(new Shade(-0.5, "900"));
shades.add(new Shade(0.7, "A100"));
shades.add(new Shade(0.5, "A200"));
shades.add(new Shade(0.166, "A400"));
shades.add(new Shade(-0.25, "A700"));
}
public PaletteTask(Activity activity) {
activityWeakReference = new WeakReference<>(activity);
}
@Override protected List<Shade> doInBackground(Integer... colors) {
for (Shade shade : shades) {
shade.color = shadeColor(colors[0], shade.percent);
}
return shades;
}
@Override protected void onPostExecute(List<Shade> shades) {
Activity activity = activityWeakReference.get();
if (activity == null || activity.isFinishing()) {
return;
}
// Create a dialog that shows our generated colors:
ScrollView scrollView = new ScrollView(activity);
LinearLayout linearLayout = new LinearLayout(activity);
linearLayout.setOrientation(LinearLayout.VERTICAL);
int width, height;
width = LinearLayout.LayoutParams.MATCH_PARENT;
height = (int) (30/*dp*/ * (activity.getResources().getDisplayMetrics().densityDpi / 160f));
// add each color
for (Shade shade : shades) {
LinearLayout layoutColor = new LinearLayout(activity);
TextView textView = new TextView(activity);
layoutColor.setLayoutParams(new LinearLayout.LayoutParams(width, height));
layoutColor.setBackgroundColor(shade.color);
layoutColor.setGravity(Gravity.CENTER);
textView.setText(shade.name + " " + String.format("#%06X", (0xFFFFFF & shade.color)));
layoutColor.addView(textView);
linearLayout.addView(layoutColor);
}
scrollView.addView(linearLayout);
new AlertDialog.Builder(activity).setView(scrollView).show();
}
public static class Shade {
final double percent;
final String name;
int color;
public Shade(double percent, String name) {
this.percent = percent;
this.name = name;
}
}
}
调用AsynTask
:
int materialRed500 = 0xFFF44336;
new PaletteTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, materialRed500);
根据以上代码创建的对话框:
答案 0 :(得分:6)
底线,您无法使用与相应的Google Material Design Palette完全匹配的单一颜色生成调色板。
这是因为调色板都遵循不同的颜色进展。例如,使用以下进程生成红色调色板(使用TinyColor.js的JS代码,但您仍然可以看到HSL修改):
return [
{ hex : tinycolor( hex ).lighten( 37.7 ).saturate( 10.4 ).spin( -13 ).toHexString(), name : '50' },
{ hex : tinycolor( hex ).lighten( 31.8 ).saturate( 10.4 ).spin( -9.5 ).toHexString(), name : '100' },
{ hex : tinycolor( hex ).lighten( 18.7 ).desaturate( 17 ).spin( -3.9 ).toHexString(), name : '200' },
{ hex : tinycolor( hex ).lighten( 9.1 ).desaturate( 20.9 ).spin( -4 ).toHexString(), name : '300' },
{ hex : tinycolor( hex ).lighten( 4.1 ).desaturate( 6.6 ).spin( -3 ).toHexString(), name : '400' },
{ hex : hex, name : '500' },
{ hex : tinycolor( hex ).darken( 3.1 ).desaturate( 12.4 ).spin( -2.7 ).toHexString(), name: '600' },
{ hex : tinycolor( hex ).darken( 7.8 ).desaturate( 24.5 ).spin( -4 ).toHexString(), name: '700' },
{ hex : tinycolor( hex ).darken( 11.7 ).desaturate( 23.2 ).spin( -4 ).toHexString(), name: '800' },
{ hex : tinycolor( hex ).darken( 17 ).desaturate( 16.1 ).spin( -4 ).toHexString(), name: '900' },
{ hex : tinycolor( hex ).lighten( 16.7 ).saturate( 10.4 ).spin( 0.6 ).toHexString(), name: 'A100' },
{ hex : tinycolor( hex ).lighten( 7.7 ).saturate( 10.4 ).spin( -4 ).toHexString(), name: 'A200' },
{ hex : tinycolor( hex ).darken( 3.9 ).saturate( 10.4 ).spin( -15.5 ).toHexString(), name: 'A400' },
{ hex : tinycolor( hex ).darken( 16.6 ).saturate( 10.4 ).spin( -4 ).toHexString(), name: 'A700' }
];
但是,当您将相同的进展应用于Indigo基色(500)时,您可以看到调色板根本不匹配。在下图中,最左边的调色板是默认的MD调色板,左边的第二个调色板是使用上述进度生成的调色板。这两个调色板完全匹配。当我加载MD Indigo调色板(第三个调色板),然后使用Indigo 500值和红色调色板渐进代码生成调色板时,它会创建第4个调色板。正如你所看到的,虽然这种进展对于红色来说是完全正确的,但对于其他颜色来说还是如此:
有关此主题的更多信息,请here。 谷歌选择的颜色很可能是由设计师亲自挑选的,而不是以编程方式生成的。
编辑:此外,该MCG的代码已经完全修改。可以找到颜色的新逻辑here,并使用tinycolor.js作为修改函数。
答案 1 :(得分:1)
接受的答案中的逻辑是错误的。它不会为您生成真实的材料颜色。有一个官方的材质调色板工具here。如果需要,可以尝试比较。
不幸的是,谷歌没有提供上述工具的库,这是一个经过精简和打包的javascript文件,其中包含redux。我和我的同事,我们进行了逆向工程,以获得仅产生颜色的零件,您可以here进行查看。请记住,这不是我的代码。
您可以尝试here 与以下行。
materialColorPicker('00ff00')
此调色板具有所选颜色的不同色调,分别是:50、100、200、300、400、500、600、700、800、900 但是给定的颜色可以是这些色调中的任何一种。
例如,如果您选择红色,则此调色板将为您提供以下设置。
50: "ffe7e6"
100: "ffc7b8"
200: "ffa28a"
300: "ff795b"
400: "ff5436"
500: "ff200c"
600: "ff1507"
700: "ff0000" // input colour
800: "f10000"
900: "da0000"
但是,如果您选择#17996b的颜色,则调色板将产生以下值:
50: "e0f3ec"
100: "b4e0cf"
200: "84cdb1"
300: "54b893"
400: "32a97f"
500: "17996b" // input colour
600: "138c60"
700: "0d7c52"
800: "016c45"
900: "00502a"
如您所见,您认为是原色的输入色可以是任何一种原色。