wrap a layout with textviews - android

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

Related

Adding views dynamically to LinearLayout not working as expected

I'm inflating views inside a linearlayout dynamically, however once the linear layout reaches the end of the first row, it cuts off the rest and doesn't start on the second row.
for(int a = 0; a < mSkills.get(i).size(); a++){
View singleSkill = LayoutInflater.from(mContext)
.inflate(R.layout.singleskill, holder.mSkillLayout, false);
TextView skillText = singleSkill.findViewById(R.id.singleskilltext);
skillText.setText(mSkills.get(i).get(a));
holder.mSkillLayout.addView(skillText);
}
For the linear layout I have it set to wrap_content for the height:
<LinearLayout
android:id="#+id/ll_skills"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_below="#+id/tv_description"
android:layout_margin="16dp"/>
I've tried setting it to a defined height e.g 300dp however that doesn't work either.
How can I make the layout start on the second row, once the first is full?
Linear Layout can either fill views horizontally or vertically so the 2nd row you are expecting cant to be done with linear layout only. you can try a horizontal scroll view for that to scroll horizontally. For the exact view-like flow that you described, you can use this 3rd party https://github.com/nex3z/FlowLayout
It can manage the flow of your dynamically inflated view such as if there is no space in the first line then it will put the next view in the second line.
also, you can use material design library chips https://material.io/components/chips/#usage
LinearLayout works exactly how it has to be because you specify it as horizontal. For such behavior, you need RecyclerView With GridLayoutManager or create your own layout;).
Actually it's doing exactly as it should be, LinearLayout is Linear!, and place its subviews in a single horizontal or vertical row.
My advice to you is that create dynamic horizontal LinearLayout as you already doing with TextViews. and put every 3 or 4 textviews (depending on screen size) inside it.
and put all LinearLayouts inside one vertical LinearLayout...
Of course in your case, it's not a good idea, the best thing you can do is to use recycler view. but I consider you have problem with that.

How to center RecyclerView in the center (and without scrolling) when possible?

This is a short question:
Suppose I have a RecyclerView that has undefined number of items, what should I do to it, so that if there is a small number of items that (all) can fit the screen, they will be centered and the user won't be able to scroll ?
Of course, if there are too many items, that cannot fit the screen, I would like to have the RecyclerView to show them all as normal (from the beginning to how much it can show, and allow to scroll).
To understand what I mean, I think such a thing is possible when using ScrollView (or HorizontalScrollView if in horizontal), together with a LinearLayout that sets the gravity to be centered .
OK, I think I've found a way:
first, we wait for the RecyclerView to finish its layout process, as I've found about here .
Then, you need to check which child views are shown (available in the LayoutManager that you use), and look at the first and last ones.
If both of them are exactly the same as those that of the total items, it means all needed views are shown, so I can add margins on both sides of the RecyclerView (or padding on its container), according to the space that's left.
I found one complicate way to achieve that.
Main concept: set the height of RV dynamicly in code
RecyclerView rv= (RecyclerView) findViewById(R.id.rv);
rv.setAdapter(new MySlideUpAdapter());
rv.setLayoutManager(new LinearLayoutManager(this));
ViewGroup.LayoutParams layoutParams = rv.getLayoutParams();
layoutParams.height=100;
rv.setLayoutParams(layoutParams);
You may need to calculate the RV's height by childcount*childheight to get pricise value. And don't forget to compare the height to the Parent Layout height, make sure RV's height is less than its Parent Layout height.
Here is my Layout
<RelativeLayout...>
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_centerInParent="true"
android:layout_width="match_parent"
<-height will be changed in code, ignore the 50dp->
android:layout_height="50dp">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>

Make First line height in textview the same as other lines

I have a recyclerview with bunch of textview each as an item as you see in picture below. (Blue lines aren't really there, i added them so you can see each item separately) as you can see everything seems nice and user will not notice the text is separated.
The problem is when user increases the line space(a typical option in app) line height gets bigger except the first and last line of each item and the result seems like second picture.
My question is how to find appropriate padding to set to each item so every line height seen exactly the same?
BTW i can not use just one textview for many reason!
You can increase the divider height of your listview according to linespacing height.
Or you can set an invisible view at the bottom of every row item and increase the height of this view according to linespacing height.
Or you can set padding at the bottom of every row item and increase the value of this padding according to linespacing height.
just add some padding to the parent of your textview in the layout file of your list item .
for example the layout with linearlayout would be like :
<LinearLayout ........
paddingTop=15dp>
<TextView
..........>
</TextView>
</LinearLayout>
and you could adjust the padding dynamically if you want.

Number of lines text needs at compile time

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

Dynamically adjust the height of group headers in an ExpandableListView

I have an ExpandableListView (ELV) with the groups having LinearLayout. I have set the height of the group to some value (38dip in this case, equivalent to two lines of text). If the group heading is long and would take more than 2 lines, it is not shown properly in the ELV item - some part of the view gets scrolled. On the other hand, if I change android:layout_height to "wrap_content" in the LinearLayout, the groups always show all the lines. But the line widths are variable, i.e., short titles show up with only 1 line and long titles show up with 2, 3 or 4 lines. That looks ugly. I would like to implement the height to be something like max("38dip", "wrap_content"). Is there a way to do this?
Even programmatically, I do not seem to be getting the actual height of the group if I set android:layout_height to "wrap_content". Any suggestions there?
Could not solve the problem directly. Added the following to the xml layout file of the group:
android:paddingTop="7dip"
android:paddingBottom="7dip"
That makes the layout looking much less congested which is what I wanted to do in the first place. Moving on - but would be interested if someone else have a better solution.

Categories

Resources