Solution
Original: Window Service > Parent Layout > Views
Fixed: Window Service > Parent Layout > Parent Layout 2 > Views
You cannot use a parent layout that is not a child to another layout before being added to window service. Only graphics will scale if you do so.
Issue
I have a RelativeLayout that parents some views like a TextView, SeekBar, and a Button. Using setScaleX/Y, I am successfully able to scale the views visually. A problem I now have is that although the graphics have scaled, the onClickListeners touch area have not scaled along with the graphics. I need to touch the original position in order to trigger any of these events. I want the touch area to scale with the graphics without scaling the children individually.
Current Scaling Code:
size.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
/** Max Progress is 100 **/
float scale = 1.0f;
scale = scale + 0.01f * progress;
/** mLayout is Parent Layout **/
mLayout.setScaleX(scale);
mLayout.setScaleY(scale);
mLayout.invalidate();
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
Solution
Original: Window Service > Parent Layout > Views
Fixed: Window Service > Parent Layout > Parent Layout 2 > Views
You cannot use a parent layout that is not a child to another layout before being added to window service. Only graphics will scale if you do so.
Related
I want to write a new class that extends Region containing a StackPane inside. But I'm getting into trouble when I add insets to it like padding or a border. Here is a simplified example of the class:
public class CustomPane extends Region
{
private ToggleButton testControl = new ToggleButton("just a test control");
private StackPane rootPane = new StackPane(testControl);
public CustomPane()
{
getChildren().add(rootPane);
setStyle("-fx-border-color: #257165; -fx-border-width: 10;");
}
}
And that is how the result looks like:
If I try to move the StackPane by calling
rootPane.setLayoutX(10);
rootPane.setLayoutY(10);
then the Region just grows:
But really I wanted it to look like this:
(The third image was created by extending StackPane instead of Region, which already manages the layouting stuff correctly. Unfortunately I have to extend Region since I want to keep getChildren() protected.)
Okay, I tried to handle the layout calculation but I didn't come up with it. Could experts give me some advise?
StackPane uses the insets for layouting the (managed) children. Region doesn't do this by default. Therefore you need to override the layoutChildren with something that uses these insets, e.g.:
#Override
protected void layoutChildren() {
Insets insets = getInsets();
double top = insets.getTop(),
left = insets.getLeft(),
width = getWidth() - left - insets.getRight(),
height = getHeight() - top - insets.getBottom();
// layout all managed children (there's only rootPane in this case)
layoutInArea(rootPane,
left, top, // offset of layout area
width, height, // available size for content
0,
HPos.LEFT,
VPos.TOP);
}
I have following server side code in the top level page to set background image for all pages in the app.
#Override
public void createContent(final Composite parent, final PageData oData) {
Image bg = ResourceManager.getImage( LnfSettings.IMAGE_PAGE_BACKGROUND );
Composite comp = parent.getParent();
int width = comp.getDisplay().getClientArea().width;
int height = comp.getDisplay().getClientArea().height;
comp.setBackgroundImage( new Image( bg.getDevice(), bg.getImageData().scaledTo(
width, height ) ) );
... more code here to create layout and contents
}
Above code correctly sets background for all pages and also scaled image to fit with the different screen sizes. But if I rotate the screen, image doesn't get scaled according to the new screen dimension. How to deal with this issue? I am using Tabris 1.4.
You can add a resize listener to your composite like this:
comp.addListener(SWT.Resize, listenerComp);
Listener listenerComp = new Listener() {
#Override
public void handleEvent(Event event) {
...
}
};
Just get sure you cache your scaled Images so you do not scale and create new images on every rotation.
Developing using GXT 2.2.5 on GWT 2.3.0.
The application I'm working on displays a resizable Window with auto scrollbars. I want to make sure the Window size does not exceed the size of the browser window it gets displayed in. To that effect, I added the following code:
addWindowListener(new WindowListener()
{
public void windowActivate(WindowEvent we)
{
super.windowActivate();
Window window = we.getWindow();
window.layout(true);
int width = window.getWidth();
int height = window.getHeight();
int maxWidth = XDOM.getViewportWidth();
int maxHeight = XDOM.getViewportHeight();
window.setSize(Math.min(width, maxWidth), Math.min(height, maxHeight));
window.center();
}
};
This manages sizing the Window to fit in the browser when it gets opened quite nicely.
My problem is that if the user then resizes the browser window, the open Window does not adjust and ends up being clipped.
Is there some way for me to either force the Window to stay within the boundaries of the browser, or capture the resize event so that I can tell the Window to resize accordingly?
Thanks.
You need to add the listener (actually handler -- listeners got depreciated) to the browser window.
So if you have several different windows you show at different times that all need to be resized with the window, you need to have a listener for each window and add it to the browser window when the window is shown.
To add a listener to the browser Window, use:
com.google.gwt.user.client.Window.addResizeHandler(handler);
So for example to resize ContentPanel cp:
com.google.gwt.event.logical.shared.ResizeHandler handler = new ResizeHandler() {
#Override public void onResize(com.google.gwt.event.logical.shared.ResizeEvent event) {
cp.setWidth(event.getWidth());
cp.setHeight(event.getHeight());
}
};
So then if you switch to a new view or ContentPanel you need to register that...
com.google.gwt.user.client.Window.addResizeHandler(handler2);
com.google.gwt.event.logical.shared.ResizeHandler handler2 = new ResizeHandler() {
#Override public void onResize(com.google.gwt.event.logical.shared.ResizeEvent event) {
cp2.setWidth(event.getWidth());
cp2.setHeight(event.getHeight());
}
};
NOTE:
You can't do event.getWindow() for the ResizeEvent you need to handle that another way.
Actually I tend to do it in a constructor like:
com.google.gwt.event.logical.shared.ResizeHandler handler2;
public MyDialog(){
handler2 = new ResizeHandler() {
#Override public void onResize(com.google.gwt.event.logical.shared.ResizeEvent event) {
setWidth(event.getWidth());
setHeight(event.getHeight());
}
};
I've been trying to work with the scaling transform in JavaFX, but haven't quite been able to wrap my head around it. Basically, I have a Pane containing a complex graph and would like to be able to rescale it. The scaling part itself works fine, however, the enclosing scroll pane will not adapt to the graph.
For simplicity's sake, i'll post a short example in which my graph is replaced by a label:
public class TestApp extends Application {
#Override public void start(final Stage stage) throws Exception {
final Label label = new Label("Hello World");
label.getTransforms().setAll(new Scale(0.5, 0.5));
label.setStyle("-fx-background-color:blue");
label.setFont(new Font(200));
final ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(label);
stage.setScene(new Scene(scrollPane));
stage.setWidth(200);
stage.setHeight(100);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
The label will scale correctly, but the enclosing scroll pane's bars will still accomodate a component of the original size.
I've tried so far:
Playing around with the labels min and pref size
wrapping the label inside a Group (no scrollbars will appear whatsoever)
scaling the enclosing Group rather than the label
What am I missing? What can I do to make the ScrollPane adapt to the content view?
Thanks for your help.
According to the ScrollPane document you might try to wrap a Pane in a Group so the ScrollPane is scroll by visual bound not the actual layout bound.
ScrollPane layout calculations are based on the layoutBounds rather than the
boundsInParent (visual bounds) of the scroll node. If an application wants the
scrolling to be based on the visual bounds of the node (for scaled content etc.),
they need to wrap the scroll node in a Group.
I implemented scaling in a ScrollPane for Graphs and other nodes in
this example of scrollpane viewports, transforms and layout bounds in JavaFX.
The code was implemented when I was first learning JavaFX, so certainly the code could be cleaner and perhaps there are simpler ways to accomplish this (e.g. using a Group as the container for the scaled node as suggested in the ScrollPane documentation).
One key to getting the solution I wanted (ScrollBars only appearing when you are zoomed in and the node is larger than the visible viewport), was this code:
// create a container for the viewable node.
final StackPane nodeContainer = new StackPane();
nodeContainer.getChildren().add(node);
// place the container in the scrollpane and adjust the pane's viewports as required.
final ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(nodeContainer);
scrollPane.viewportBoundsProperty().addListener(
new ChangeListener<Bounds>() {
#Override public void changed(ObservableValue<? extends Bounds> observableValue, Bounds oldBounds, Bounds newBounds) {
nodeContainer.setPrefSize(
Math.max(node.getBoundsInParent().getMaxX(), newBounds.getWidth()),
Math.max(node.getBoundsInParent().getMaxY(), newBounds.getHeight())
);
}
});
...
// adjust the view layout based on the node scalefactor.
final ToggleButton scale = new ToggleButton("Scale");
scale.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
if (scale.isSelected()) {
node.setScaleX(3); node.setScaleY(3);
} else {
node.setScaleX(1); node.setScaleY(1);
}
// runlater as we want to size the container after a layout pass has been performed on the scaled node.
Platform.runLater(new Runnable() {
#Override public void run() {
nodeContainer.setPrefSize(
Math.max(nodeContainer.getBoundsInParent().getMaxX(), scrollPane.getViewportBounds().getWidth()),
Math.max(nodeContainer.getBoundsInParent().getMaxY(), scrollPane.getViewportBounds().getHeight())
);
}
});
}
});
I have the following setup:
my controller inherits UINavigationController.
It holds a member of DialogViewController
My controller's ContentSizeForViewInPopover is set to 400|400
The DialogViewController's ContentSizeForViewInPopover is also set to 400|400
One of the elements in the dialog view controller discloses a long list of sub elements. If this list is longer than the 400 units I defined, the popover controller's height will be increased if this list is pushed on the navigation controller. This is fine, however if I go back to the previous menu, the size won't be resized to the 400 units I defined.
Is there a way to tell DialogViewController to not change the size?
Can you show code for your specific usage of MonoTouch.Dialog? You may be seeing this behavior because every time the TopViewController changes...UIPopoverController will attempt to auto-negotiate it's own ContentSize.
You should set the ContentSizeForViewInPopover for each UIViewController being presented by overriding the WillShowViewController method and setting the SizeF there.
public class NavDelegate : UINavigationControllerDelegate
{
public NavDelegate()
: base()
{
}
public override void WillShowViewController(UINavigationController navigationController, UIViewController viewController, bool animated)
{
base.WillShowViewController(navigationController, viewController, animated);
viewController.ContentSizeForViewInPopover = new SizeF(.., ..);
}
}