Custom shaped textview, Android - android

I'm looking for a way of making custom shaped text input control on Android, like showed on screenshot.
What is need is to have some predefined places(gray rects) that will not be covered by text. So when user typing - text will lays out with some offsets from left side, or right side, depending on place of gray rect.
It is easy to do on iOS, just a couple lines of code and that is all. But I can not find a way of doing this on Android. Note that gray rects may not be a part of text input component. On iOS I simply put two UIImageView over the UITextView, and set up rects for excluding from rendering text:
CGFloat margin = 8;
CGRect firstPathRect = CGRectMake(0, 80, 160 + margin, 90 + margin);
CGRect secondPathRect = CGRectMake([UIScreen mainScreen].bounds.size.width - 160 - 2 * margin, 280, 160, 90 + margin);
UIBezierPath *path1 = [UIBezierPath bezierPathWithRect:firstPathRect];
UIBezierPath *path2 = [UIBezierPath bezierPathWithRect:secondPathRect];
self.textView.textContainer.exclusionPaths = #[path1, path2];
I hope somebody can help me with this task. Thanks in advance!

Check out this library for flowing text:
https://github.com/deano2390/FlowTextView

Related

How to draw a line to perfectly align top of a text?

I am able to align the baseline perfectly. The getLineBounds will give a baseline that is perfectly aligned with text (lineBottom - descent).
I am using rect.top as the topline which will give a line with padding on top see the screenshot.
The main issue is I have different fonts.And this code works perfectly on some fonts.
This is the code
int baseline = getLineBounds(i, rect);
int topLine = rect.top;
canvas.drawLine(rect.left - padding, baseline, rect.right + padding,
baseline, paint);
canvas.drawLine(rect.left - padding, topLine, rect.right + padding, topLine,
paint);
canvas.drawLine(rect.left - padding, (baseline + topLine) / 2, rect.right
+ padding, (baseline + topLine) / 2, paint1);
This is what I have tried.
1) Used a "StaticLayout" to get the top line but didn't make any difference.
2) Used paint to get the height of font and add it with baseline
paint.setTextSize(getTextSize());
paint.setTypeface(getCurrentTypFace());
paint.getTextBounds(getText().toString(), 0, getText().length(), r);
int height = r.height();
int topLine = baseline + height;
3) Tried with FontPadding =false android:includeFontPadding="false"
So my question is how to get the the topline like the baseline.
Any help with this is greatly appreciated.
Try paint.getTextBounds(...) again, but use r.top, (or actually -r.top) instead of r.height:
paint.setTextSize(getTextSize());
paint.setTypeface(getCurrentTypFace());
paint.getTextBounds(getText().toString(), 0, getText().length(), r);
int ascent = r.top;
int topLine = baseline + ascent;
r.height gives the distance from the very bottom of the character to the very top, whereas r.top should give the negative of the distance from the baseline to the very top.
If this doesn't work either, you might just need to draw the text to a temporary canvas in memory and run through the pixels row by row until you find a black one to measure the ascent yourself.
In either case, make sure you use a text that has capital letters in it. If you use a text with only lower case, it will likely give you the coordinates of the orange dashed line instead.
Note that both methods will give you the coordinate of a pixel at the very top edge of the font, not in the center of the stroke. Also, some letters in some fonts might overshoot the coordinate you really want to draw by quite a bit. Your safest bet is probably to pick a standard-string for measuring, like a capital O for the blue line and a lower-case o for the orange line (if it's not a script-font that has a little squiggle in the top right corner of the O that goes above the top of the circle...) and then store some small offset for each font that tells you how thick the line-width of the stroke is, so your lines go through the top of the letter rather than above it.

How to draw circle with alpha gradient on canvas?

How to draw on canvas like this pic with alpha gradient?
Please specify next time whether you mean the android app canvas or HTML5 canvas on android browsers. If its the former, use android-canvas. This solution is in JS since its easier to show, and will work fine on either platform.
Gradients along paths in canvas are hard. The easiest way is to fudge it.
Instead of thinking of your image as a gradient that follows a circular path, think of it as two linear gradients.
One on the left side, going from green to gray, top to bottom.
The other on the right side, going from white to gray, top to bottom.
Imagine a square made of those two gradients:
Now imagine a circle cutting through:
That's all you gotta do.
To "cut" through like that its easiest to use clipping regions, so I've made an example doing that.
Here's the live example: http://jsfiddle.net/simonsarris/Msdkv/
Code below:
var greenPart = ctx.createLinearGradient(0,0,0,100);
greenPart.addColorStop(0, 'palegreen');
greenPart.addColorStop(1, 'lightgray');
var whitePart = ctx.createLinearGradient(0,0,0,100);
whitePart.addColorStop(0, 'white');
whitePart.addColorStop(1, 'lightgray');
var width = 20;
ctx.lineWidth = width;
// First we make a clipping region for the left half
ctx.save();
ctx.beginPath();
ctx.rect(-width, -width, 50+width, 100 + width*2);
ctx.clip();
// Then we draw the left half
ctx.strokeStyle = greenPart;
ctx.beginPath();
ctx.arc(50,50,50,0,Math.PI*2, false);
ctx.stroke();
ctx.restore(); // restore clipping region to default
// Then we make a clipping region for the right half
ctx.save();
ctx.beginPath();
ctx.rect(50, -width, 50+width, 100 + width*2);
ctx.clip();
// Then we draw the right half
ctx.strokeStyle = whitePart;
ctx.beginPath();
ctx.arc(50,50,50,0,Math.PI*2, false);
ctx.stroke();
ctx.restore(); // restore clipping region to default

How to make the simplest <div>-like transparent container/layer in AndEngine?

I would simply like to have an Entity, Rectangle or something that would serve as a plain container for other Sprites.
Positioning purposes is what I need it for... I need to be able to set this container's width and position.
I have tried with Rectangle, but it seems to hide absolutely everything behind it (with a lower Z-index).
you can change the alpha of the Rectangle to "see" what's underneath it. Something like
myRect = new Rectangle(x, (CAMERA_HEIGHT - 480 + 100) / 2, size, size, vboManager);
myRect.setAlpha(0);
scene.attachChild(myRect);

Android Monospace fonts aren't fixed width

I'm writing a custom View for a timer, but I can't get a properly fixed-width font for the numbers in the middle. Here's the relevant code (from two different methods):
mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTypeface(Typeface.create(Typeface.MONOSPACE, Typeface.NORMAL));
// Get rectangle that is the size of the text
mTextPaint.getTextBounds(
getTimeText(),
0,
getTimeText().length(),
mTextBounds);
// X and Y coordinates of text
float mTextPosX = (width / 2) - (mTextBounds.width() / 2);
float mTextPosY = (height / 2) + (mTextBounds.height() / 2);
// Draw text
canvas.drawText(
getTimeText(),
mTextPosX,
mTextPosY,
mTextPaint);
This seems to work fine, but whenever one of the numbers changes to a 1, that 1 takes up less space and the whole chunk of text moves over a bit. This obviously should not be happening, since I'm using a monospace font. Can anyone shed some light on how I might fix this?
I had the same problem. A way to fix it is by using an external font in which "1" behaves as expected. A website with many fonts to try is this one: http://www.fontcubes.com/ . A related discussion on how to use external fonts in Android is here: How to change fontFamily of TextView in Android .

How can I really center my text horizontally?

I have a Piano app with some round labels on it with the note names.
These note names need to be completely centered on the label.
I finally figured out how to do that vertically using ascent and descent. However, I am still not getting the horizontal alignment perfectly ok.
It is mainly about the rendering of single characters. Whatever I do, some of the characters are off. It's slightly, but it's there.
Notice how the E is slightly off to the right for example, and the B a bit to the left.
I am rendering the labels in onDraw(), not with custom views. I also tried with a TextView the size of the labels and using Gravity.CENTER, but this gave the same results. Also note that I tried Align.Center too.
Code:
usedPaint.setTextAlign(Align.LEFT); //Also tried it with Center
Rect textBounds = new Rect();
usedPaint.getTextBounds(infoText, 0, infoText.length(), textBounds);
float textWidth = usedPaint.measureText(infoText);
canvas.drawText(infoText, circleX - (0.5F * textWidth), circleY - ((usedPaint.descent() + usedPaint.ascent())/2),
usedPaint);
canvas.drawRect((circleX - (0.5F* textWidth)), circleY - (0.5F * textBounds.height()), circleX + (0.5F * textWidth), circleY + (0.5F * textBounds.height()), otherPaint);
The drawn box's width is the result of measureText. At the E character you see that somehow it measures some whitespace on the left, making the character drift off to the right.
This is using the standard font on Android 4.0.3. Using a custom TTF font results in the same kind of issues, but different for each character.
I am wondering what else I can do? (Besides getting over it ;) )
with center align just change canvas.drawText(infoText,
circleX - (0.5F * textWidth), ... to canvas.drawText(infoText,
circleX, ...

Categories

Resources