Friends,
I have 3 text views in a LinearLayout which has a bounded width of 300dp. Each text view has a layout_weight of 1 so the screen will be divided evenly among the three TextViews.
[text view 1][text view 2][text view 3]
Most of the time the text fits in one line in each of the TextView but there are some occasion when it does not. Is there any way I could determine that the Text will need two lines and set the number of lines parameter of the TextView to 2?
If one of the TextViews needs 2 lines than all three TextViews should be set to two lines
The short answer is yes- TextView has a getLineCount() method that will tell you how many lines of text are the TextView.
Unfortunately there's a caveat- the TextView must be layed out and measured before this method works properly.
If you are setting the text dynamically (e.g. via setText()), then you will need to create a callback for when the layout pass happens like so:
mTextView1.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (mTextView1.getLineCount() > 1) { // or textView2, etc.
// Adjust all text view heights
}
}
});
Related
I have two TextViews next to each other inside ConstraintLayout. Each of them has two words.
The words inside of them can be changed by the current locale.
Currently each of them takes equally space on the width by using android:layout_weight="1" and android:layout_width="0dp"
If the text in any of them is too long to fit one line, I want both of them to expand to two lines. I need the text itself to be expanded, not the TextView - that can be done only if the text has at least two words.
Is there a way to do that?
You will need for layout to proceed then determine if the left TextView has two lines and, if it does, adjust the right TextView to also occupy two lines. The following code is one way to do this. You can place this in onCreate().
val layout = findViewById<ConstraintLayout>(R.id.layout)
layout.doOnNextLayout {
val textView1 = findViewById<TextView>(R.id.textView1) // Left view
val textView2 = findViewById<TextView>(R.id.textView2) // Right view
if (textView1.lineCount == 2) { // If left view has 2 lines, add newline to the right view.
textView2.text = textView2.text.toString().replace(" ", "\n")
}
}
I have a layout that looks like this:
<RelativeLayout>
<!--aligned parent top-->
</<RelativeLayout>
<FlowLayout>
<!--Should fill remaining space-->
</FlowLayout>
<RelativeLayout>
<!--aligned parent bottom-->
</<RelativeLayout>
I used FlowLayout to show a list of textviews(It may contain 10-15 textviews). So, based on available empty screen space, I want to show number of textviews. For example, if there are 15 textviews to be shown there and there is space for 10 textviews in a large screen, I want to show 9 textviews and show "+6" in the last textview. In a small screen space may be available only for 5 textviews, in that i want to show 4 textviews with "+11" in the last textview. For clear understanding, here is the screenshot. As you can see, actual number of textviews to be displayed are 5. but 2 are displayed, and +3 is added. Similarly, based on screen space available, I want to add number of textviews in the layout.
How can this be achieved programmatically?
Try programmatically adding TextViews to a linearLayout in a for loop in which after adding each textView, get remaining width available (Can be calculated using [ScreenWidth-(sum of added textviews width + [no.of textviews * margin/padding for each])]*)
If width is less than a certain minimum (say you need 100px minimum for each textview) then break the loop and add the count indicator text.
I can think of below code, it might not be precise but just to show you what Im thinking of
int screenWidth = getScreenWidth();
int currentWidth=0;
int minimumWidthForAChildWithOffset = 100;//offset should include width of indicator
int childCount = 10;
int paddingForEachChild = 15;
for (int i = 0; i <childCount; i++) {
TextView label= getChildView();
parent.addView(label, i);
currentWidth += parent.getChildAt(i).getWidth() + paddingForEachChild;
if(i!=childCount-1/*ignore if this is the last item*/ && screenWidth-currentWidth<=minimumWidthForAChildWithOffset){
//add indicator label to layout here
break;
}
}
Try adding the textviews in a loop, adding each one separately in a new OnPreDrawListener. After each one is added, check if it exceeds the space on the row, and if so remove it and add the counter. If it still exceeds the row, remove one more and increase the counter.
The key is to test each in a separate OnPreDrawListener, so it all happens before the view is shown, but after the view has had its layout and size calculated.
If I had to implement something like you described, I would try to fork/subclass FlowLayout and update its onMeasure and onLayout methods.
Here's the FlowLayout: https://github.com/blazsolar/FlowLayout/blob/develop/FlowLayout/src/main/java/com/wefika/flowlayout/FlowLayout.java
1) First step is to limit height of FlowLayout in onMeasure. Also, It might be enough to do something like this:
<LinearLayout android:orientation="vertical" ... >
<RelativeLayout ... />
<FlowLayout android:layout_height="0dp" android:layout_weight="1" ... />
<RelativeLayout ... />
</LinearLayout>
2) Second step is to update onLayout, so it stops adding lines and line views when max height is reached, then add your view which displays number of hidden views
I want to create textview programmatically and display horizontally if it fits on device screen else display in next row.
I have the screen's available width and some text. Based on that text I want to create textview and display it. I also have additional text which i want to display in first row if it fits there. Otherwise, it should go on the next row. The only problem is that I am not able to get the width of textview based on its text. I can't use wrap_content as it will not give me its width value.
In the activity that includes your textview, implement this interface;
global::Android.Views.ViewTreeObserver.IOnGlobalLayoutListener
This will make you implement OnGlobalLayout method.
You will also need to add;
rootLayout = FindViewById<RelativeLayout>(Resource.Id.rootLayout);
rootLayout.ViewTreeObserver.AddOnGlobalLayoutListener(this);
Root layout here can be your root layout that includes your text views.
On the method you implemented,
public void OnGlobalLayout()
{
if (textView != null)
{
int height = textView .Height;
}
}
if you call textView.Height or textView.Width, it will return the true width and height of your textview after the view is created, instead of the wrap content -1 value.
So I have two TextViews in a RelativeLayout in my xml file. When they are localized to different languages, there will be a chance that the two views will overlap with each other.
In this case I want to put them into two lines instead of just one line. How to detect the overlap and reset their position so on is on top of the other in java code?
I did this with a LinearLayout and by using the textview's auto wrap feature Iwas able to detect if the textview wrapped. By using a ViewTreeObserver and looking at the number of lines for the textview I then programmatically set the view to Gone.
final TextView text = findViewById(R.id.textview1);
text.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int lineCount = text.getLineCount();
Log.d(this, "LineCount = " + lineCount);
if (lineCount > 1) {
text.setVisibility(View.GONE);
}
getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
Just have to make sure your layouts don't ellipsize or that you set the singleLine or Maxlines to true or 1. I set Max line on the one textview I want gone to 2 so that it will wrap if it won't fit.
Just put your layout in a language spefic layout folder.
Your standard layout in res/layout
another in res/layout-ar (example for arabic)
I have a simple problem but could not solve it with clean solution .
Suppose there are two textviews horizontally next to each other. I want to make them such that
second textview come just right to first and first should grow as much as it can without putting second textview out of screen (means second textview should always be visible).
Hint:you could always use Relative layout and try scaling them in the Graphical layout.
One solution would be, putting the two textViews in a LinearLayout and assign each textView a weight attribute. The LinearLayout divides the space between those views accordingly to the weight. For example if the first textview has weight 3 and the second has weight 2, the width for the first textview would be 3/5 superviews width and the second would be 2/5.
Another solution would be to put the second textView with a fixed width aligned right to the parent RelativeLayout, and the first view to be leftof the second view with the width 'match_parent'