修改 Android 可绘制对象的颜色

2024-05-06

我希望能够使用相同的可绘制对象来表示两者:

Blue icon and Red icon

作为相同的可绘制对象,并根据某些编程值重新为可绘制对象着色,以便最终用户可以重新主题化界面。

做这个的最好方式是什么?我已经尝试过(并重复使用了其中的图标)这个以前的S.O.问题 https://stackoverflow.com/questions/4354939/understanding-the-use-of-colormatrix-and-colormatrixcolorfilter-to-modify-a-draw但我不能将这种变化表示为简单的色调变化,因为它的饱和度和明度也有所不同。

最好将我想要更改的区域的图标存储为全白色吗?还是透明的?或者其他纯色?

是否有某种方法可以让您根据红色图标的颜色和蓝色图标的颜色之间的差异计算出矩阵?


因此,经过大量的试验和错误,阅读不同的文章,最重要的是,通过 API 演示(ColorFilters.java - 在 com.example.android.apis.graphics 中找到)我找到了解决方案。

对于实体图像,我发现最好使用颜色滤镜 PorterDuff.Mode.SRC_ATOP 因为它将颜色覆盖在源图像的顶部,允许您将颜色更改为您正在寻找的确切颜色。

对于更复杂的图像(如上面的图像),我发现最好的办法是将整个图像着色为白色(FFFFFF),这样当您执行 PorterDuff.Mode.MULTIPLY 时,您最终会得到正确的颜色,并且图像中的所有黑色 (000000) 将保持黑色。

colorfilters.java 向您展示了在画布上绘图时是如何完成的,但如果您需要的只是为可绘制对象着色,那么这将起作用:

COLOR2 = Color.parseColor("#FF"+getColor());
Mode mMode = Mode.SRC_ATOP;
Drawable d = mCtx.getResources().getDrawable(R.drawable.image);
d.setColorFilter(COLOR2,mMode)

我使用一些 API 演示代码创建了一个演示活动,在每种颜色滤镜模式之间进行交换,以在不同的情况下尝试它们,并发现它非常有价值,所以我想我将其发布在这里。

public class ColorFilters extends GraphicsActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new SampleView(this));

}

private static class SampleView extends View {
    private Activity mActivity;
    private Drawable mDrawable;
    private Drawable[] mDrawables;
    private Paint mPaint;
    private Paint mPaint2;
    private float mPaintTextOffset;
    private int[] mColors;
    private PorterDuff.Mode[] mModes;
    private int mModeIndex;
    private Typeface futura_bold;
    private AssetManager assets;

    private static void addToTheRight(Drawable curr, Drawable prev) {
        Rect r = prev.getBounds();
        int x = r.right + 12;
        int center = (r.top + r.bottom) >> 1;
        int h = curr.getIntrinsicHeight();
        int y = center - (h >> 1);

        curr.setBounds(x, y, x + curr.getIntrinsicWidth(), y + h);
    }

    public SampleView(Activity activity) {
        super(activity);
        mActivity = activity;
        Context context = activity;
        setFocusable(true);

        /**1. GET DRAWABLE, SET BOUNDS */
        assets = context.getAssets();
        mDrawable = context.getResources().getDrawable(R.drawable.roundrect_gray_button_bg_nine);
        mDrawable.setBounds(0, 0, mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());

        mDrawable.setDither(true);

        int[] resIDs = new int[] {
            R.drawable.roundrect_gray_button_bg,
            R.drawable.order_button_white,
            R.drawable.yellowbar
        };
        mDrawables = new Drawable[resIDs.length];
        Drawable prev = mDrawable;
        for (int i = 0; i < resIDs.length; i++) {
            mDrawables[i] = context.getResources().getDrawable(resIDs[i]);
            mDrawables[i].setDither(true);
            addToTheRight(mDrawables[i], prev);
            prev = mDrawables[i];
        }

        /**2. SET Paint for writing text on buttons */
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setTextSize(16);
        mPaint.setTextAlign(Paint.Align.CENTER);

        mPaint2 = new Paint(mPaint);
        /** Calculating size based on font */
        futura_bold = Typeface.createFromAsset(assets,
                "fonts/futurastd-bold.otf");
        //Determine size and offset to write text in label based on font size.
        mPaint.setTypeface(futura_bold);
        Paint.FontMetrics fm = mPaint.getFontMetrics();
        mPaintTextOffset = (fm.descent + fm.ascent) * 0.5f;

        mColors = new int[] {
            0,
            0xFFA60017,//WE USE THESE
            0xFFC6D405,
            0xFF4B5B98,
            0xFF656565,
            0xFF8888FF,
            0xFF4444FF,
        };

        mModes = new PorterDuff.Mode[] {
            PorterDuff.Mode.DARKEN,
            PorterDuff.Mode.DST,
            PorterDuff.Mode.DST_ATOP,
            PorterDuff.Mode.DST_IN,
            PorterDuff.Mode.DST_OUT,
            PorterDuff.Mode.DST_OVER,
            PorterDuff.Mode.LIGHTEN,
            PorterDuff.Mode.MULTIPLY,
            PorterDuff.Mode.SCREEN,
            PorterDuff.Mode.SRC,
            PorterDuff.Mode.SRC_ATOP,
            PorterDuff.Mode.SRC_IN,
            PorterDuff.Mode.SRC_OUT,
            PorterDuff.Mode.SRC_OVER,
            PorterDuff.Mode.XOR
        };
        mModeIndex = 0;

        updateTitle();
    }

    private void swapPaintColors() {
        if (mPaint.getColor() == 0xFF000000) {
            mPaint.setColor(0xFFFFFFFF);
            mPaint2.setColor(0xFF000000);
        } else {
            mPaint.setColor(0xFF000000);
            mPaint2.setColor(0xFFFFFFFF);
        }
        mPaint2.setAlpha(0);
    }

    private void updateTitle() {
        mActivity.setTitle(mModes[mModeIndex].toString());
    }

    private void drawSample(Canvas canvas, ColorFilter filter) {
        /** Create a rect around bounds, ensure size offset */
        Rect r = mDrawable.getBounds();
        float x = (r.left + r.right) * 0.5f;
        float y = (r.top + r.bottom) * 0.5f - mPaintTextOffset;

        /**Set color filter to selected color 
         * create canvas (filled with this color)
         * Write text using paint (new color)
         */
        mDrawable.setColorFilter(filter);
        mDrawable.draw(canvas);
        /** If the text doesn't fit in the button, make the text size smaller until it does*/
        final float size = mPaint.measureText("Label");
        if((int) size > (r.right-r.left)) {
            float ts = mPaint.getTextSize();
            Log.w("DEBUG","Text size was"+ts);
            mPaint.setTextSize(ts-2);
        }
        canvas.drawText("Sausage Burrito", x, y, mPaint);
        /** Write the text and draw it onto the drawable*/

        for (Drawable dr : mDrawables) {
            dr.setColorFilter(filter);
            dr.draw(canvas);
        }
    }

    @Override protected void onDraw(Canvas canvas) {
        canvas.drawColor(0xFFCCCCCC);            

        canvas.translate(8, 12);
        for (int color : mColors) {
            ColorFilter filter;
            if (color == 0) {
                filter = null;
            } else {
                filter = new PorterDuffColorFilter(color,
                                                   mModes[mModeIndex]);
            }
            drawSample(canvas, filter);
            canvas.translate(0, 55);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
                // update mode every other time we change paint colors
                if (mPaint.getColor() == 0xFFFFFFFF) {
                    mModeIndex = (mModeIndex + 1) % mModes.length;
                    updateTitle();
                }
                swapPaintColors();
                invalidate();
                break;
            }
        return true;
        }
    }
}

如果您想对其进行测试,可以直接从 API 演示活动复制其他两个依赖项 GraphicsActivity.java 和 PictureLayout.java。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

修改 Android 可绘制对象的颜色 的相关文章

  • 找不到参数的方法 dependencyResolutionManagement()

    我正在尝试使用老师给我的一个项目 但它显示了一个错误 Settings file Users admin AndroidStudioProjects HTTPNetworking settings gradle line 1 A probl
  • 如何对这个字符串进行子串化

    我想得到这个字符串的 4 个部分 String string 10 trillion 896 billion 45 million 56873 我需要的4个部分是 10万亿 8960亿 4500万 和 56873 我所做的是删除所有空格 然
  • 如何快速自动发送FCM或APNS消息?

    我正在开发一项后端服务 通过 FCM 或 APNS 向移动应用程序发送推送通知 我想创建一个可以在一分钟内运行的自动化测试 并验证服务器是否可以成功发送通知 请注意 我不一定需要检查通知是否已送达 只需检查 FCM 或 APNS 是否已成功
  • android中向sqlite中插入大量数据

    目前 我必须一次向我的 Android 中插入超过 100 亿条数据 然而 内存不足的问题会使程序崩溃 sqlite 插入测试非常简单 只需使用 for 循环生成 sql 插入命令并通过 开始 和 提交 进行包装 private Array
  • SearchView过滤ListView

    我已经实现了搜索视图来过滤我的列表视图项目 当我输入任何文本时 它会过滤列表 但当我退出搜索视图时 它不会返回原始列表项 public class PlacesListAdapter extends ArrayAdapter
  • Android 后退按钮无法与 Flutter 选项卡内的导航器配合使用

    我需要在每个选项卡内有一个导航器 因此当我推送新的小部件时 选项卡栏会保留在屏幕上 代码运行得很好 但是 android 后退按钮正在关闭应用程序而不是运行 Navigator pop import package flutter mate
  • 谷歌坐标认证

    当我尝试连接到 Google 坐标时 总是出现异常GoogleAuthException 我拥有 Google 地图协调中心许可证 我确实使用我的包应用程序名称和 SHA1 在 google 控制台中创建了我的客户端 ID 我将权限添加到清
  • 如何在android中获取Camera2 API的当前曝光

    In android hardware Camera旧的 我使用下面的代码获取当前曝光并获取它Camera Camera Parameters param mCamera getParameters currentExposure para
  • 无法访问 com.google.android.gms.internal.zzbfm 的 zzbfm 类文件未找到

    我正在将我的 Android 应用程序项目从GCM to FCM 为此 我使用 Android Studio 中的 Firebase 助手工具 并遵循 Google 开发人员指南中的说明 一切都很顺利 并将我的应用程序代码更改为FCM根据助
  • 如何使用 Cordova 获取当前安装的应用程序的版本?

    我已经找到了应用程序可用性插件 https github com ohh2ahh AppAvailability它主要检查用户是否在其设备上安装了某个应用程序 是否有可能获得应用程序的当前版本 开发者名称 重要 以及所有可能的信息 一般来说
  • Android MediaExtractor seek() 对 MP3 音频文件的准确性

    我在使用 Android 时无法在eek 上获得合理的准确度MediaExtractor 对于某些文件 例如this one http www archive org download emma solo librivox emma 01
  • Ubuntu 16.04 - Genymotion:找不到 /dev/hw_random

    I install Genymotion on the Ubuntu 16 04 64Bit I created a virtual emulator for Android 6 0 then I run this emulator but
  • 如何使用InputConnectionWrapper?

    我有一个EditText 现在我想获取用户对此所做的所有更改EditText并在手动将它们插入之前使用它们EditText 我不希望用户直接更改中的文本EditText 这只能由我的代码完成 例如通过使用replace or setText
  • Android访问远程SQL数据库

    我可以直接从 Android 程序访问远程 SQL 数据库 在网络服务器上 吗 即简单地打开包含所有必需参数的连接 然后执行 SQL 查询 这是一个私人程序 不对公众开放 仅在指定的手机上可用 因此我不担心第三方获得数据库访问权限 如果是这
  • Android Studio - Windows 7 上的 Android SDK 问题

    我对 Google i o 2013 上发布的最新开发工具 Android Studio 有疑问 我已经成功安装了该程序并且能够正常启动 我可以导入现有项目并对其进行编辑 但是 当我尝试单击 SDK 管理器图标或 AVD 管理器图标时 或者
  • Android向menuItem添加子菜单,addSubMenu()在哪里?

    我想根据我的参数以编程方式将 OptionsMenu 内的子菜单添加到 menuItem 中 我检查了android sdk中的 MenuItem 没有addSubMenu 方法 尽管你可以找到 hasSubMenu 和 getSubMen
  • .isProviderEnabled(LocationManager.NETWORK_PROVIDER) 在 Android 中始终为 true

    我不知道为什么 但我的变量isNetowrkEnabled总是返回 true 我的设备上是否启用互联网并不重要 这是我的GPSTracker class public class GPSTracker extends Service imp
  • 增加活动的屏幕亮度

    显然 Android 操作系统中至少有三种不同的技术可以改变屏幕亮度 其中两个在纸杯蛋糕之后不再起作用 而第三个被接受的技术显然有一个错误 我想在单视图活动开始时增加屏幕亮度 然后在活动结束时将亮度恢复为用户设置 没有按钮 没有第二个视图或
  • 将两个文本视图并排放置在布局中

    我有两个文本视图 需要在布局中并排放置 并且必须遵守两条规则 Textview2 始终需要完整显示 如果布局中没有足够的空间 则必须裁剪 Textview1 例子 文本视图1 文本视图2 Teeeeeeeeeeeeeeeeeextview1
  • 强制 Listview 不重复使用视图(复选框)

    我做了一个定制Listview 没有覆盖getView 方法 Listview 中的每个项目都具有以下布局 联系布局 xml

随机推荐

  • 使用 PHP 发布到 Blogger

    我在使用 PHP 的 Blogger API 时遇到问题 我需要的是能够将新的博客文章发布到我的博客帐户 我使用的代码取自 Google API 页面 http code google com intl nl apis blogger do
  • 使用 avg 和 group by 进行 SQL 查询

    我在为 MySQL 编写 SQL 查询时遇到一些问题 我有一个具有以下结构的表 mysql gt select id pass val from data r1 limit 10 id pass val DA02959106 5 00000
  • Kubernetes coredns pod 陷入待处理状态。无法启动仪表板[关闭]

    Closed 这个问题是与编程或软件开发无关 help closed questions 目前不接受答案 我正在按照此构建 Kubernetes 集群tutorial https www profiq com kubernetes clus
  • mysqli_query() 需要至少 2 个参数,其中 1 个参数在? [复制]

    这个问题在这里已经有答案了 每次运行这个 php ini 时 我都会遇到同样的 3 个错误 我不知道我做错了什么 有人可以帮忙吗 以下是错误 2014 年 5 月 5 日 19 20 50 美洲 芝加哥 PHP 警告 mysqli quer
  • 我们如何针对 DOM 操作执行单元测试?

    QUnit 的介绍位于netTuts com http net tutsplus com tutorials javascript ajax how to test your javascript code with qunit 关于如何针
  • tsconfig.json:构建:在配置文件中找不到输入

    我有一个 ASP NET core 项目 当我尝试构建它时收到此错误 error TS18003 Build No inputs were found in config file Z Projects client ZV src ZV S
  • 如何通过成员函数指针进行调用?

    我正在尝试使用成员函数指针进行一些测试 这段代码有什么问题 这bigCat pcat 语句无法编译 class cat public void walk printf cat is walking n int main cat bigCat
  • Tensorflow:docker 镜像和 -gpu 后缀

    在具有 GPU 支持的 Tensorflow 的 Docker 映像中 例如 tensorflow tensorflow 2 2 0 gpu 安装的python包是tensorflow gpu 如图所示pip freeze 安装任何依赖于的
  • 为什么 Visual Studio 使用 xchg ax,ax

    我正在查看程序的反汇编 因为它崩溃了 并注意到很多 xchg ax ax 我用谷歌搜索了一下 发现它本质上是一个 nop 但是为什么 Visual Studio 会执行 xchg 而不是 noop 该应用程序是一个C NET3 5 64位应
  • 导入错误:没有名为 PyQt4 的模块

    我使用 Homebrew 安装了 pyqt4 但是当我在 python 解释器中导入 PyQt4 时 它说 没有名为 PyQt4 的模块 有人可以帮我吗 After brew install pyqt 你可以brew test pyqt它将
  • 如何将java库添加到kotlin本机

    所以我尝试使用intellij创建kotlin native应用程序 我在项目创建中选择了模板kotlin gt kotlin native 它创建了示例 gradle hello world 项目 下载所有依赖项后编译为exe文件并正常运
  • "$(document).on('pageshow'" 不适用于 jQuery 1.9.1 + JQM 1.3.0-stable

    使用 jQuery 1 8 3
  • 选项卡式导航

    我真的很难弄清楚如何执行以下操作 我想要有两个选项卡 水平相邻 一个用于搜索 并如此标记 另一个用于帖子 如此标记 当选择搜索选项卡时 我希望出现一个搜索框 当选择帖子选项卡时 我希望出现另一个搜索框 我不想隐藏搜索框 我猜它本质上是使用
  • 从 Json Python 获取特定字段值

    我有一个 JSON 文件 我想做的是获取这个特定字段 id 问题是当我使用json load input file 它说我的变量data是一个列表 而不是字典 所以我不能做类似的事情 for value in data id print d
  • Jquery 事件处理程序返回值

    返回值有什么用处吗 click and change 处理程序 如return true or return false return false 将阻止事件冒泡AND抑制默认操作 换句话说 返回 false 类似于这两行 event st
  • 获取已连接 USB 设备的端口名称

    当USB设备连接到计算机时 如何使用C 代码获取它所连接的端口名称 我找到了很多方法来查找 USB 何时连接 断开 驱动器号 路径 设备 ID 等 但没有找到任何明确的示例来说明如何知道它连接到哪个端口 我看到了一种可能的解释 但这涉及很多
  • MbUnit v3 中的UsingFactories 替代方案

    我试图弄清楚如何在 MbUnit v3 中编写组合测试 网上的所有示例代码均参考MbUnit v2 这意味着使用3个属性 组合测试 Factory 使用工厂 在 MbUnit v3 中 没有 usingFactories 属性 并且 Fac
  • 删除networkx有向图中入度和出度等于1的所有节点

    假设我在 NetworkX 中制作了一个有向图 import networkx as nx G nx DiGraph n A B C D E F H I J K L X Y Z e A Z Z B B Y Y C C G G H G I I
  • 算法:最大计数器

    我有以下问题 您有 N 个计数器 最初设置为 0 并且您对它们有两种可能的操作 increase X 计数器 X 加 1 max counter 所有计数器都设置为任何计数器的最大值 给出一个包含 M 个整数的非空零索引数组 A 该数组代表
  • 修改 Android 可绘制对象的颜色

    我希望能够使用相同的可绘制对象来表示两者 and 作为相同的可绘制对象 并根据某些编程值重新为可绘制对象着色 以便最终用户可以重新主题化界面 做这个的最好方式是什么 我已经尝试过 并重复使用了其中的图标 这个以前的S O 问题 https