Horizontally and vertically scrollable layout in react native - android

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?

Related

How to set multiple scroll views size to change dynamically relative to each other?

I have two scroll views in a vertical linear layout.
I want them to be relative to each other so that they fill the entire linear layout and compensate if one cant cover half the screen.
Lets call that scroll views TOP and BOT.
If the screen can display 4 rows and both scroll views have infinite rows, each scroll views should display 2 rows and be able to scroll down to se the rest rows.
If TOP has 1 and BOT infinite rows, BOT should be resized to 3/4 of the linear layout.
If TOP have infinite and Bot has 1 row TOP should still just display 2, i.e. it should never pass the linear layouts vertical center.
Here are some pictures for reference:
my setup with weight set to 0.5/0.5.
result of 0.5/0.5 weight. Notice the gray bar above the BOT title bar. This empty space should be filled by the BOT bar.
if Using fixed size or wrap content the TOP will push the Bot out of view.
How can I have them hugging each other and still set TOP to a maximal height?
Preferable in XML.
Its better to set the weight dynamically. Count the number of items in both views. Set the weight of each view according to the ratios of their number of items. You can refer set weight dynamically for setting weights at run time

Android-Move view from column 1 to column 2 if column 1 overflows

I have a number of custom views that can expand on a click event and they push down views below them.
This may result in some views completely or partially out of screen. I want to detect these occurrences and move them to column two of the screen.
Both columns take half of the screen size.
I do not want to use Listview or anything scroll-able, just move views from column 1 to column 2 and back if space is free.
EDIT: I am trying to override each views onDraw, so it can check if bottom coordinates is below screen y coordinates and then reparent them to a pre-defined Layout. But so far no success.
EDIT2: I managed to detect if a view is out of screen space.
For future reference: i have overriden the dispatchDraw of my custom view class, where i calculated its bottom position and the screen height with: context.getresources().getdisplaymetrics().heightpixels;

android GridLayout divider row

I'm trying to implement a tabular layout that has a header and a bunch of rows underneath it. I've chosen the GridLayout (android.support.v7.widget.GridLayout) as there's some requirements for some elements to span multiple columns (but those are of no concern to the question).
My header cells each contain a LinearLayout with a bunch of TextViews, they're dynamically filled in code,for the sake of example, have a look at the image below.
The second row should contain the divider which is a simple view, that should span my header columns (3).
The problem is the width of the divider - if I choose MATCH_PARENT, it will push the GridLayout to fill the whole remaining space to the right. The grid needs to wrap the content and center itself horizontally. It seems to me there's a conflict between the grid's layout (WRAP_CONTENT) and the divider's layout (MATCH_PARENT).
How can I fix the width of the divider without hardcoding it?
http://i61.tinypic.com/2415eg5.png
In red, my LinearLayouts (header), green, the GridLayout itself, the thin blue line at the bottom is the divider.
Thanks,
MO
SOLUTION (as provided below):
I had to set the column weight for the divider to 1, without specifying a width (actually setting it to zero). Because of my specific requirement to handle all of these in code, the solution was to manually instantiate the GridLayout.LayoutParams class and use
ColumnSpec = GridLayout.InvokeSpec(row_index, num_spanned_cols, weight)
Hope this helps others in the future.
If you set the width to 0dp then give it android:layout_weight="1"
(you could give it any weight you want) it should fill all the available space and not push your bounds if I understand what you are asking correctly

Android - GridLayout cell sizes

I am trying to use GridLayout with ImageViews. My problem is that the images I have are all different sizes. I have set the row count and column count, but somehow I need to set a fixed cell size (somehow uniform - as in cell width = total / num of columns, and cell height = total / num of rows). I want to do this so that when I set height and width of imageview to match_parent, the image view doesn't expand beyond the cell size and the layout looks uniform.
I need 5 rows and 3 columns. Can someone suggest how to do this ?
I answered a similar question here. The theory is to use a wrapper layout for your cell and provide the margins that it needs to it. Then use the imageview inside this layout. Thus the outer layout acts as a container for your imageview and it will never go out of the bound of its parent.

How to resize the rows so that they always fill the full height of the parent?

I have a parent LinearLayout with a fixed size. At onCreate() I load data and add rows to the parent layout dynamically. Anywhere from 1-10 rows are loaded. I want the rows to always fill the parent, for example if I have 2 rows each row should have 50% height of the parent (50% + 50% = 100%). If I have 3 rows each row should use 33% of the parent height etc.
I tried to use an OnGlobalLayoutListener to get the height of the parent and resize the rows dynamically, unfortunately when I run the app the resizing is arbitrary at best. Sometimes the rows get resized, sometimes they get resized after a noticeable delay of about 0.5 seconds.
Is there a better way to achieve this? Maybe already in the XML as for example with layout_weight (given that the rows only get added in code)?
You can do this by setting the weight sum on the parent LinearLayout to the number of rows you have inside of it. If this is a vertical list of items you would then set the height of each row to 0 and set its weight to 1. If this is a horizontal list of items you do the same but set the width to 0 and set the weight to 1.

Categories

Resources