Ivan Fork
Ivan Fork

Reputation: 822

What is the best way to colour a part of the letter?

I want to achieve something like this:

enter image description here

The first thing that comes to mind is to draw the text on a canvas two times and cover the first text with a shape. But maybe there is a better solution.

Upvotes: 4

Views: 310

Answers (2)

Karakuri
Karakuri

Reputation: 38595

One approach is using a PorterDuffXfermode for compositing the blue rectangle over the text. You could extend TextView and override onDraw() to draw the rectangle after the text has been drawn, and with the proper mode (I believe XOR is the one you want) it should achieve the desired effect. Something like this:

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
    }
}

More info on Porter/Duff compositing: http://ssp.impulsetrain.com/porterduff.html

Upvotes: 3

Shaunak
Shaunak

Reputation: 18018

Your approach sounds good for a pure android solution, however I am going to go a little unconventional here and suggest that you make that part of your UI into a HTML component web-view and go with html-css solution as this kind of rendering is a lot easier to do. Not sure if this is idea solution for Purists, but it certainly sounds easily doable. Check this working example where I tried to re-create your UI (Just hit run code snippet, or check the jsfiddle link at the end):

function barWidth() {
    var barWidth = $('.progress-bar').width();
    $('.progress-fill-text').css('width',barWidth);
}
barWidth();
window.onresize = function() {
    barWidth();
}
.progress-bar {
    background:#ccc;
    color: #7d7d7d;
    padding:10px 0;
    width:100%;
    text-align:center;
    position:relative;
    font-size: 40px;
    font-family: 'Open Sans', sans-serif;
}

.progress-fill {
    background:#0095dd;
    color:#fff;
    width:47%;
    padding:10px 0;
    position:absolute;
    left:0;
    top:0;
    overflow:hidden;
}

.progress-fill-text {
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>

<div class="progress-bar">
    <div class="progress-fill">
        <div class="progress-fill-text">37 UNITS</div>
    </div>
    37 UNITS
</div>

http://jsfiddle.net/zkL29/56/

Upvotes: 2

Related Questions