How to set a drawable to a TextView's text? - android

Short question:
Suppose I have a TextView, and I wish that the text itself (not the backround) will have a drawable set to it (and not just a solid color), how should I do it?
The only solution I've found is this one , but it's only for gradient colors, and I wish to be able to use any drawable.

Ok, I think I've found a possible solution, but I have some notes about it:
It's not for any drawable. It's for a bitmap, so you will need to somehow convert it to a bitmap.
It requires that you know the size of the textView (which you can use this for this purpose)
It requires that you have enough memory for the scaled bitmap that is in the same size of the textView.
Not sure how to make it work per character or per line.
Here's the code:
public static void setBitmapOnTextView(final TextView tv, final Bitmap bitmap) {
final TileMode tile_mode = TileMode.CLAMP;
final int height = tv.getHeight();
final int width = tv.getWidth();
final Bitmap temp = Bitmap.createScaledBitmap(bitmap, width, height, true);
final BitmapShader bitmapShader = new BitmapShader(temp, tile_mode, tile_mode);
tv.getPaint().setShader(bitmapShader);
}
I hope that there is a better solution for this.

edited:
I don't believe it's possible to change the actual stroke used on the text, the best closest option you probably have is to use a different font.
In android you can "draw" any text using any *.ttf font.
for that you must include the file in your assets folder and call from code (maybe there's a way using XML, but I don't know how) this:
TypeFace mFont = TypeFace.createFromAsset(mContext.getAssets(), "my_font.ttf");
mTextView.setTypeFace(mFont);
I reckon that is the closes you'll get to have a different stroke on the text.
original answer:
TextView have the following properties:
Drawable Top
Drawable Bottom
Drawable Left
Drawable Right
that you set on the XML. Or you can call
setCompoundDrawables(left, top, right, bottom)
from code!

Related

Should I use a LinearLayout with repeated background or a SVG ImageView to fill a whole row?

Linked questions
The below questions couldn't finally solve my problem, described below.
Android: Is it possible to repeat an (SVG!) drawable inside an ImageView?
Android: Keep ratio for a full-width and undefined height ImageView in a ConstraintLayout?
Showing a full-width ImageView containing a SVG distorts it
Context
I use a ConstraintLayout. My aim is to show an SVG image which contains a button:
Its width is 100% the screen's width - it must be repeated
Its height is defined to be the space between the bottom side of a widget and the bottom side of the button - it must be repeated
The problem
Each time I tried to show this image, either the drawable was badly scaled, badly cropped or blurred.
An exemple is:
It should look like this:
Many tests
I have tried to use an ImageView with the attribute src: I used every scale type, with and without the attribute that allows to set a custom ratio
I have tried to use an ImageView with a background instead of src
I have tried to use a RelativeLayout with a background drawable file that is repeated: so I didn't use an SVG image but its JPEG version, and even this way has resulted in bad results
Nota for 3.: I'd really want to use an SVG image instead of a bitmap one, because it will be resolutions-compliant.
My question
So, given all these explanations (cf.: part Context) and given the above illustrations, how would you proceed to show this image?
use java code
ColorDrawable colorDrawable = new ColorDrawable(Color.parseColor("#888888")); // bg color
Drawable vDrawable = AppCompatResources.getDrawable(this, R.drawable.ic_vector_star); // vector drawable
if (vDrawable != null) {
Bitmap bitmap = Bitmap.createBitmap(vDrawable.getIntrinsicWidth(), vDrawable.getIntrinsicHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
vDrawable.draw(canvas);
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), bitmap);
bitmapDrawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); // set repeat
LayerDrawable drawable = new LayerDrawable(new Drawable[]{colorDrawable, bitmapDrawable});
findViewById(R.id.frameLayout).setBackground(drawable);
}

Not able to set textview drawable dynamically

Im trying to create a textview dynamically . I want to set the drawable to textview`
TextView tab = new TextView(getContext());
tab.setText(title);
tab.setSingleLine();
tab.setGravity(Gravity.CENTER);
int padding = getResources().getDimensionPixelOffset(R.dimen.offset);
tab.setPadding(0,0,padding,0);
if(typeface!= null){
tab.setTypeface(typeface);
}
tab.setCompoundDrawables(getResources().getDrawable(R.drawable.ic_arrow_back_white_24dp),null,null,null);
`
But I'm not able to achieve it. Can anyone of you help me out.
use setCompoundDrawablesWithIntrinsicBounds
Sets the Drawables (if any) to appear to the left of, above, to the
right of, and below the text. Use null if you do not want a Drawable
there. The Drawables' bounds will be set to their intrinsic bounds.
setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.ic_arrow_back_white_24dp),null,null,null);
OR
setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.ic_arrow_back_white_24dp),0,0,0);
try this use setCompoundDrawablesWithIntrinsicBounds
>
void setCompoundDrawablesWithIntrinsicBounds (Drawable left,
Drawable top,
Drawable right,
Drawable bottom)
Sets the Drawables (if any) to appear to the left of, above, to the right of, and below the text. Use null if you do not want a Drawable there. The Drawables' bounds will be set to their intrinsic bounds.
Calling this method will overwrite any Drawables previously set using setCompoundDrawablesRelative(Drawable, Drawable, Drawable, Drawable) or related methods.
sample code
TextView textView = (TextView) findViewById(R.id.myTxtView);
textView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon, 0, 0, 0);

Create image of imageview having textview on it

HI'm having an imageview having EditText on that Image. I want to create single Image of that imageview with EditText.
I tryed this,
editTextOptOneInput.buildDrawingCache();
imageViewOptOne.setImageBitmap(editTextOptOneInput.getDrawingCache());
imageViewOptOne.buildDrawingCache();
Bitmap bitmap1 = imageViewOptOne.getDrawingCache();
but chamge my image to black as my text color is black(I guess).
You may use only 1 buildDrawingCache(), the subsequent ones will replace the previous contents.
So, you better group the EditText and the ImageView into a container and shoot that one.
OR...
Instead of using an EditText, just use a TextView.
This one can have one or more compound drawable inside.
So, you may shoot the TextView only.
This is a preferred solution, since it reduces the View and (possibly) the layout count.
[EDIT]
To use compound drawables simply use in xml the android:drawableLeft = "#drawable/your_drawable" (and/or drawableRight, drawableTop, drawableBottom) attribute/s of your TextView.
To set them in Java, use setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom), as found in the official docs: http://developer.android.com/reference/android/widget/TextView.html#setCompoundDrawablesWithIntrinsicBounds(int, int, int, int)
You need get drawing cache of Parent of that imageview & EditText.
parentLayout.buildDrawingCache();
Bitmap bitmap1 = parentLayout.getDrawingCache();
Where parentLayout contains imageview & EditText.
I don't understand why you need that but as I understand you should create new Bitmap object from drawing cache before set as source of ImageView
Reminder:
If you are capturing the result image+text from screen, the quality of the output image is certainly compromised
If you want to keep the original quality of image, you should use Canvas and Bitmap to help you
Canvas c=new Canvas();
c.setBitmap(bitmap); // *mutable* copy of bitmap of the image for the ImageView
c.drawText(text, x, y, paint); // font size and typeface can be set through "Paint" class
bitmap.compress(CompressFormat.PNG, 100, new FileOutputStream(out)); // export output

CircularImageView with a solid color

The CircularImageView, https://github.com/Pkmmte/CircularImageView, works great when setting an image bitmap like so...
circularImageView.setImageBitmap(bitmap);
However, there are times where I just want to set a solid color instead of a bitmap. If I do something like this,
circularImageView.setBackgroundResource(R.color.blue);
The color of the view is set but the image is never made circular, so it fill the entire rectangular view. I'm assuming the getDrawable() is returning null so it can't actually manipulate the view. Anyone ran into this problem or any suggestions on what to do?
Edit:
I can do this but it seems a bit flimsy:
Bitmap image = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
image.eraseColor(android.graphics.Color.GREEN);
circularImageView.setImageBitmap(image);
You should call circularImageView.setImageResource(R.color.blue) instead.
The code you wrote sets the background of the view, not the content image. Looking at the code on github, this view will only clip the content image to the circle--it has no effect on the background at all.
Give a try for ColorDrawable;
int decode = Integer.decode("FF6666");
ColorDrawable colorDrawable = new ColorDrawable(decode);

Android TextView getTextSize() does it include descenders, ascenders

I can't find anywhere there is a mention of how the getTextSize() in Textview is measured. From visual tests it doesn't seem to be including descenders, but seems to include ascenders. It doesn't appear to start exactly from the baseline also.
http://en.wikipedia.org/wiki/Descender
This is the closest mention of it but Romain Guy from Google just ignores that part of the question.
http://www.mail-archive.com/android-developers#googlegroups.com/msg08514.html
As I need this as I am using Compound Drawables and I need to be able to align the drawable to the text on different devices.
Here is code I used to test on a compound drawable a circle that touches edges
tvData.setTextSize(TypedValue.COMPLEX_UNIT_PX, 100);
tvData.setText("agB5ãÂ");
int size = (int)tvData.getTextSize();
Drawable img = getResources().getDrawable(R.drawable.circle_white_full_72 ).mutate();
img.setBounds( 0 , 0 , size , size);
tvData.setCompoundDrawables( null, null, img, null );
Here is the result
as you can see it doesn't seem to use the descenders and ascenders.
Here is the drawable image, if others want to test
http://i.imgur.com/Yhf8b.png
When changing the image to 80% of the text size using
int size = (int)tvData.getTextSize() *80/100;
Here is the result, with the image transposed on top of the 100% image. Maybe setCompoundrawables is doing it's own scaling
I tried measuring midpoints of the font and drawable and it is off. Here is an image highlighting it
Finally I moved the drawable 50pixels to the left, and then measured the output and it was half the height of the font text baseline to baseline, as the setTextSize was set at 100px.
Android must be using some other layout to scale and position the compound drawable. Maybe I should create another question for this.
Here is an image highlighting baseline to baseline.
From some light testing, it appears to be from ascent to descent (text size = descent - ascent). Did some debugging with a TextPaint to verify, and just to be a little more specific, I did:
Paint.FontMetricsInt metrics;
for(int i = 1; i < 100; i++) {
mTextPaint.setTextSize(i);
metrics = mTextPaint.getFontMetricsInt();
if((metrics.descent - metrics.ascent) != i) Log.v("type", "Not equal");
}
And it remained true for each value.

Categories

Resources