I'm starting with JavaFX on a new application and I want to get a layout on screen identical to WPF's UniformGrid. There's TilePane but it's different (similar to WrapPanel I guess).
My approach so far would be (for a collection [size = N] I want to display as "tiles"):
Use a TilePane t.
t.setPrefRows( ROUNDUP( sqrt(N)))
That's probably not the best approach.
Do you know a better solution? Maybe a resizable one?
It sounds like you want a layout which:
Has a fixed number of cell nodes in each row.
Each cell node has the same height and width.
I'm not familiar with WPF or UniformGrid, but I think the above is what you want.
TilePane likely isn't a Good Fit
It seems like TilePane would be a good fit for this, but, as you found out, it doesn't really exhibit this behaviour out of the box. With a TilePane, you set a preferred number of rows, but as you resize the TilePane the number of rows and the number of columns can change as the tiles are rearranged to fit the available area.
Use a GridPane with Binding and Preference Settings or Constraints
To get a fixed number of cells per row, use a GridPane. A GridPane will keep a fixed number of rows and columns as it resizes. To ensure that each cell node has the same height and width, you can listen to the height and width properties of the GridPane and, on change, set the min/max/preferred sizes of the child elements so that they all have the same size. Or set some constraints on the GridPane rows and columns such as setPercentWidth and setPercentHeight.
To demonstrate this approach, the ColorChooser sample provides some code for a re-sizable ColorChooser with a fixed number of color swatches per grid row and as the overall containing grid grows or shrinks, the color swatches are grown and shrunk to fit the available area as appropriate. The color swatches themselves don't necessarily maintain the same height/width ratio, but you could easily achieve that by setting appropriate min/max/preferred sizes on the child elements.
Create Your Own Layout
As an alternative to using change listeners and setting min/max/preferred sizes on children, you could implement your own layout manager by subclassing Pane to create a UniformGrid class and implementing the layoutChildren method. In layoutChildren, arrange the size and position of UniformGrid children as needed. You can refer to the source code of an existing Pane to find an example of how to create your own layouts.
Investigate 3rd party Layouts
The ControlsFX project has a GridView or MigLayout which might provide the functionality of a UniformGrid.
Related
I have a number of UI elements like panels, edit fields, buttons, labels etc. so panels contain other panels which contain input fields, editors and so on. Most of the elements are editable and/or resizable which means whenever I change anything, a lot of adjacent UI elements should change their width, height and x/y position on the pane. It works fine with a small number of elements but incredibly slow when the number of elements is thousands.
Is there a fast layout algorithm which can be used in this case? Note that I cannot use any existing layout managers and should come up with my own implementation.
I'd suggest taking a leaf out of the Android playbook and have a larger 'grid' and keep everything sized in modular multiples - this avoids you needing to solve the knapsack problem everytime!
For example, instead of having a button with an width of 80 and a height of 40 you store this as metadata as {2:1} (assuming your layout grid is 40^40 squares).
This way if you have a work panel with space of, say, {2:12} this could be filled with two objects of size {2:6} or maybe 3 of size {2:4}.
It's pretty simple to fit-to-max too as any available space can just be scaled up (say you delete a {1:1} item you can just expand the one next to it to take the space etc - you can of course create your own rules around whether objects can scale in single directions etc.
The other advantage of this approach is that you can easily manage different screen sizes and resolutions too while still keeping the same framework and look and feel.
Since Jason Smith didn't recommend Relative layout and said that we should use Absolute layout I have a question how can we deal with RelativeToView concept?
Absolute Layout sets proportional coordinates and sizes of the elements within itself relative to itself not to each other as RelativeLayout. What to do if I need some elements to be relative to each other? Creating additional Grids and StackLayouts? I would rather use RelativeLayout then or I am missing something.
Decided to add a simplest example and consider we are talking ONLY about Relative and Absolute layouts, no Stack, no Grid. I have 2 buttons and I want to place them as shown in the picture
With absolute layout I could define the position of the top button and say it's height 10% of the screen. Now I could shift the bottom button by saying it starts at 11% of the screen. BUT this will change my top button height. If I want my top button to be it's natural "auto" size I cannot do that. So, how can I put my bottom button under top one if I have no idea how much top button occupies on screen? I know how to do it with Relative but how I can do it with Absolute Layout?
It looks like the solution is nest bunch of layouts https://developer.xamarin.com/guides/xamarin-forms/user-interface/layouts/absolute-layout/
Is that the only way? Is that performance still better than Relative layout?
By its nature RelativeLayout is powerful and offers layouting options that no other Layout on its own does. But that power comes at a cost in performance. Resolving the constraint dependencies consistently and obtaining a final layout doesn't come cheaply.
The point is not necessarily that RelativeLayout should never be used, rather that often times other Layouts can do the job, and yes, even 2-3 nested Layouts can be more performant than a single equivalent RelativePanel.
Grid in particular is a powerful option with which similar effects can be achieved by astute use of Auto, Star, and/or absolute-sized rows and columns as appropriate, plus RowSpan and ColumnSpan, plus element margins, etc.
To consider your specific example, I don't know of a way to achieve what you want with an AbsoluteLayout, at least without the added complication of attached properties. But it seems like a natural fit for a Grid with RowSpan="Auto" on the first row. From a diagram alone I can't tell exactly what other constraints you're going for.
Is there any Cocoa control equivalent to WPF's itemscontrol? I have been using a single column, view based NSTableView but can't seem to get individual rows to size to fit their content, or even to get different height rows (all views are sized to be as tall as the tallest one).
More generally speaking, is there any way of getting views to size to fit their content? I have been using constraints, but seem to only be able to make views size according to their container's size.
You should use NSTableViewDelegate and it's -tableView:heightOfRow: method to specify the individual row height.
I'm implementing the CSS3 flexible box layout module as defined by the W3C, which is similar to Mozilla's box model for xul. While these standards specify how the model should behave, they don't give any details on how they should be implemented.
The parts of the model I'm interested in are:
Boxes have a width and height.
Boxes can contain other boxes.
Container boxes (parent boxes) are responsible for sizing and positioning the boxes they contain (child boxes).
Boxes have orientation which may be horizontal or vertical. The orientation determines how the child boxes are positioned and resized.
Child boxes may be flexible or inflexible. If the child box is inflexible it is drawn at the size specified in the width and height parameters. If it is flexible, then it is resized to fit into the available space in the parent container.
Flexibility is relative to other child boxes in the same container, boxes with higher flexibility are resized more than boxes with lower flexibility.
Child boxes can be constrained to a minimum or maximum size. If the child box is flexible, the parent box will never resize it below the minimum size, or above the maximum size.
Features 1-5 can be implemented quite efficiently. Feature 6 is problematic as the most efficient algorithm I can come up with is quite naive. The algorithm works as follows:
Place all the boxes in a list.
Loop through each child box and resize it using the flexibility to determine the amount to resize it by.
If the size exceeds one of the limits, then set the box size to the limit and remove it from the list, and start from the beginning of the list.
Step 3 is where the efficiency drops. For example, if there are ten items in the list, and the last one has a constraint, then the algorithm calculates the size for the first nine items, then when it reaches the tenth one it needs to redo all of the calculations. I have considered keeping the list sorted and first sizing all the constrained boxes, however this comes with the cost of added complexity and the overhead of sorting the list.
I expect there is a recognised optimal solution considering this is a fairly common feature in browsers and frameworks (XUL, .Net, Flex, etc).
Most box/container layout algorithms use a 2 pass algorithm. In the case of .NET (WPF) they are called "Measure" and "Arrange". Each control can measure its content and report a "desired size" in the recursive measure pass.
During the second pass (arrange) if the childrens desired sizes will not fit inside the parent, the parent uses its layout algorithm to provide the actual size to each child, for example by assigning the actual size weighted by desired size. Minimum/maximum sizes, box flexibility etc can come into play here.
More information on the WPF layout system
http://msdn.microsoft.com/en-us/library/ms745058.aspx
Xul layout
http://www-archive.mozilla.org/projects/xul/layout.html
I want to load a table view with cells. In between cells I should able to see minimum cell gap. How can I increase existing table view cell distance in my navigation controller root view?
You can't increase cell distance, but what you can do is subclass UITableViewCell, override -layoutSubviews, and reposition all the internal views to allow for a bit of padding on one (or both) end(s) of the cell.
That said, I can't think of a single app on the iPhone that has a cell padding like this. You should think very carefully before doing this, as it's quite non-standard.
+1 you cant increase cell distance. However you can make it look that way: custom cells are easy to make in IB, and good custom cells are worth their weight in gold. You could set the cell spacer to none and a desired hight while making two UIImageViews (or a label with a cheeky string of underscores) in the cell to create the illusion of a cell boundary.
Here is a good tutorial on custom cells (I recommend watching the screen-cast):
http://icodeblog.com/2009/05/24/custom-uitableviewcell-using-interface-builder/