Android 给信的一部分涂颜色最好的方法是什么?

Android 给信的一部分涂颜色最好的方法是什么?,android,Android,我想实现这样的目标: public class ProgressTextView extends TextView { private static final float MAX_PROGRESS = ...; private Paint mPaint; public ProgressTextView(Context context) { super(context); initPaint(); } /* othe

我想实现这样的目标:

public class ProgressTextView extends TextView {

    private static final float MAX_PROGRESS = ...;

    private Paint mPaint;

    public ProgressTextView(Context context) {
        super(context);
        initPaint();
    }

    /* other constructor omitted, but do the same pattern in those */

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setColor(...);
        mPaint.setXfermode(new PorterDuffXfermode(Mode.XOR));
        // note: you may also need the following line if hardware accel is available
        setLayerType(LAYER_TYPE_SOFTWARE, null);
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawProgress(canvas);
    }

    private void drawProgress(Canvas canvas) {
        int w = getWidth() - getPaddingLeft() - getPaddingRight();
        int h = getHeight() - getPaddingTop() - getPaddingBottom();
        float progress = getProgress();
        float rectW = w * (progress / MAX_PROGRESS);

        int saveCount = canvas.save();
        canvas.translate(getPaddingLeft(), getPaddingTop());
        canvas.drawRect(0, 0, rectW, h, mPaint);
        canvas.restoreToCount(saveCount);
    }

    private float getProgress() {
        // TODO
    }
}


首先想到的是在画布上画两次文本,并用形状覆盖第一个文本。但是也许有更好的解决方案。

对于纯android解决方案来说,您的方法听起来不错,但是我在这里要做的有点非传统,建议您将UI的这一部分转换为HTML组件web视图,并使用HTML css解决方案,因为这种渲染要容易得多。不确定这是否是纯粹主义者的理想解决方案,但听起来确实很容易做到。检查这个我试图重新创建UI的工作示例(只需点击运行代码片段,或检查最后的JSFIDLE链接):

函数条宽度(){
var barWidth=$('.progress bar').width();
$('.progress fill text').css('width',barWidth);
}
条宽();
window.onresize=函数(){
条宽();
}
。进度条{
背景:#ccc;
颜色:#7d7d7d;
填充:10px0;
宽度:100%;
文本对齐:居中;
位置:相对位置;
字体大小:40px;
字体系列:“开放式Sans”,无衬线;
}
.进度填写{
背景:#0095dd;
颜色:#fff;
宽度:47%;
填充:10px0;
位置:绝对位置;
左:0;
排名:0;
溢出:隐藏;
}
.进度填写文本{
}

37个单位
37个单位

一种方法是使用
PorterDuffXfermode
在文本上合成蓝色矩形。您可以扩展
TextView
并覆盖
onDraw()
以在绘制文本后绘制矩形,并且使用适当的模式(我相信
XOR
就是您想要的模式)应该可以达到所需的效果。大概是这样的:

public class ProgressTextView extends TextView {

    private static final float MAX_PROGRESS = ...;

    private Paint mPaint;

    public ProgressTextView(Context context) {
        super(context);
        initPaint();
    }

    /* other constructor omitted, but do the same pattern in those */

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setColor(...);
        mPaint.setXfermode(new PorterDuffXfermode(Mode.XOR));
        // note: you may also need the following line if hardware accel is available
        setLayerType(LAYER_TYPE_SOFTWARE, null);
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawProgress(canvas);
    }

    private void drawProgress(Canvas canvas) {
        int w = getWidth() - getPaddingLeft() - getPaddingRight();
        int h = getHeight() - getPaddingTop() - getPaddingBottom();
        float progress = getProgress();
        float rectW = w * (progress / MAX_PROGRESS);

        int saveCount = canvas.save();
        canvas.translate(getPaddingLeft(), getPaddingTop());
        canvas.drawRect(0, 0, rectW, h, mPaint);
        canvas.restoreToCount(saveCount);
    }

    private float getProgress() {
        // TODO
    }
}

有关Porter/Duff合成的更多信息:

在web环境中可能很理想,但当您需要通过视图结构控制内容时就不行了。即使使用web视图,您也可以通过Java代码控制web视图。考虑到这一点,你所要做的就是在进度条中的CSS中更改<代码>宽度>代码> PARAM。现在,如果你再编写一点JavaScript,从URL读取宽度,从Android代码中,你可以不断更新web视图的JavaScript路径,你就有了一个动态组件。是的,你可以,但主要的问题是,对于这么简单的东西来说,这似乎有些过分了。另外,让我们假设应该有一个动画如何在内容上需要渲染/动画,除非你是一个网络专家,使动画更专注于Web组件。我并不是说这是不可能的,我只是说,对于一个应用程序(在android中)来说,使用这样的东西可能更需要维护成本,而这个应用程序在任何方面都不可能是面向网络的。在所有方面,我都同意你的看法。这只是我建议的另一种选择。我想这要归结为编写和维护本机渲染的复杂程度,而不是实现html组件的成本。我想知道是否还有其他解决方案。如果某人的应用程序是面向web的,那么无论哪种方式+1都绝对是一个很好的方法:)这应该是一个进度条吗?或者只是突出显示了数字?听起来你想要的是
paint.setXfermode(新的PorterDuffXfermode(PorterDuff.Mode.XOR))查看此问题了解更多信息:注意:我在@theFunkyEngineer发表评论之前就开始写此答案,但他链接的帖子也很有用。这看起来方向正确,但当我使用Mode.XOR时,它会删除rect和文本,我尝试过其他模式,但没有成功。@IvanFork尝试使用调试器,并确保绘图在正确的坐标下进行。也许可以删除
Paint
上的
Xfermode
,看看它是否在正确的位置绘制。另外,其中有一个注释行调用视图上的
setLayerType()
,您可能需要取消注释以使其正常工作。您是否测试了代码?如果有效,您可以提供xml吗?我尝试过使用所有PorterDuff模式的多种方法,但遗憾的是它们都不起作用,通常文本会随着rect完全剪切。最后,我使用canvas.clipRect再次绘制了文本的后半部分。@IvanFork我不得不取消对
setLayerType()
调用的注释,但除此之外,它的工作方式与使用
XOR
时的预期完全相同。