I want to show some static text over seek bar track.
It's different from what's normally required, i.e., showing current progress as tip or inside thumb.
I've tried both options of showing text; By adding a TextView over seekbar or by adding it dynamically in onDraw() method of my custom seekbar class.
NORMAL VIEW:
PROBLEM VIEW:
The issue is that the text is ABOVE both track and seekbar (as shown above). I somehow want to decrease the z-index of text so that it hides behind the thumb.
I'm overriding the onDraw method like:
#Override
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.getTextBounds(text, 0, text.length(), bounds);
paint.setTextSize(36);
int x = getWidth() / 2 - bounds.centerX();
int y = getHeight() / 2 - bounds.centerY();
canvas.drawText(text, x, y, paint);
}
Is there a way I can hide text behind thumbnail?
Any help is greatly appreciated.
Related
Whenever extending the class, the bar will be drawn in the vertical center of its container. I need to place text above the bar and increasing the height (I am setting an arbitrary height on the view) causes a bunch of blank space beneath the bar. I've been googling for quite some time now but all I find is regarding the thumb mostly, and I need to draw the bar on the bottom of its container.
This is what I'm trying to achieve as a single view (notice how the bar's position in not centered):
The only "useful" code I could find was this:
Window window = ((Activity) getContext()).getWindow();
window.setGravity(Gravity.BOTTOM);
WindowManager.LayoutParams wmlp = window.getAttributes();
wmlp.y = getHeight() / 4;
window.setAttributes(wmlp);
But it has no effect whatsoever.
My custom class, nothing out of the ordinary:
public class RateSeekbar extends AppCompatSeekBar {
private Paint lettersPaint;
private Paint numberPaint;
// constructors and call to init()
private void init() {
lettersPaint = new Paint();
numberPaint = new Paint();
... // style the two different paints
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
... // get a couple of strings from resources and measure them
int middleHor = getWidth() / 2;
canvas.drawText(text1, getPaddingLeft(), 40, lettersPaint);
canvas.drawText(text2, getWidth() - text2Size - getPaddingRight(), 40, lettersPaint);
canvas.drawText(String.valueOf(getProgress()), middleHor - (text3Size / 2), 50, numberPaint);
}
}
Any ideas?
I have a ViewGroup that consists on a header and a circle of menu items. Basically I have a closing/opening animation where my item views go behind the header view. Since all views have transparencies, when the item views go behind the header view, they are still visible and end up appearing behind the header view through the transparencies.
What I wanted to do is to intersect the item views with the hweader view, erasing the intersection. What I came up with was to override dispatchDraw and do something like PorterDuff.Mode.CLEAR
But I can only do this to all views at once, in the sense. Using the code below, it'll erase everything that's been drawn in the view in that specific area, thus the header as well.
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
//do stuff here
}
Is there any way i can draw the view again, or even select which views I want to erase?
Just for future reference, this is what I did. Override dispatch draw, erase the given area and draw the child again with child.draw(canvas)
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
Paint p = new Paint();
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawCircle((float) center.x, (float) center.y, headerSize / 2, p);
canvas.save();
canvas.translate(padding, padding);
getChildAt(0).draw(canvas);
canvas.restore();
}
I need a progress bar displaying progress from right to left or from left to right depending on variable. I have also text in the middle of the bar. For all that, I am using a custom class. For rotating the bar, I followed this thread but somehow either the text is not displayed, or it is rotated, or everything disappears from the view...
Code without rotation:
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw text
}
I have a property positive telling whether to start from left or from right. It would be easy, if I didn't had the text, I would simply call setRotation() somewhere in the code, but now I am trying to rotate the canvas and I can't manage it to bring everything in the correct order. Can someone help me?
I just found it out. Using this thread, I ended up with the following code:
protected synchronized void onDraw(Canvas canvas) {
canvas.save();
if(!positive) {
int cx = this.getMeasuredWidth() / 2;
int cy = this.getMeasuredHeight() / 2;
canvas.scale(-1f, 1f, cx, cy);
}
super.onDraw(canvas);
canvas.restore();
// draw text
}
I have no idea why rotation doesn't work for me but the scale method works fine.
I have a custom ScoreView that consists of two lines of text (a name and a score). Behind that text, I am drawing a bar representing the score.
I have a fragment that contains three such ScoreViews. When I update the ScoreViews with a new name or score, everything works fine. However, if I update the rectangle behind them, only the first rectangle is redrawn.
The end result is something like this:
All three ScoreViews should have a gray bar behind the text.
To prevent the possibility of my fill color attribute causing this, I am statically setting the bar's color in the ScoreView.
ScoreView snippet:
public class ScoreView extends View {
public void setFillPercent(float percent) {
mFillPercent = percent;
mFillRect = new Rect(getLeft(), getTop(), getLeft() + Math.round(mFillPercent*getWidth()), getBottom());
invalidate();
requestLayout();
}
#Override
protected void onSizeChanged (int w, int h, int oldw, int oldh) {
mFillRect = new Rect(getLeft(), getTop(), getLeft() + Math.round(mFillPercent*w), getBottom());
mTextXPos = getLeft() + 20; // TODO dp?
mNameTextYPos = h/2 - (int)mNameTextSize;
mScoreTextYPos = h/2 + (int)mScoreTextSize;
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawRect(mFillRect, mFillPaint);
canvas.drawText(mName, mTextXPos, mNameTextYPos, mNameTextPaint);
canvas.drawText(String.valueOf(mScore), mTextXPos, mScoreTextYPos, mScoreTextPaint);
}
}
In my fragment, I call:
oneScoreView.setFillPercent(.5f);
twoScoreView.setFillPercent(.5f);
threeScoreView.setFillPercent(.5f);
I set a breakpoint in onDraw() and I can see that it is being called, and that mFillRect has the correct size and position. It simply doesn't get displayed.
I also discovered that if I rearrange the three ScoreViews, it is always the first ScoreView that updates properly.
I am not sure, but mFillRect = new Rect(getLeft(), getTop(), getLeft() it means you set offset left and top of the view, but then you use this rectangle to draw inside the same view. I think it's just out of view's canvas area, that's why you cannot see it. I might be wrong though.
I need to create a progressbar in arc shape. should I create a custom view for that? Or with the help of onDraw() method of ProgressBar class I can perform this thing? I also want to add marker on this progressBar like thermometer. Please suggest me any idea. Thanks.
Something like this:
protected synchronized void onDraw(Canvas canvas) {
int progress = this.getProgress();
int maxProgress = this.getMax();
//calc the progress to angles
float angleProgress = progress * 360 / maxProgress;
//create and set the arc paint
Paint arcPaint = new Paint();
arcPaint.setColor(0xff800000);
arcPaint.setAntiAlias(true);
arcPaint.setStyle(Style.FILL);
Rect arcRect = new Rect(); this.getDrawingRect(arcRect);
canvas.drawArc(new RectF(arcRect), -90, angleProgress,true, arcPaint);
}
For ref check this image arc shape progressbar
The default ProgressBar widget is not easily customisable, even for significantly less ambitious changes than this. In my opinion, it offers you no valuable behaviours in this context, other than acting as a carrier for minimum, maximum and current values. It also brings with it unwanted functionality such as the 'indeterminate' state.
Create a custom view by extending View and implementing onDraw() - as you have - and onMeasure().