Reputation: 477
By following this question, I was able to have text around an image. However, I have the following problem.
As you can see, the space for the image on top is displayed in every paragraph at the right. In the question someone had this problem and suggested to change 'ss.length()' for 'lines'. This seemed to work except if the first paragraph was too short, the next paragraph would overlap the image.
I modified the FlowTextHelper class slightly to use text from Html. This is the code I'm using:
public class FlowTextHelper {
private static boolean mNewClassAvailable;
/* class initialization fails when this throws an exception */
static {
try {
Class.forName("android.text.style.LeadingMarginSpan$LeadingMarginSpan2");
mNewClassAvailable = true;
} catch (Exception ex) {
mNewClassAvailable = false;
}
}
public static void tryFlowText(String text, View thumbnailView, TextView messageView, Display display, int addPadding){
// There is nothing I can do for older versions, so just return
if(!mNewClassAvailable) return;
// Get height and width of the image and height of the text line
thumbnailView.measure(display.getWidth(), display.getHeight());
int height = thumbnailView.getMeasuredHeight();
int width = thumbnailView.getMeasuredWidth() + addPadding;
messageView.measure(width, height); //to allow getTotalPaddingTop
int padding = messageView.getTotalPaddingTop();
float textLineHeight = messageView.getPaint().getTextSize();
// Set the span according to the number of lines and width of the image
int lines = (int)Math.round((height - padding) / textLineHeight);
//SpannableString ss = new SpannableString(text);
//For an html text you can use this line:
if(!text.equals("")) {
SpannableStringBuilder ss = (SpannableStringBuilder) Html.fromHtml(text);
ss.setSpan(new MyLeadingMarginSpan2(lines, width), 0, ss.length(), 0);
messageView.setText(ss);
messageView.setMovementMethod(LinkMovementMethod.getInstance()); // links
// Align the text with the image by removing the rule that the text is to the right of the image
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) messageView.getLayoutParams();
int[] rules = params.getRules();
rules[RelativeLayout.RIGHT_OF] = 0;
}
}
}
public class MyLeadingMarginSpan2 implements LeadingMarginSpan.LeadingMarginSpan2 {
private int margin;
private int lines;
public MyLeadingMarginSpan2(int lines, int margin) {
this.margin = margin;
this.lines = lines;
}
@Override
public int getLeadingMargin(boolean first) {
return first ? margin : 0;
}
@Override
public int getLeadingMarginLineCount() {
return lines;
}
@Override
public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
int top, int baseline, int bottom, CharSequence text,
int start, int end, boolean first, Layout layout) {}
}
What is causing the space being repeated every paragraph and how can I get rid of it? Any help is appreciated.
Upvotes: 3
Views: 2206
Reputation: 66
I've spend hours to solve this issue, but solved it with thanks to the answer found here: text wrapping around image in android
Basically as follows:
First add a margin to your textview and set the text
final RelativeLayout.LayoutParams params = RelativeLayout.LayoutParams)messageView.getLayoutParams();
params.setMargins(marginWidth, 0, 0, 0);
messageView.setText(Html.fromHtml(text));
Then add an OnGlobalLayoutListener and in the onGlobalLayout() call you calculate how many lines actually need the margin. You split the lines in 2 separate spannables and add the Margin only to the first one:
messageView.getViewTreeObserver().addOnGlobalLayoutListener( new OnGlobalLayoutListener() {
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {
int linesCount = messageView.getLayout().getLineCount();
// restore the margin
params.setMargins(0, 0, 0, 0);
SpannableString spanS = new SpannableString ( Html.fromHtml(text) );
if (linesCount <= lines) {
spanS.setSpan(new MyLeadingMarginSpan2(lines, width), 0, spanS.length(), 0);
messageView.setText(spanS);
} else {
// find the breakpoint where to break the String.
int breakpoint = messageView.getLayout().getLineEnd(lines-1);
Spannable s1 = new SpannableStringBuilder(spanS, 0, breakpoint);
s1.setSpan(new MyLeadingMarginSpan2(lines, width), 0, s1.length(), 0);
Spannable s2 = new SpannableStringBuilder(System.getProperty("line.separator"));
Spannable s3 = new SpannableStringBuilder(spanS, breakpoint, spanS.length());
// It is needed to set a zero-margin span on for the text under the image to prevent the space on the right!
s3.setSpan(new MyLeadingMarginSpan2(0, 0), 0, s3.length(), 0);
messageView.setText(TextUtils.concat(s1, s2, s3));
}
// remove the GlobalLayoutListener
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
messageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
messageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
Upvotes: 5
Reputation: 477
If you need to wrap text around an image, use this library FlowTextView.
The library performs well, and it can be used with a couple lines. However, it does not support screen pixel size for fonts. I found a workaround with this answer, so that you can convert pixel size to sp.
I hope this helps anyone and you don't waste as much time as me using the question from my original post.
Upvotes: 0