reorganize layout on orientation change in titanium - appcelerator

I have a layout that has sum specifications when it is in portrait. But when I change the screen orientation the layout needs to reorganize to fit the entire screen. The problem is that the layout keeps he's dimensions. So if the layout starts portrait the I change to landscape the layout keeps the portrait configuration. How can I make my layout so it auto reorganizes on screen orientation changes?
How I create my views:
var deviceHeight = Ti.Platform.displayCaps.platformHeight,
deviceWidth = Ti.Platform.displayCaps.platformWidth,
platform = Ti.Platform.osname;
if (platform == 'android') {
deviceHeight = Math.round(Ti.Platform.displayCaps.platformHeight / Ti.Platform.displayCaps.logicalDensityFactor);
deviceWidth = Math.round(Ti.Platform.displayCaps.platformWidth / Ti.Platform.displayCaps.logicalDensityFactor);
}
var View = Ti.UI.createView({
height : deviceHeight,
width : deviceWidth,
backgroundColor : 'white',
layout : 'vertical'
});

Very important: Don't specify width in points/pixels, but in percentages. Or use relative width. For example, if you want a view that is full width, minus 10 left and 10 right, specify that:
Ti.UI.createView(){
left: 10,
right: 10
}
Treat Apps different as websites! Make everything relative. There are so many resolutions it is impossible to make a layout PER resolution. Make a single solution for mobile, and possible re-arrange some stuff for tablets.
If you really want to redraw manually, use this event and redefine all your views after again:
Ti.Gesture.addEventListener('orientationchange',function(e) {
});
For this to work, you need to keep a reference to all your views and adjust where you like.

Related

Frame animation from outside screen and translateto inside screen

I'm new to animation with Xamarin Forms, I have a frame that I need to place it outside the screen like this:
The small frame is outside the device's screen
The small frame now inside the device screen
My problem is I need to know how I can place the frame like that (outside the screen) from the start, and how to know the width and the height of every device so I can use the TranslateTo() method to translate the frame to the exact same position for every device.
Thanks in advance
You can try this from your .cs page
Application.Current.MainPage.Width
Application.Current.MainPage.Height
You can use Xamarin.Essentials NuGet pakage to achieve this. And there is a useful class DeviceDisplay in there that should be helpful for you.
The documentation can be found here.
Usage example:
// Get Metrics
var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
// Orientation (Landscape, Portrait, Square, Unknown)
var orientation = mainDisplayInfo.Orientation;
// Rotation (0, 90, 180, 270)
var rotation = mainDisplayInfo.Rotation;
// Width (in pixels)
var width = mainDisplayInfo.Width;
// Height (in pixels)
var height = mainDisplayInfo.Height;
// Screen density
var density = mainDisplayInfo.Density;

Wrong map center in iOS using nativescript-google-maps-sdk

In iOS when I put marker and mapView location, the map does not display centered, but if I move the phone to landscape and rotate again to portrait the map center displays fine.
In Android works fine.
You can get more information in this GitHub issue:
https://github.com/dapriett/nativescript-google-maps-sdk/issues/322
I have personally faced this and discovered that it's basically a layout problem on iOS. The height and width attribute values supplied to the MapView's XML element are somewhat differently treated by iOS. The solution to our problem, as described in the question itself is resizing the map on runtime (as rotating the screen makes it go through a resizing routine). Applying this absurd logic at the beginning of the map render, solves the problem.
This is how I did it:
Provide the width value of the MapView in XML:
<maps:mapView width="100%" mapReady="onMapReady" />
and set the height of the map inside onMapReady method, with a 100 millisecond delay.
/* if you want to set height in DIP */
setTimeout(() => this.mapView.height = 500, 100);
or if you want to set height in percentage
/* [0.85 means 85% here] */
setTimeout(() => this.mapView.height = {
unit: '%',
value: 0.85
}, 100);
100 millisecond delay makes it go through the resize effect. Tested on iOS 12.1

Custom Xib With Defined Frame Constraints Is Changing At Runtime

I've spent several hours googling and in the debugger and I cannot figure out why my parent view in this xib is changing at runtime.
I have created a simple Xib:
In the container I set the width and height constraints (I tried setting constraints in the top parent but I can't seem to be able to):
At runtime I load the Xib programatically and I add it to a view. However after I add it to the view and set the position, the frame of the parent is smaller and the position is wrong.
Here I am explicitly set the x to 16, and the y to 400. When I look at it in the inspector debug tool however, I get different results than I want because the parent frame has changed and the Container position is wrong as a result. I turned the inspector to the side so you can see the parent (in blue) and the child container (in white) and how the parent is smaller than the child:
The details for the parent (the root xib view 'Item Detail Size Widget') are as follows. Notice the height is now 32 instead of 76:
The details for the top level child (Container) are as follows:
So the constraints I set for the container are being honored but the parent is resizing (I assumed since I couldn't set constraints it would use the frame I set).
I tried turning off and on translatesAutoResizingMaskIntoConstraints and a few other things but I can't seem to get the parent to be the exact same size as the Container.
Do you have any suggestions as to why the root Item Detail Size Widget will not match the size of the Container and is changing at run time?
Update
For reference here is the code where I add the widget:
let sizer: ItemDetailSizeWidget = .fromNib()
sizer.x = 16
sizer.y = 400
contentView.addSubview(sizer)
I have UIView extensions that set x and y as follows:
var x: CGFloat {
set { self.frame = CGRect(x: newValue,
y: self.y,
width: self.width,
height: self.height)
}
get { return self.frame.origin.x }
}
var y: CGFloat {
set { self.frame = CGRect(x: self.x,
y: newValue,
width: self.width,
height: self.height)
}
get { return self.frame.origin.y }
}
And here is the fromNib extension
class func fromNib<T: UIView>() -> T {
return Bundle.main.loadNibNamed(String(describing: T.self), owner: nil, options: nil)![0] as! T
}
Xcode always uses the autoresizing mask for a top-level view in a xib. You can see that your first screen shot: it has the autoresizing control shown.
Your top-level view's autoresizingMask is set to flexible width and height.
You have not set any width or height constraints between your top-level view and the “Container” subview.
You also have this code:
contentView.addSubview(sizer)
I suspect (since you mention contentView) that you're adding sizer to the view hierarchy of a table view cell or a collection view cell. When the cell is first created, it might not yet be at its final size. The collection view (or table view) might resize the cell after you return it from collectionView:cellForRowAtIndexPath:.
Since your sizer view has translatesAutoresizingMaskIntoConstraints set to true when it's loaded from the nib, and since its autoresizingMask is [.flexibleWidth, .flexibleHeight], this means that it will grow or shrink when its superview grows or shrinks.
To fix, try these steps:
Change the autoresizing mask to this:
Constrain the width of “Item Size Detail Widget” to equal the width of “Container”, and constrain the heights to equal also:

Xcode - viewDidLayoutSubviews

i have a view inside a viewController, i wanted to start the smaller view outside the viewController in the left, and animate it to the centre when i press a button. so i made it like this:
override func viewDidLayoutSubviews() {
smallView.center = CGPointMake(smallView.center.x - 400, smallView.center.y)
}
And it works perfectly!, the problem is i have a text view inside that smaller view, and every time i start editing it it jumps outside of the main viewController right where it was, and i have to press the button again to bring it inside.
How to fix this?
PS: i tried positioning it to the centre when i start editing the text view like this:
func textViewDidBeginEditing(textView: UITextView) {
smallView.center = CGPointMake(smallView.center.x + 400, smallView.center.y)
}
But it doesn't work. and the method is connected to the textView properly(delegate)
PS2: i also have imagePickerController inside my viewController.
OK, as you're using Auto Layout.
The first rule of Auto Layout (you will see this in any Auto Layout book) is that you absolutely cannot touch the frame or center of a view directly.
// don't do these
myView.frame = CGRectMake(0, 0, 100, 100);
// ever
myView.center = CGPointMake(50, 50);
You can get the frame and center but you can never set the frame or center.
In order to move stuff around using Auto Layout you need to update the constraints.
For instance if I set up a view called myView and want it to grow and shrink in height I would do something like...
Set the top constraint to the superview at 0.
Set the left constraint to the superview at 0.
Set the right constraint to the superview at 0.
Set the height constraint to 50 (for example) and save it in a property called heightConstraint.
Now to animate the change in height I do this...
self.heightConstraint.constant = 100;
[UIView animateWithDuration:1.0
animations:^ {
[self.view layoutIfNeeded];
}];
This will then animate the height from 50 (where it was when I set it) to 100.
This is the same for ANY animation of views using Auto Layout. If (for instance) I had saved the left constraint I could change that and it would increase and decrease the gap from the left edge of the superview to myView.
There are several really good tutorials about AutoLayout on the Ray Wenderlich site. I'd suggest you take a look at them.
Whatever you do, I'd strongly suggest not just disabling Auto Layout. If you don't know how to use Auto Layout then you will very quickly fall behind with iOS 8 and the new device sizes.

titanium view height and contents

I am new to Titanium and try to understand the how the views works and i am facing a problem.
I have create a view that contains one image and 2 labels.
var row = Titanium.UI.createTableViewRow({height:'auto'});
var item_view = Titanium.UI.createView({
height:'100%',
layout:'vertical',
top:5,
right:5,
bottom:5,
left:5
});
var item_image = Titanium.UI.createImageView({
url:imageUrl, // the image for the image view
top:0,
left:0,
height:97,
width:65
});
item_view.add(item_image);
var productName_lbl = Titanium.UI.createLabel({
text:productName,
left:70,
width:'auto',
top:-97,
bottom:2,
height:'auto',
textAlign:'left',
color:'#444444',
font:{fontFamily:'Trebuchet MS',fontSize:12,fontWeight:'bold'}
});
item_view.add(productName_lbl);
var comName_lbl = Titanium.UI.createLabel({
text:comName,
left:70,
width:'auto',
top:7,
bottom:2,
height:'auto',
textAlign:'left',
color:'#444444',
font:{fontFamily:'Trebuchet MS',fontSize:12,fontWeight:'bold'}
});
item_view.add(comName_lbl);
The problem is that the image has height 97px but both labels on left have smaller height.
The result is the image is now showing 100% but only show according the height of labels on left.
keep in mind that labels maybe really long texts so i have on labels width,height auto
i tried to change the row height from auto to 100% but still not working.
Any help appreciated
Try Titanium 2.0. It solves lots of these types of rendering issues.
You can read about it on their wiki Titanium 2.0 Layout Changes
I was having problems with View elements filling out to be the height of the screen (as opposed to the height of the elements it contains) and after reading the layout changes link from JC Guerrero (thanks JC!), I Added:
Ti.UI.createView(height: Ti.UI.SIZE, ...
and it successfully auto-adjusted the view's height to match it's contents
[edit] Removed quotation mark, and it works well, thanks!
Titanium calculate elements height badly, if you use 'vertical' layout. So you must set their height's by yourself, or remove layout property for 'absolute' positioning.

Resources