I have a simple layout contains just one TextView.
I wanna load an image into TextView using ImageSpan.
Below method creates Spannable:
private Spannable getImageSpannable(int drawableId, int targetWidth, int targetHeight) {
Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), drawableId);
Bitmap bitmap = Bitmap.createScaledBitmap(originalBitmap, targetWidth, targetHeight, true);
Drawable dr = new BitmapDrawable(getResources(), bitmap);
dr.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
Spannable imageSpannable = new SpannableString("\uFFFC");
ImageSpan imgSpan = new ImageSpan(dr, DynamicDrawableSpan.ALIGN_BOTTOM);
imageSpannable.setSpan(imgSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return imageSpannable;
}
I use this method to create content like this:
public void setContent() {
SpannableStringBuilder content = new SpannableStringBuilder();
content.append(getImageSpannable(R.drawable.my_image, 100, 260));
content.append("\n");
txtContent.setText(content);
}
When I call setContent() method my result is something like this:
As you see there is small gap between ImageSpan and top of TextView.
This is not line spacing, because I set line spacing to 0.
And interesting point is when I remove "\n" from content(declared in setContent method) this space is gone.
And another point is that when I tried to measure content size using StaticLayout, with "\n" at the end bottom of line 0 it returns 270 and without "\n" it returns 260.
This behavior causes some difficulties for me, because I have to measure text and ImageSpan using StaticLayout and decide witch one can fit into TextView.
I appreciate everyone can help me.
Thanks.
Here's my xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/txtContent"
android:layout_width="300dp"
android:layout_height="500dp"
android:background="#fed9f4"
android:textSize="22sp"/>
</LinearLayout>
I'v done some tests and I find that font size is affects ImageSpan rendering.
Can somebody explain this affect please?
I hope this method works
The following line of code
public void setContent() {
SpannableStringBuilder content = new SpannableStringBuilder();
content.append(getImageSpannable(R.drawable.my_image, 100, 260));
content.append("\n");
txtContent.setText(content);
}
Change to
public void setContent() {
SpannableStringBuilder content = new SpannableStringBuilder();
content.append(getImageSpannable(R.drawable.my_image, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
content.append("\n");
txtContent.setText(content);
}
And resize "R.drawable.my_image" dimensions
Related
I am trying to add multiple smiles in textview using this code.
This is my TextView.
<TextView
android:id="#+id/textViewId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:bufferType="spannable" />
And this is add smiley function.
public void addSmily() {
int resource = R.drawable.smily ;
Spannable spannable = Spannable.Factory.getInstance().newSpannable(" ");
Drawable d = ContextCompat.getDrawable(this, resource);
d.setBounds(0, 0, 40, 40);
ImageSpan smilySpan = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
spannable.setSpan(smilySpan, spannable.length()-1, spannable.length(), 0);
sendText.append(spannable);
}
Smiles are adding perfectly but the problem is when I add lots of smiles did not fit in a single line then the first line of smiles become invisible and they start from the 2nd line.
This is what happening. Plz, someone help me.
Solution:
Try this inside your button:
SpannableString ss = new SpannableString("abc");
Drawable d = ContextCompat.getDrawable(your_activity.this, R.drawable.your_smiley_drawable);
d.setBounds(0, 0, 40, 40);
ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
ss.setSpan(span, 0, 3, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
edittext.append(ss);
Note: Also, EditText's inputtype must be textMultiline.
Try it, Works in my lap, Let's Hope it helps to you too.
You can also set smiley by unicode in textview.
how set emoji by unicode in a textview?
int unicode = 0x1F60A;
Which can be used with
public String getEmojiByUnicode(int unicode){
return new String(Character.toChars(unicode));
}
So Textview displays 😊 without Drawable
Try it with http://apps.timwhitlock.info/emoji/tables/unicode
Hope it may help you.
The design called for just icon on the tab of the PagerTabStrip.
Here's the XML:
<android.support.v4.view.PagerTabStrip
android:id="#+id/tbstrp_album"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foregroundGravity="bottom"
android:padding="0dp"
android:background="#color/offWhite">
Here's my getPageTitle inside the adapter:
#Override
public CharSequence getPageTitle(int position) {
// This is "generic" string that we will use as the title to be replaced.
String title = "title";
Drawable myDrawable = oContext.getDrawable(R.drawable.alpha);
// initiate the SpannableString builder
SpannableStringBuilder spanBuilder = new SpannableStringBuilder(title); // space added before text for convenience
// set the drawable's size...if it could be too big or too small for display
myDrawable.setBounds(0, 0, 50, 50);
// turn the Drawable into ImageSpan and align it along the baseline
ImageSpan imageSpan = new ImageSpan(myDrawable, ImageSpan.ALIGN_BASELINE);
// CRUCIAL: this is where we replace the "title" w/ the image
// 0: we start from the beginning
// title.length(): we are replacing the entire string
// the last flag doesn't do anything in our case
spanBuilder.setSpan(imageSpan, 0, title.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return spanBuilder;
}
The output looks like this:
What's causing the strip clipping the image? Thanks!
It turns out this statement is the culprit:
myDrawable.setBounds(0, 0, 50, 50);
I changed the second argument which is the "top" to 30 and the icon was not clipped.
The unanswered question is still...why do I have to specify a value for the "top" argument.
Here is my code to put an ImageSpan in an EditText.
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
EditText et = (EditText) getActivity().findViewById(R.id.html_text);
SpannableString ss = new SpannableString("ABC");
Drawable d = getResources().getDrawable(R.drawable.ic_launcher);
d.setBounds(0,0,2256,760);
ImageSpan span = new ImageSpan(d, "haha", ImageSpan.ALIGN_BASELINE);
ss.setSpan(span, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
et.setText(ss);
}
While playing around, I noticed something strange. My AVD is 2560x1600. When the setBounds call with width less or equal to 2256, the picture is showing correctly. But for width larger than 2256, the picture is shown twice.! The magic value is the same for different pictures. I also tried AVD with different size. For 720x1080, the magic width is 608. What is this magic width? How can I make sure my picture doesn't exceed this magic width?
BTW, here is the layout for the EditText:
<EditText
android:id="#+id/html_text"
android:layout_width="match_parent"
android:layout_height="match_parent" />
this worked for me
int width;
int height;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_matn_activity3);
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth(); // deprecated
height = display.getHeight(); // deprecated
SpannableString ss = new SpannableString("ABC");
Drawable d = getResources().getDrawable(R.drawable.ic_launcher);
double ratio= (double)((double)(d.getIntrinsicWidth())/(double)(d.getIntrinsicHeight()));
//this shows the original ratio of image
if(d.getIntrinsicWidth()<width){
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
Log.v("small","small");
}else{
Log.v("big","big");
d.setBounds(0, 0,(int)(width*.95),(int)(d.getIntrinsicHeight()/ratio*.95));
//i dont know why but if you put 1 instead of .95 again you will see 2 images
//this is exactly the magic width you have said
}
}
it may have little problems because my project is big and different i cant put the exact code
.but it generally works
Currently, I wish to add an image in between texts and align it to the top of the TextView.
Something like this:
The only vertical alignments I can find are baseline (which seems to put it right down the center of the text) and align bottom.
What happens if I use ALIGN_BASELINE is:
Is there a way to align it to the top instead?
My current code:
txtView.setText(this.addImageAsterisk(
"The string to have asterisk at the end*"), BufferType.SPANNABLE);
then
private CharSequence addImageAsterisk(String string) {
Drawable d = context.getResources().getDrawable(R.drawable.img_asterisk);
ImageSpan imageSpan = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
final SpannableString spannableString = new SpannableString(string);
spannableString.setSpan(imageSpan, string.length()-1, string.length(), 0);
return spannableString;
}
removing ImageSpan.ALIGN_BASELINE sets it to align to the bottom which is also not my expected result.
--- Thank you user Lalit Poptani, I tried applying your answer----
after applying this, what happens is that the whole textview seems to have extra margin top.
before applying span:
This is the text*
after applying the SuperscriptSpanAdjuster
(some extra space)
This is the text*
My code:
String string = "This is the text*";
Drawable d = this.context.getResources().getDrawable(R.drawable.img_asterisk);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
ImageSpan imageSpan = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
SuperscriptSpanAdjuster s = new SuperscriptSpanAdjuster(1.5);
final SpannableString spannableString = new SpannableString(string);
spannableString.setSpan(s, string.length() - 1, string.length(), 0);
spannableString.setSpan(imageSpan, string.length(), string.length() + 1, 0);
textView.setText(spannableString);
What you can do is use a custom MetricAffectingSpan for maintaining its ratio like,
public class SuperscriptSpanAdjuster extends MetricAffectingSpan {
double ratio = 0.5;
public SuperscriptSpanAdjuster(double ratio) {
this.ratio = ratio;
}
#Override
public void updateDrawState(TextPaint paint) {
paint.baselineShift += (int) (paint.ascent() * ratio);
}
#Override
public void updateMeasureState(TextPaint paint) {
paint.baselineShift += (int) (paint.ascent() * ratio);
}
}
And the you can use SpannableString to apply asterisk to your String like,
SpannableString mString = new SpannableString("This is what I wanted*");
mString.setSpan(new SuperscriptSpanAdjuster(0.5), mString.length() - 1,
mString.length(), SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
mTextView.append("\n");
mTextView.append(mString);
This is append asterisk to your text as you required. And your output will be as,
Just wrap your drawable in inset drawable and set inset bottom to some value like 8dp. Not the best solution, but will work.
Modify your drawable/img_asterisk.xml --
<inset
xmlns:android="http://schemas.android.com/apk/res/android"
android:insetBottom="8dp">
<!-- Your previous asterisk drawable, probably a 'shape' -->
</inset>
I have an ExpandableListView and in the ViewGroup method i have an image span set to some textview like this:
String statusText = postsList.get(groupPosition).get(TAG_userStatus).substring(urlStr.length(), postsList.get(groupPosition).get(TAG_userStatus).length());
Bitmap bm = BitmapFactory.decodeFile(urlStr);//urlStr is the path to my image: /mnt/sdcard/1.jpg
Bitmap resized = Bitmap.createScaledBitmap(bm, 200, 200, true);
TextView userStatus1 = (TextView)v.findViewById( R.id.userStatus );
SpannableStringBuilder ssb = new SpannableStringBuilder(" "+statusText );
ImageSpan span = new ImageSpan(resized, ImageSpan.ALIGN_BOTTOM);
ssb.setSpan( span, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
userStatus1.setText( ssb, BufferType.SPANNABLE );
I need to be able to click on the image and show it in full screen.But I don't know how to make the image clickable. I have read similar threads but nothing works for me. I think it's because expandableListView but I'm not sure. I hope you can help me. Thank you!