Reputation: 822
I want to achieve something like this:
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
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
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>
Upvotes: 2