TextView with too long Strings - android

I have this layout
<ScrollView>
<TextView android:id="#+id/textView" />
</ScrollView>
When I try to set a too long text, this Textview doesn't show that.
//OnCreate
//...
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText("..."); //Here is a text with more than 2500
//chars and at least have 10 \n char
//(it means has at least 10 paragraph)
How can do I show that text?
Edit One :
Even I set a background to that TextView and the TextView does'nt show that background

you can set
android:maxLines="1"
android:ellipsize="end"
to your textview, so the text which long than your textview will be hide.

Because android:singleLine="true" attribute has been deprecated, set the following attributes to your TextView:
android:ellipsize="end"
android:maxLines="1"
The TextView will then show only the text that can fit to your TextView, followed by an ellipsis ...

i dont know if this will help you but saw this on developer.android...
With Android 8.0 (API level 26) and higher, you can instruct a TextView to let the text size expand or contract automatically to fill its layout based on the TextView's characteristics and boundaries. This setting makes it easier to optimize the text size on different screens with dynamic content.
android:autoSizeTextType="uniform"
There are three ways you can set up the autosizing of TextView:
Default
Granularity
Preset Sizes
=================================================
readMore

Use this :
EditText thumbnailView = (EditText) findViewById(R.id.enterBearingNo_editText_id);
TextView messageView = (TextView) findViewById(R.id.string2);
String text = "LargeText";
Display display = getWindowManager().getDefaultDisplay();
FlowTextHelper.tryFlowText(text, thumbnailView, messageView, display);
FlowTextHelper.class
class FlowTextHelper {
static boolean mNewClassAvailable;
static {
if (Integer.valueOf(Build.VERSION.SDK) >= 8) { // Froyo 2.2, API level 8
mNewClassAvailable = true;
}
// Also you can use this trick if you don't know the exact version:
/*
* 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) {
// 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();
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 / textLineHeight);
// For an html text you can use this line: SpannableStringBuilder ss =
// (SpannableStringBuilder)Html.fromHtml(text);
SpannableString ss = new SpannableString(text);
ss.setSpan(new MyLeadingMarginSpan2(lines, width), 0, ss.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
messageView.setText(ss);
// 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 static void tryFlowTextPrice(String text, TextView messageView,
Display display) {
// 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();
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 / textLineHeight);
// For an html text you can use this line: SpannableStringBuilder ss =
// (SpannableStringBuilder)Html.fromHtml(text);
SpannableString ss = new SpannableString(text);
// ss.setSpan(new MyLeadingMarginSpan2(lines, width), 0, ss.length(),
// Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
messageView.setText(ss);
// Align the text with the image by removing the rule that the text is
// to the right of the image
// LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)
// messageView
// .getLayoutParams();
// int[] rules = params.getRules();
// rules[RelativeLayout.RIGHT_OF] = 0;
}
}

Related

Extract text lines as displayed in textview

Is it possible to get each line of a multiline text as it will appear in a textview of a fixed width, with a font, size, alignment without actually drawing the textview ?
My Text is stored in a string. I can apply different font, size, alignment for the text. When passing it to my api, I want to split it into a list of Strings just how it was displayed in the app. Is this possible ?
In the view the text is formatted using the following:
TextView textView = new TextView(getContext());
LayoutParams textLayoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
if (itemWidth > 0) {
textLayoutParams.width = itemWidth;
}
if (itemHeight == -1) {
textLayoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
}
textLayoutParams.leftMargin = xPosition;
textLayoutParams.topMargin = yPosition;
textView.setLayoutParams(textLayoutParams);
textView.setPaintFlags(Paint.ANTI_ALIAS_FLAG);
font = getFontName(font);
if (!StringUtils.isEmpty(font)) {
CalligraphyUtils.applyFontToTextView(getContext(), textView, CalligraphyConfig.get(), "fonts/" + font);
}
if (!StringUtils.isEmpty(color))
textView.setTextColor(Color.parseColor(color));
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, (int)size );
if (alignment.equalsIgnoreCase("center")) {
textView.setGravity(Gravity.CENTER);
} else if (alignment.equalsIgnoreCase("left")) {
textView.setGravity(Gravity.START);
} else if (alignment.equalsIgnoreCase("right")) {
textView.setGravity(Gravity.END);
} else if (alignment.equalsIgnoreCase("left_center")) {
textView.setGravity(Gravity.START | Gravity.CENTER);
}
addView(textView);
For multi line strings, it will display on different lines. In a background process, I want to know which substring was displayed on 1st line, which substring was displayed on second line and so on. Is this even possible ?

Derive layout param width from textView text length

I want to set the width of a textView programmatically. I want the width to vary with the length of the text (value) of the textView. The text of the textView must not wrap. If the text of a textView is "OLA OMO ALARE", how can I use the length of this string (13) to derive the correct value to set lp.width to, in the code below ?
LayoutParams lp = tv.getLayoutParams();
lp.width =
tv.setLayoutParams(lp);
I tried the code below, but the width was not long enough, thus text was auto wrapped in textView.
lp.width = Math.round( tv.getPaint().measureText(tv.getText().toString())) )
Thanks.
1) You have to use Rect instance for this.
2) Then you need to use this in textView's getPaint() and getTextBound() methods which allows you to put your text of the textview.
3) At the end just get width from the Rect instance.
Code is here with all the steps implemented,
I tested this and it works fine. Hope it helps.
TextView textView = new TextView(this);
textView.setText("AALAP");
Rect rect = new Rect();
textView.getPaint().getTextBounds(textView.getText().toString(), 0, textView.getText().length(), rect);
Log.d(TAG, "onCreate: width: "+rect.width());
Use the ViewGroup.LayoutParams.WRAP_CONTENT constant for this.
ViewGroup.LayoutParams params = myTextView.getLayoutParams();
params.width = ViewGroup.LayoutParams.WRAP_CONTENT;
myTextView.setLayoutParams(params);

Android text around image bug

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.
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);
}
}
});
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.

How to find the Text Area(Height/Width) of TextView programmatically in android

I have an EditText, a Button and a TextView. On clicking the button, textview shows the text written in edittext. Is it possible to find the size of textview occupied depending upon text. i.e. If It has three characters "abc", what is width now, if it has 5 characters like "abcde" , then what is the width ?
Rect bounds = new Rect();
Paint textPaint = textView.getPaint();
textPaint.getTextBounds(text,0,text.length(),bounds);
int height = bounds.height();
int width = bounds.width();
or
textView.setText("bla");
textView.measure(0, 0);
textView.getMeasuredWidth();
textView.getMeasuredHeight();
Please try this:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView edit = (TextView) findViewById(R.id.edit);
edit.setTextSize(20);
edit.setText("Hello, world");
edit.measure(0, 0);
int width = edit.getMeasuredWidth();
Log.w("width", width.toString());
}
Before you get width, you have to measure the view / label / text edit.
Please let me know if this is not working.
TextView txt = new TextView(mContext);
txt.setText("Some Text)";
int height = txt.getLineCount() * txt.getLineHeight();
int width = txt.getWidth();
Try this way,hope this will help you to solve your problem.
yourTextView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int width = yourTextView.getMeasuredWidth();
int height = yourTextView.getMeasuredHeight();
}
});
please tell me width in??? do you want ?
TextView method getWidth() gives you width of your view, in pixels
TextView textView = (TextView)findViewById(R.id.textview);
textView.getWidth(); //width of your view, in pixels

Programmatically fill LinearLayout with a single line of TextViews

I'm trying to display a bunch of text on the screen by placing TextViews inside rows of single-line LinearLayouts. Each word is stored in its own separate TextView, and I want to be able to place as many TextViews as will fit on a single LinearLayout line and detect when I've run out of horizontal space so that I can move to the next line.
The problem I'm facing is that I can't seem to find a way to measure the changing layout sizes as I create the display, because I can't get a reference width using getWidth() on the parent layout, and even after I add the TextViews, I can't seem to control the width.
We had a working version before, but it did everything using on hard-coded numbers based on the number of characters in a TextView at a fixed size. I'm trying to extend the app to work with all text and screen sizes. If this needs to be completely overhauled, I understand - I just want to be able to fill up the screen with an indefinite number of lines of text.
An obvious solution would be to just place all the text inside one TextView, but we need to be able to access each Word/Ponctuation object and its attributes through the displayed TextViews.
// layout_row is the current LinearLayout row I'm adding my TextViews to
// layout is the LinearLayout parent of all layout_rows
// text.text_content is a linked list of Word and Ponctuation objects
// each Word and Ponctuation object has a TextView attribute called view
private void display_views() {
if (text != null)
{
boolean prochainLigneSuivante; // if new line is to follow
int widthSoFar = 0;
int layoutWidth = layout_row.getWidth();
for (Object o : text.text_content) {
if (o instanceof Word ) {
Word w = (Word) o;
Object next = text.next(o);
if (noNeedForSpace(w)) {
// by default all TextViews have
// right padding to simulate spaces
w.view.setPadding(0, 0, 0, 0);
}
layout_row.addView(w.view);
widthSoFar += w.view.getWidth();
// Am I out of space?
prochainLigneSuivante = widthSoFar >= layoutWidth;
if(prochainLigneSuivante) {
layout_row.removeView(w.view);
widthSoFar = 0;
layout_row = new LinearLayout(context);
layout_row.setOrientation(LinearLayout.HORIZONTAL);
layout_row.addView(w.view);
layout_row.setBackgroundColor(Color.BLACK);
layout_row.setLayoutParams(new
LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.MATCH_PARENT));
layout.addView(layout_row);
}
}
else if (o instanceof Ponctuation) {
Ponctuation p = (Ponctuation) o;
if (p.text.contains("CR")) {
layout_row = new LinearLayout(context);
layout_row.setOrientation(LinearLayout.HORIZONTAL);
layout_row.setLayoutParams(new
LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.MATCH_PARENT));
widthSoFar = 0;
layout.addView(layout_row);
}
else {
if (p.view.getText().equals(" "))
p.view.setPadding(0, 0, 0, 0);
layout_row.addView(p.view);
if(!p.view.getText().equals(""))
widthSoFar += p.view.getWidth();
}
}
}
}
else {
Log.e("Text", "text est nul");
}
scroll.refreshDrawableState();
transition.startTransition(0);
}

Categories

Resources