I came up with this very annoying layout issue.
Basically the UI component I'm looking for is not that complex, but the behavior needs to be exact.
In all cases I have 2 or 3 texts I need to layout horizontally.
In best case scenario all of these 3 fit in one line, so layout is not a problem.
| text 1 < empty space> | text 2 | < empty space> text 3 |
But when I hit an issue that text1 needs more than 1 lines, I should set that column 0 stretchable for TableLayout at the same time text2 might also need more than 1 lines so that column also needs to be stretchable and I would need the result to be like this:
| text1 many lines taking 40% | text2 takes 20% | text 3 many lines takes 40% |
And when this issue comes I haven't found a way to set TableLayout shrink and stretch columns. And also problem is that TableRow can contain 2 or 3 children.
I did few hour testing playing with LinearLayout and onGlobalLayout I calculated how much which is taking and adjusted weights of those views, but that's very complex and not working always, width on view3 sometimes just returned zero when view1 was very long.
I'm looking for some tips where to start here, should I do layouts in xml and inflate them instead programmically making them etc.
Okay I found out the solution, column 0 shrinkable, column 1 stretchable and tablerow span 2 for tablerow child number 2 if only 2 childs.
Related
I am trying to configure table grid layout in react native which could be scrollable horizontally and vertically.
By table grid layout I mean the layout similar to html table/tr/td: all views in the same row should have the same height and all views in the same column should have the same width.
The height of the row should be selected based on the height of the biggest view in the row.
The width of the column should be selected based on the width of the biggest view in the column.
I've started with horizontal scrolling.
This is what I've done:
https://snack.expo.io/#grekonstudio/01_initial
While it looks fine for me in the browser, on my device in looks this way:
The biggest column takes as much space as it needs and the rest of the space is shared between other columns. But it is done for each row independently, so columns border floats. Ideally, I want Row 1, Col 1 and Row 2, Col 1 to be the same size as Row 3, Col 1. That does not work as they and in different rows.
Well, obvious idea is to switch to column base layout, right:
https://snack.expo.io/#grekonstudio/04_column_based
Again, in the browser, it looks different. On the device it looks this way:
On the first look, this is exactly what I want! But apparently, it just moves the problem to another dimenstion. Let's make one View higher than the others, add a vertical ScrollView and we are losing row layout now:
https://snack.expo.io/#grekonstudio/05_same_problem
You can see the bigger cell takes all space and the rows are not having the same size anymore :(
Additionally, I tried two more things:
setting the flex: 1 to Scroll's view contentContainerStyle.
https://snack.expo.io/#grekonstudio/02_flex_1
In this case, it does not scroll at all.
Getting device height and width and fixing the size of the scroll view contentContainerStyle
https://snack.expo.io/#grekonstudio/03_fixed_width
In this case 'flex: 1' works as it works without a scroll view: splitting it to equal size boxes, while I want rows and cols to be adjusted by content
Another disadvantage is hardcoding width: 2 * screenWigth as e.g. for small content I might not need 2 screen width, I might need 1.5 or 1.2 only. It would also not work in portrait easlity.
I've also tried using the DataTable component https://callstack.github.io/react-native-paper/data-table.html, but when added to horizontal scroll view it fails to keep table layout the same way as in my first image: cells in the same column have different width.
Does anyone have a solution for the above?
I would like to have a background on my app that changes color depending on a given number. Let me elaborate some more. For example, I pass the number 40 out of 100, 2/5s of the screen should be x color, and the other 3/5s should be the other color. Here are two little diagrams:
40 / 100 40/60
+---+ +---+
| | 3/5 not filled in | | 1/3 not filled in
| | |...| 2/3 filled in
| | |...|
|...| 2/5 filled in +---+
|...|
+---+
So I was thinking I could go about making a dynamic background (giving a certain number) by drawing in the shapes. The problem is, I am not exactly sure how I would go about doing this. Where do I place the code to draw the shapes, and how exactly would I insert them into my XML file in the correct place (I already have a static color background that is up in my XML)?
Ok, you need to create an activity with two Linear Layouts. The width attribute will be set to match_parent and the height to 0dp. You will then be able to set the height with a layout weight of X %.
As an example, those layouts split the screen 25% 75% :
<LinearLayout
layout_weight="1"/>
<LinearLayout
layout_weight="3"/>
Give them an id to change values programmatically (weight and background color).
You can do it this way :
LinearLayout top = findViewById(R.id.top);
//Third Param stands for weight
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, 0, 1.0f);
top.setLayoutParams(param);
top.setBackgroundColor(Color.BLUE);
Consider 4 TextViews inside a horizontal layout each of which has Layout width of 0 and Layout weight of 1. What is the difference when they all have Layout width of 0.25 instead? It seems the output is the same:
Linear layout says, give every textview a(0.25 weight) 25% space (considering 100% available space). since there are 4 textview , so 100% would be divided among 4 as 25% ratio. Now linear layout gives each textview 25% space, textview weight 1 i.e 100% says, fill all the available space that is given to you by linear layout.
Okay so it is fairly simple to understand.
layout_width=0dp and layout_weight=1 means that you want all the views to take equal space horizontally.
whereas
layout_width=0dp and layout_weight=0.25 means that you want all the views to take 1/4 times the space of the total width of the parent.
This value becomes equal in case you have 4 views to be placed and not always.
There is no difference.
The spacing (layout_width) is calculated as a percentage of the total. In other words, if each TextView has a layout_weight of 1 then the total is 4 but each TextView gets 1 out of 4 (i.e., a quarter).
When using 0.25 the total is 1 but 0.25 is a quarter of 1 so, again, each TextView gets a quarter of the space.
I have this custom HorizontalScrollView that dynamically builds the following layout
<HorizontalScrollView width=match_parent>
<LinearLayout width=match_parent horizontal>
// here TextViews are dinamycally added
</LinearLayout>
</HorizontalScrollView>
so whenever I need to update the TextViews, what is actually done is removeAllViews() in the LinearLayout and they are re-created and re-added.
The TextViews have a padding of a some DP and setLines(1);. When adding them to the LinearLayout, they're being added with LinearLayout.LayoutParams(0, WRAP_CONTENT, 1f) (zero width, but weight=1).
The objective here is that if the TextViews are smaller than the screen width they will expand to fit the screen and if they're bigger than the screen width they will be padding + text lenght + padding and scroll horizontally in the screen.
It almost works except in some edge cases. Examples:
Works: I have 5 TextViews with a couple of short/medium words on each. All layouts nicely and you can scroll through them
Works: I have 2 TextViews with a couple of short/medium words on each. The TextViews expands to fill the screen and the text is centered on them.
Fail: I have 3 TextViews with the following texts: 1 lorem | 43 consectetur | 20 dolor the layout will simply match the screen width and the word "consectetur" will disappear (trying to go to the next line). Similar fails for different size words or numbers.
I tried requestLayout, invalidate, setVisibility(GONE);setVisibility(VISIBLE) updateViewLayout, setFillViewport(true); and trick out the layout weight of the TextViews based on the text lenght. All with no luck.
Does anyone knows how I could make this work without having to re-write the onMeasure of the LinearLayout (which I checked it's a total of 381 lines for the Horizontal version)
I have a UI Design from my designer, and it exists of a background map with several buttons on it, positioned non-linear all over the map. Currently I position them in a RelativeLayout that is as large as the map, and use margin-left and margin-top etc in dip.
This works ok, but I also need to account for users with very small screens, that cause the map to scale down. My relative layout scales with it, but the margin values ofcourse not.
So I am wondering, how should I do this? I would prefer to layout these buttons using percentages like
left="30%"
top="50%"
Is there anything in Android that makes such a thing possible? Otherwise I have to come up with a custom layout class for that.
Visual Representation: (Ofcourse they don't actually are on 6 lines, and partially overlap in x or y position). It's actually a real (abstract) map of a building with location markers that you can press as buttons.
-------------------------
| x x |
| x |
| |
| x |
| x |
| x x|
-------------------------
Here is a complicated way that does not require a custom ViewGroup. Suppose you want a button at left 30%, top 40%
FrameLayout
View with background, match parent
LinearLayout orientation=horizontal, match parent
View layout_width=0dp, layout_weight=30, height=match_parent
LinearLayout orientation=vertical, width=0dp, weight=70, hieght=match
View layout_height=0dp, layout_weight=40, width=match_parent
FrameLayout layout_height=0dp, layout_weight=60
Button
I use Dimension resource files put in the relevant layout- buckets so I can change margins/paddings/sizes depending on device size.
(http://developer.android.com/guide/topics/resources/more-resources.html#Dimension)
(Storing dimensions in xml file in Android)