【发布时间】:2016-01-01 17:59:33
【问题描述】:
Google 设计了一个color palette。给定一种颜色,我想在 Android 中动态创建调色板。
Graphic Design site 和 an open source javascript solution 中有一个类似的问题,它生成了类似的调色板。每种颜色的因子在here 中找到,用于创建颜色的函数在this stackoverflow answer 中找到。
我使用该答案和项目来生成类似于 Google 的调色板。但是,我想要一种算法,它可以返回 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);
由上述代码创建的对话框:
【问题讨论】:
-
很好奇为什么需要动态创建它;你不能把它作为应用程序中的资源吗?
-
@ChiefTwoPencils,是的,我可以将所有颜色作为资源。为什么?为了科学。 :)
-
您从我的答案中使用的算法并非 100% 准确。它不使用 HSL 来变亮或变暗。 Google 的调色板可能使用适当的 HSL 转换来变亮(提高 L)。如果需要准确性,建议使用 TinyColor 对我的回答进行评论。我的是为了速度。
-
此外,虽然 Google 调色板确实为每种原色提供 9 种强调色,但总共有 10 种。目前尚不清楚他们所做的阴影是否恰好是每级 10%,因为它会导致一个相信。我的意思是,他们列出的范围是 50-900... 不完全是 100-1000 我会说...您可以看到 900 并没有像我认为的 90% 那样接近黑色
-
我打算写一个正确的答案,但后来我意识到我没有设置我的 Android Dev Env 并且无法对其进行测试或正确编码。但是在使用
RGBToHSV来转换它的某个地方......然后提高/降低B或V或L或者他们在Android上称之为翻转...... 10%......然后使用HSVToColor转换回来
标签: android colors material-design