JavaFX evenly split children - layout

How can I acheive an evenly split UI, as the Player boxes demonstrate in the following example:
I would model it as an HBox with 2 evenly sized VBoxes, but I can't get them to stretch to the same size in the HBox.

Stretching VBoxes as two halves of single HBox works for me with HBox.hgrow="ALWAYS" property set for both VBoxes:
<HBox>
<VBox HBox.hgrow="ALWAYS">
...
</VBox>
<VBox HBox.hgrow="ALWAYS">
...
</VBox>
</HBox>

Give your HBox a PrefWidth Value. Then you can bind the Widths of your VBoxes to the half of that Width
hBox.setPrefWidth(400);
vbox.setPrefWidth(hbox.getPrefWidth()/2);
You might wanna take a look at JavaFX Scene Builder. There you can Design your Layouts.
Just saw using a SplitPane would also work. There you can set the DividerPosition to 0.5 (so centered). Then you can put every kind of Panes inside you like.

Place the two VBoxs in a TilePane instead of an HBox.

Related

iOS UIView Draw(CGRect rect) never called when I set VerticalOptions="CenterAndExpand"

I am using an iOS UIView for Custom control in Xamarin.IOS. I have used this control in Xamarin.Forms Xaml.
If I set my Grid Horizontal and VerticalOptions="CenterAndExpand", My Draw() in UIView never gets called. It works fine if i set the value to 'FillAndExpand'.
My requirement is to place my custom control in center of my screen.
Is there any way to handle this? or is there other way I could display my UIView in Center of my screen.
<ScrollView>
<Grid HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
<localControls:CustomUIView />
</Grid></ScrollView>
I need this Draw(CGRect rect) method to get the Width and Height of the available size in Screen. Hence my Draw is mandatory.
You can use AbsoluteLayout to let the view to the center of screen.
Views within an AbsoluteLayout are positioned using four values:
X – the x (horizontal) position of the view's anchor
Y – the y (vertical) position of the view's anchor
Width – the width of the view
Height – the height of the view
Each of those values can be set as a proportional value or an absolute value.
Values are specified as a combination of bounds and a flag. LayoutBounds is a Rectangle consisting of four values: x, y, width, height.
Code in Xaml like this:
<ContentPage.Content>
<AbsoluteLayout>
<local:MyCustomView AbsoluteLayout.LayoutBounds="0.5,0.5,300,200" AbsoluteLayout.LayoutFlags="PositionProportional" BackgroundColor="Red"/>
</AbsoluteLayout>
</ContentPage.Content>
AbsoluteLayout.LayoutBounds="0.5,0.5,300,200" AbsoluteLayout.LayoutFlags="PositionProportional" means the anchor is the center of the screen. And the view's Width and Height is 300 and 200.
It works like this:
BTW, I tried your code, but it works fine on my side with Visual Studio 15.3.5 and Xamarin.iOS 11.0.0.0, updating yours may solve the CenterAndExpand issue.

Can't get buttons in custom layout to return a minimal width measurement with WRAP_CONTENT

I created a custom flow layout class to lay out a series of buttons of equal height and various widths depending on what text each button displays. Each row contains as many buttons as possible, and any remaining space is distributed evenly to fill up the row. This generally works, but I can't get the buttons to be just small enough to fit their text, and as a result most of the buttons are exactly the same size.
This is how I'm creating the button and adding it to the flow:
Button button = new Button(this);
button.setMinimumWidth(0);
button.setText(eventType.get("name").asString());
button.setAllCaps(false);
button.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
button.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
eventTypeFlow.addView(button);
In the layout class' onLayout, I measure each button like this:
View child = getChildAt(childIndex);
measureChild(child, MeasureSpec.makeMeasureSpec(clientWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(clientHeight, MeasureSpec.AT_MOST));
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
But unless the text in the button is especially long, the width is always the same (264 in my case). I tried creating a linear layout XML with the button in it, setting minimum width to 0 and layout:width to wrap_content and that way the button is smaller, but when I distribute the extra space the linear layout grows, not the button.
Is there a way to get the buttons to return a smaller measurement when adding them directly to the custom layout?
Try using a LinearLayout using the layout_weight attribute. Give each button equal weight (1) and set your android:width attribute to 0dp.
Linear Layout layout_weight
More on LinearLayout's LayoutParams can be found here.
What ended up working is inflating the same linear layout XML I described in my question, then removing the button from the linear layout and adding it directly to my custom layout. Not very elegant, but it's the only thing I found that gets those buttons to be smaller.

JavaFX – exclude/include parent and all its children from layout dynamically

Background/Context:
I have a HBox as a parent and many child Nodes (Buttons, TextFields, Labels…). The HBox is a child of other container (BorderPane/VBox/Grid)
My questions:
How do I dynamically remove/exclude the parent (HBox) and all its children from layout?
I am looking for some three-state property on Node (like in Microsoft WPF):
Visible – visible and participate in layout
Collapsed – is not visible and do not participate in layout (applies to its children as well)
Hidden – is not visible but participate in layout
http://msdn.microsoft.com/en-us/library/ms590101.aspx
What options does JavaFX offer?
My solutions so far:
hBox.setManaged(false);
this work only for HBox, its children are still present
root.getChildren().remove(hBoxTop);
root.getChildren().add(hBoxTop);
Well, this looks like it could work.., but for example in case of root being BorderPane, once I remove/add and remove the HBox, the space after it remains unused. I already tried requestLayout() but id does not force thr rrot to fill it. Am I missing something? Is it correct approach to this problem?
Edited:
Well, I got this working.
Dynamically removing and adding for this specific case can be achieved by:
Remove:
root.setTop(null);
Add:
root.setTop(hBoxTop);
When I did not call setTop(null) on removal, BorderPane still reserved space for HBox (even after removal from its children).
IMHO: it is not very good model as it is parent-container specific. For example if I change, BorderPane to VBox a I had to change these methods as well. For VBox, remove/add on children collection works but I need to remember index so that HBox appears at same place after calling add.
Using root.setTop(null) is not a good idea because as you say it's specific to BorderPane.
I think the best solution is to use:
root.getChildren().remove(yourPane);
And use layout methods to place your other childrens as you want.
But maybe you should not use a BorderPane in the first place with the behaviors you want in your application.
Notice you can also do root.getChildren().clear() to remove all component and add it again to your layout but differently.

how to set lwuit textarea scrolling false

I want to add large string content to a container dynamically.
There are 60 different contents(strings) to be displayed in this container.
To add the string to container, I am adding a TextArea(empty border with 100% transparency).
The problem is that TextArea offers scroll and I do not want it to scroll. Instead I want to grow(increase height) according to content. I am unable to achieve this.
Can you help me out with this?
Or can I use any other component for the purpose?
I am using LWUIT with J2ME.
You can derive text area and return false for isScrollableY() although it should generally work seamlessly even if you don't do that (since your parent layout is scrollable). Is it possible you changed the text area and don't revalidate the parent form on the EDT?
There are problems with text area layout when it is modified by a separate thread (race condition with the layout code).
First put the TextArea.setSingleLineTextArea(false) , and grow by content true.

How place the components the front of another one?

I want to place the components A and B over component with List. I need that would text of list will be to visible. I can not find which layout can do it.
How this behavior is in lwuit? What solutions exist?
The question is somewhat unclear, jmunoz answer is correct if you want component's A and B to reside at the bottom of the screen and the list to scroll above. However from the drawing it seems you want an "always on top" effect which you can achieve either via a glass pane (for non-interactive components) or via the LayeredLayout class.
This is actually quite simple using the following:
myForm.setLayout(new LayeredLayout());
myForm.setScrollable(false);
// will occupy the entire area of the form but should be scrollable
myForm.addComponent(componentUnderneath);
Container south = new Container(new BorderLayout());
myForm.addComponent(south);
south.addComponent(BorderLayout.SOUTH, whateverYouWantToPlaceOnTopInTheSouth);
You must do the following:
The Form must not do scroll. Use Form.setScrollable(false). Set the layout of the ´Form´ to BORDER_LAYOUT, myForm.setLayout(new BorderLayout()) . Ok in BorderLayoutyou can put the components in the Form as you want.
Put the Listcomponent in the center of the BorderLayout with myForm.addComponent(BorderLayout.CENTER, List) and the other two elements in the south of the layout using
Container southContainer = new Container();
southContainer.addComponent(A);
southContainer.addComponent(B);
myForm.addComponent(BorderLayout.SOUTH, southContainer)
With this you can get a scrollable Listand two elements always visible.

Resources