Add a TextView inside a Custom View that herited View - android

I would like to know if it is possible to add a textview programmatically in a custom view that herites from View. In this customView, I draw some shapes with a canvas and I need to put some text too. I tried to use drawText but it doesn't offer enough possiblities, especially for the position of the text. Basically, i want to put text inside, and precisely in the middle of a circle and at the same time that my text fits right in the circle (I already know how to do that).
That's why I'm wondering if it is possible to add a textview by just declaring it and draw it. Maybe I need to use an Inflater ?
I don't really know what are the best choices so I need your help :)

You can use drawText(String text, float x, float y, Paint paint) method for this.
Like this :
Paint mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawText("YOUR TEXT HERE", 10, 20, mPaint);

Instead of extending View you should extend a ViewGroup subclass like
FrameLayout.
This way you can still use the canvas to draw your custom view, but also add children views to your custom drawn viewgroup.

Related

Clip content of ActivityView

i am implementing a custom launcher in Android, displaying 3rd party apps using ActivityViews.
I want to clip the content of these ActivityViews to a custom shape (other than Circle, Rectangle, RoundedRectangle, Ring...).
I already tried to call clipPath/drawPath on the dispatchDraw canvas of a parent viewgroup element which works fine for all children except the ActivityView. Even the ActivityView itself and its referenced SurfaceView seem to be clipped according to my given path (if i add a solid color for testing). But the rendered content remains unchanged. Manipulating the SurfaceView canvas (which you receive by calling getHolder().lockCanvas()) doesnt have any effect, too.
I think this has something to do with the virtualdisplay and/or various SurfaceControls which are used by the ActivityView, but i dont have any clue how to set clipping areas/paths for those classes.
Does anyone have an idea how to solve this?
Hint: i cannot paint over the ActivityViews content as i want to display the system wallpaper in the transparent areas.
finally setting up the PorterDuffXfermode correctly solved the issue. Just overwrite the dispatchDraw method of the parent viewgroup and erase the required areas using PorterDuff.
Sometimes it looks like the direction does matter how the path for drawPath is created (CW or CCW). So maybe try both.
Unfortunately this approach does not work if the hosted activity uses a SurfaceView on its own.
protected void dispatchDraw(Canvas canvas) {
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(getContext().getColor(android.R.color.white));
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
int save = canvas.save();
super.dispatchDraw(canvas);
canvas.drawPath(path, p);
canvas.restoreToCount(save);
}

Reference to drawn text using drawText() on a canvas

I have a canvas on which I have drawn some text using drawText(), is it possible to get a reference to that text? I want to select that text using the onLongPress() gesture and I think I need to have the reference of that text to do that.
You won't be having refrence to what you drawn using drawText() on canvas.To implement select text you have to use Paint.measureText() to get height and width of your text and then draw the backgound to make a custom effect of text selection(handle long press using onTouch()).
When drawing text on canvas you have to handle every behaviours of text view as your own.
An alternate way is to to Create a TextView and add it to any layout and then use the following code to draw the layout into canvas
//measure the width and height of the layout(covers entire canvas)
vLayout.measure(canvas.getWidth(), canvas.getHeight());
//set the bounds of the layout.
vLayout.layout(0, 0, canvas.getWidth(), canvas.getHeight());
vLayout.draw(canvas);

Centering text(String) in a surface view

How do you horizontally center a String in a surface view?
I don't want
c.drawText(""+score, c.getWidth()/2, y);
Because this will display text starting at the center of the screen.
I want something like
c.drawText(""+score, c.getWidth()/2-score.length()/2*fontSize, y);
Is there an equation to solve this problem? If not, are there any other ways to center text in a surface view?
BTW I'm using a custom font, I don't know if that changes anything or not. If you need to know any extra information about the font please comment.
You don't have to calculate manually. You just need to specify some extra parameters in your Paint object:
Paint paint = new Paint();
paint.setColor(textColor);
paint.setTextSize(28);
paint.setTypeface(typeface);
paint.setTextAlign(Align.CENTER);
The key is that you need to specify Align.CENTER, in this way you can just call:
canvas.drawText("CENTERED TEXT", canvas.getWidth()/2, posY, paint);

Android drawText() in defined rectangular region

I'm currently using the following method to draw some text to the SurfaceView:
canvas.drawText("someText", 0, 0, paint);
Yet what if the text exceeds the width of the screen? Is it possible to define a region wherein the text can be drawn?
So now when the string's width exceeds the rectangles width, the text will be formatted to fit underneath the above text and so on eg.
"sometext"
"text carried"
"on"
Based on this answer, I believe this is what the Layout subclasses are used for. Per documentation:
A base class that manages text layout in visual elements on the
screen.
For text that will be edited, use a DynamicLayout, which will be
updated as the text changes. For text that will not change, use a
StaticLayout.
And with each subclass there's a note:
This is used by widgets to control text layout. You should not need to use this class directly unless you are implementing your own widget or custom display object, or would be tempted to call Canvas.drawText() directly.
Which sounds exactly like what you're doing.
It's basically a replacement for canvas.drawText(). It can be used in this fashion:
TextPaint tPaint = new TextPaint(paint);
StaticLayout sLayout = new StaticLayout(sText, tPaint, mWidth, widthToFill, Layout.Alignment.ALIGN_CENTER, 1.2f, 1.0f, false);
canvas.save();
canvas.translate(posX, posY);
sLayout.draw(canvas);
canvas.restore();

Draw text on canvas and make it visible on screen

This code was supposed to convert text to image
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
paint.setTextSize(16);
paint.setAntiAlias(true);
paint.setTypeface(Typeface.MONOSPACE);
Bitmap bm = Bitmap.createBitmap(16, 16, Bitmap.Config.ALPHA_8);
float x = bm.getWidth();
float y = bm.getHeight();
Canvas c = new Canvas(bm);
c.drawText("Test", x, y, paint);
}
Is this code ok? If yes, how can I make this new bitmap visible on screen? I tried this code which produced an error
setContentView(c); //<- ERROR!
I am confused with the element Canvas as there is not such element in XML which I can use in the code.
setContentView(View) takes a View and Canvas is not a View.
I am not sure that you want to create a Canvas on your own. There are ways to get a Canvas passed to you from the Android Framework though. One way you can do this is by creating a custom View. To do this, you will need to create a new class that extends View.
When overriding a View class, you will have the ability to override the onDraw(Canvas) method. This is probably where you want to do what you are attempting to do in your onCreate() method in the code you posted.
This link gives a good overview of what is required to create your own custom view.
First: If you draw your text at the x and y position you specified, you draw it
at the lower right corner, starting with exactly that pixel. Nothing will be drawn on your canvas. Try bm.getWidth()/2, for height the same for test drawing. You can optimize that later.
Second: Canvas is not a View (does not extend the View class). You can only set Views via set ContentView(). What I recommend here is writing a XML layout containing only a single ImageView and set that via setContentView(R.layout.mylayout).
After that, you can use findViewById() to grab that ImageView and use ImageView.setImageBitmap(bm) to show your bitmap on it.
You dont have to do anything with the canvas, once you created it with your bitmap. Everything you draw inside the canvas from that point on is found in the Bitmap immediately.
Therefore you can't specify the Canvas in XML. It's just an "Editor" to edit pictures, so to speak and not an actual UI element.

Categories

Resources