Draw text on ImageView doesn't work - android

I have extended class from ImageView and want some text to be drawn on it. This doesn't work, do you know why? Thank you.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int imgWidth = getMeasuredWidth();
int imgHeight = getMeasuredHeight();
float txtWidth = mTextPaint.measureText("your text");
int x = Math.round(imgWidth/2 - txtWidth/2);
int y = imgHeight/2 - 6; // 6 is half of the text size
canvas.drawText("your text", x, y, mTextPaint);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
mTextPaint = new Paint();
mTextPaint.setColor(android.R.color.black);
mTextPaint.setTextSize(12);
mTextPaint.setTextAlign(Paint.Align.LEFT);}

I ran your code, and immediately got a Lint error. In init() you are setting your mTextPaint to android.R.color.black. Because it's a static value, I could immediately see that the actual int value of that variable is 0x0106000c, which is almost completely transparent. You should use getResources().getColor(android.R.color.black) or plain ol' Color.BLACK.
Note that a textSize of 12 is very, very small. This code shows 12 (albeit very small).
public class MyImageView extends ImageView {
public MyImageView(Context context, AttributeSet attributeSet, int defStyle) {
super(context, attributeSet, defStyle);
init();
}
public MyImageView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
init();
}
public MyImageView(Context context) {
super(context);
init();
}
Paint mTextPaint;
private void init() {
mTextPaint = new Paint();
mTextPaint.setColor(Color.BLACK);
mTextPaint.setTextSize(12);
mTextPaint.setTextAlign(Paint.Align.LEFT);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int imgWidth = getMeasuredWidth();
int imgHeight = getMeasuredHeight();
float txtWidth = mTextPaint.measureText("your text");
int x = Math.round(imgWidth/2 - txtWidth/2);
int y = imgHeight/2 - 6;
canvas.drawText("12", x, y, mTextPaint);
}
}
xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.mytest.MyImageView
android:layout_width="100dp"
android:layout_height="100dp"/>
</RelativeLayout>
Copy/paste, if problem persist, start logging. Again, this code works, I see 12 on my screen.

You should be able to accomplish the desire effect without creating your own class. Just set the background of a TextView with an image drawable. See my example with a text in a speech bubble.
<TextView
android:id="#+id/textOverImage"
android:background="#drawable/speech_bubble"
android:text="#string/hello_world"
android:gravity="center"
android:layout_width="..."
android:layout_height="..."
/>

Related

How to use android canvas to draw a striped rectangle?

rectangles
I already drew the left rounded rectangle. I need to insert some lines horizontally for it to become a striped rectangle. How can I achieve this?
I already tried to use path and draw a line. But nothing worked how it was supposed to. Can someone help me?
Here's a sample code for drawing a striped rectangle in Android Canvas:
public class StripeRectView extends View {
private Paint mPaint;
private int mStripeWidth = 10;
private int mStripeHeight = 10;
public StripeRectView(Context context) {
super(context);
init();
}
public StripeRectView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public StripeRectView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.FILL);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int x = 0;
int y = 0;
while (y <= getHeight()) {
canvas.drawRect(x, y, x + mStripeWidth, y + mStripeHeight, mPaint);
x += mStripeWidth * 2;
if (x > getWidth()) {
x = 0;
y += mStripeHeight * 2;
}
}
}
}
the Canvas is used to draw rectangles, with alternating stripes of width mStripeWidth and height mStripeHeight until the entire height of the View is filled. You can modify it according to your needs.

Android clipPath not working

I am trying to clip paths in my imageview. But nothing is happening.
My ImageView
public static class CliptImageView extends ImageView {
Path path = new Path();
public CliptImageView(Context context) {
super(context);
}
public CliptImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CliptImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
path.reset();
float y = getMeasuredHeight() / 2.0f;
float x = getMeasuredWidth() / 2.0f;
path.addCircle(x,y, 20,Path.Direction.CW);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
canvas.clipPath(path, Region.Op.DIFFERENCE);
super.onDraw(canvas);
canvas.restore();
}
}
I add the imageview programatically to a linearLayout like this
private View getMiddleArea() {
CliptImageView imageView = new CliptImageView(getContext());
LinearLayout.LayoutParams params =
new LinearLayout.LayoutParams(
0, ViewGroup.LayoutParams.MATCH_PARENT, 2);
imageView.setLayoutParams(params);
imageView.setBackgroundColor(ContextCompat.getColor(getContext(),R.color.white));
// imageView.setBackgroundResource(R.drawable.bottom_bar_semicircle);
// imageView.getBackground().setLevel(5000);
return imageView;
}
Nothing happens. The view is kept white. So i am obviously doing something wrong. But i have no idea what. I have had a lot of trial and error the latest 2 days. But nothing seems to work.
So any help that would get me in the right path is appreciated
Edit update
This is what i am trying to achieve. a transparent circle that clips the view and makes everything transparent

onDraw on View extends ImageButton not work

I'm trying to draw a custom text on an ImageButton. I have overwritten the method onDraw(Canvas) but it didn't work. This is the code:
public class CustomImageButton extends ImageButton {
private static final String TAG = "CustomImageButton";
private String text = "";
private float textSize;
private int textColor;
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
public CustomImageButton(Context context) {
super(context);
initialize(null);
}
public CustomImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(attrs);
}
public CustomImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(attrs);
}
private void initialize(AttributeSet attrs) {
if (attrs != null) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CustomImageButton);
text = a.getString(R.styleable.CustomImageButton_text);
textSize = a.getDimension(R.styleable.CustomImageButton_textSize, 20);
textColor = a.getColor(R.styleable.CustomImageButton_textColor, getResources().getColor(R.color.white));
//setBackgroundColor(getResources().getColor(R.color.transparent));
a.recycle();
invalidate();
}
}
#Override
protected void onDraw(Canvas canvas) {
Typeface font = Typefaces.get(getContext(), "fonts/my-font.ttf");
paint.setColor(Color.WHITE);
paint.setTypeface(font);
paint.setTextSize(100);
paint.setTextAlign(Paint.Align.CENTER);
int xPos = canvas.getWidth() / 2;
int yPos = (int) ((canvas.getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2));
canvas.drawText(text, xPos, yPos, paint);
}
}
And XML Layout:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#OOOOOO"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.my.app.CustomImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:text="Hello!"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"/>
. . .
</RelativeLayout>
I used setWillNotDraw(false) but it seems that does not work. I have verified that my custom view has a few correct dimensions.

Custom View disappears when aligned within a RelativeLayout

I have a custom view that simply draws a circle onto a canvas (so far).
Using it within a RelativeLayout is fine until I tell it specifically where to be aligned within the RelativeLayout.
i.e. as soon as I add something like: android:layout_centerInParent="true"
it will no longer appear.
The following is the relevant code:
public class CircleProgressBar extends ProgressBar {
int radius;
float centerX;
float centerY;
Paint progressPaint;
public CircleProgressBar(Context context) {
super(context);
init(context);
}
public CircleProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CircleProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context) {
progressPaint = new Paint();
progressPaint.setColor(ContextCompat.getColor(context, R.color.colorAccent));
}
private void init(Context context, AttributeSet attributeSet) {
progressPaint = new Paint();
progressPaint.setColor(ContextCompat.getColor(context, R.color.colorAccent));
}
#Override
protected synchronized void onDraw(Canvas canvas) {
radius = Math.max(getMeasuredWidth(), getWidth()) / 2;
centerX = getLeft() + radius;
centerY = getTop() + radius;
canvas.drawCircle(centerX, centerY, radius, progressPaint);
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.tomtaila.circleprogressbar.CircleProgressBar
android:layout_centerInParent="true"
android:layout_width="100dp"
android:layout_height="100dp"/>
</RelativeLayout>
Try like this. This will fix your problem
Remove "android:layout_centerInParent="true"" from "CircleProgressBar" and
set "android:gravity="center"" to the "activity_main" RelativeLayout
OR
#Override
protected synchronized void onDraw(Canvas canvas) {
radius = Math.max(getMeasuredWidth(), getWidth()) / 2;
centerX = radius;
centerY = radius;
canvas.drawCircle(centerX, centerY, radius, progressPaint);
}
While CircleProgressBar tag without centerInParent attribute, Its position is Top left (0,0). So in "onDraw" method you are using getLeft() return 0 and getTop() return 0.
But While CircleProgressBar tag with centerInParent attribute, Its position is center of the parent (parent_width/2,parent_height/2). So In "onDraw" method getLeft() will return parent_width/2() (if parent width is 480, then it will return 240) and simmilarlly getTop() will return parent_height/2. Now centerX, centerY values become too big.

EditText's onDraw canvas gets shifted to the left when single line is set

I have a very simple customized EditText like this:
public class MyEditText extends EditText {
private Paint mPaint;
public MyEditText(Context context) {
super(context);
init();
}
public MyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setSingleLine();
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(6);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int y = canvas.getHeight() * 6 / 7;
canvas.drawLine(0, y, canvas.getWidth(), y, mPaint);
}
}
As I set single line mode on, when text is short everything is fine, it would look like this:
But once the text gets longer (more than width of the EditText), the red line is shifted to the left like this:
As you'll probably notice I used 0 and canvas.getWidth() to connect both sides of the view, but the line gets shifted, so doesn't it mean the whole canvas gets shifted as well?
If so it's such a strange behavior that I didn't expect from a View descendant. Can someone shed me some light on this strange behavior?
Thanks
Change your onDraw() method like below...
#Override
protected void onDraw(Canvas canvas) {
Rect r = new Rect();
int baseline = getLineBounds(0, r);
int y = canvas.getHeight() * 6 / 7;
canvas.drawLine(r.left, y, r.right, y, mPaint);
super.onDraw(canvas);
}

Categories

Resources