How to replace a view - titanium

Application requires more than one window (Lets call A,B,C). Each window has more than one view (table views, image views as well as web view). Lets say window A has three views (x, y,z) and window B has three views (d,e,f). Application needs to display images of different size on orientation change.
I have achieved the same using gesture event listener and looping through windows for views and replacing the view with new images. The problem I have is when we navigate from one window to other and the orientation changes, the loading of view after looping goes for a toss. Is there a better way to achieve the same ?
Is there a method in titanium like following code to replace a view ?
var self=Ti.UI.currentWindow
var newView=Ti.UI.createImageView({image:'abc.png'})
self.replace(self.children[1],newView )

Unfortunately there is now replace method.
You need to remove the whole view and add it again but this can cause a wrong layout if you have more than one view on a same level. The implementation then depends on the layout which was set (vertical, horizontal, composite etc).
For example in vertical layout removing an item and simply add a new one would remove your specified item but appends the new one at the end since you can't specify in which order it should be added.
If you have a composite layout you can specify absolute positions but adding a new view causes a higher zIndex for this view so that it will hide views that were previously added at the same/similar position.

Why not simply change the image link ?
var self = Ti.UI.currentWindow;
self.children[1].image = 'bcd.png';

Well you could always lock the orientation of your window. But this isnt exactly good practice (especially for iOS).
Generally orientation changes are handled pretty well if you define the width and height of your views to be percentages or Ti.UI.FILL, if you have a composite layout. Check that you are not giving the views absolute coordinates as this could cause layout problems. If you have a vertical or horizontal layout you usually don't have to worry about orientation change, unless you did not nest your views in a main container correctly.

Prasad,
If this is about just ensuring that the images look good on different orientations,you can make use of the different folders provided by Titanium in the android/images folder.You can just make different images for each of the orientations and device sizes.For IOS you can change just the images on orientation change as you are already doing.
https://wiki.appcelerator.org/display/guides/Using+density-specific+resources+on+Android
If you are concernced about the layout there are couple of things you can do:
1.Give all the height or width values in percentages.This way all elements will be re sized once the orientation changes automatically.
2.On each window open check if the orientation is vertical or horizontal by default and accordingly set the image attribute of the imageView.
Ti.UI.orientation
This property will give you the orientation of the window by default.Values of this property could be this
Ti.UI.PORTRAIT
Ti.UI.UPSIDE_PORTRAIT
Ti.UI.LANDSCAPE_LEFT
Ti.UI.LANDSCAPE_RIGHT
Use "if else" and accordingly set the images.

Related

Autolayout: NSStackView won't resize parent view when height dynamically changed

Similar question: How to resize a parent view based on the size of subviews layouted with Autolayout
I got an NSStackView which loads DisclosureViewControllers (NSViewController subclasses) just like in the Apple Example InfoBarStackView.
Those can expand and retract views of arbitrary height.
I would like the parent view containing the NSStackView to resize its height according to the contents of the NSStackView. In the Apple example that works.
However, unfortunately, Apple is resizing a NSWindow and I am using a CCNStatusItem (CCNStatusItem Github), a view that attaches to the status item in the Apple menu bar. That window resizes to the contents of the NSStackView when it loads, but doesn't resize when the contents change.
When I expand a section, the content overflows and gets clipped on the bottom edge of the view.
I went through all the constraints and tried to reproduce it exactly, but couldn't get it to work. In the Apple example, they are adding everything programmatically, whereas I added a NSStackView in Interface Builder.
Here are the constraints of the NSStackView:
My question would be: What constraints do I have in the Interface Builder (with what priorities), so that the parent view (the window) resizes with the contents of the stack view dynamically?
Do I have to call some method of the view to make it work?
Please let me know if I missed to provide some necessary information.
UPDATE
The accepted answer was the right way to do it. Here's the result. My forked version of CCNStatusItem can be found at https://github.com/julianvogels/CCNStatusItem.git
When using auto layout constraints, you don't need to call a view method to cause this effect, but just make sure that:
the views inside the stack view have constraints that will cause them to grow
the container has constraints to the stack view that indicate the container should grow with the stack view
the container doesn't have any constraints that would prevent it from growing
The screenshots seem to indicate it's not the first -- the views are growing as expected. So it could be either the second or third. The screenshot from interface builder seems to show that the bottom StackView<>Container constraint is optional (it's dashed). Depending on what the priority actually is, that could be your problem. Based on the design you described, there should be no reason for that constraint to be non-required.
The problem is that CCNStatusItem is not auto-layout-compatible. It sets the content view of its window to an instance of one of its own view classes (CCNStatusItemWindowBackgroundView). Your view is a subview of that view.
When it creates and adds its view, it does not turn off translatesAutoresizingMaskIntoConstraints or use constraints to position it relative to its superview. That basically means it can't be forced to a different size by constraints.
Likewise, when it adds your view to the background view, it does not turn off translatesAutoresizingMaskIntoConstraints on your view nor does it set up constraints to relate your view to the background view.
Since you've got the source, you can make those changes.

How to implement scroll view in xib cocoa objective-c

In order to implement scroll view I do:
Create Cocoa Application
Go to XIB
Drag scroll view to the view window and set its constraints to 0
Everything seems fine until now
Under Bordered Scroll View (in the Document Outline) I press on Clip View and then View and resize that to any large number (under size inspector)
I add a button (for the sake of it) to the view (under clip view) (in the Document Outline) and sets its constraints
After this I immediately get the "Ambigious Layout. Position is ambigious for "View".
What am I doing wrong? Is this the proper way to add scrollview? It also seems rather difficult to add items to the scrollable area as I dont see the entire scrollable area in the xib.
Please help a noob.
In general this is a correct way to add a scroll view. (You can also create a view or set of sibling views, select them, and choose Editor > Embed In > Scroll View.)
If a view has no constraints, then Xcode will add sufficient constraints at build time. These constraints are not necessarily the ones that cause the view to behave like you want as things change size, but they're good enough to maintain the current layout of the canvas when things have their current sizes.
However, once you add constraints, Xcode will start insisting that the constraints are mutually-compatible (no conflicts) and sufficient to be unambiguous.
So, that explains why you get that warning. You have added some constraints, but not enough to make the layout unambiguous. You need to add enough. Xcode should explain in more detail what's needed, although there will necessarily be multiple possibilities for how to resolve the ambiguity.
In your case, I'm guessing that the size of the view in the scroll view is ambiguous. For example, you may have added constraints to position the button relative to the top and leading edge, and the button likely has intrinsic size, but you haven't constrained the view's bottom or trailing edges to the button. So, the size of the view could be anything.
Of course, rather than constraining the view's bottom and trailing edge to the button, you could just add explicit height and width constraints to it. Or whatever.
You may also need to constrain the view to the clip view.
You can also use Editor > Resolve Auto Layout Issues > Add Missing Constraints and see what Xcode adds. You can then change things from there if what Xcode added is not what you want.
For my Mac OS X app, I selected the controls on xib to embed in scroll view ( Editor > Embed In > Scroll View ) and applying the following constraints to Custom View (inside Scroll View -> Clip View) did work.
Where hight is to accommodate controls.

IOS 7 Approach for create container with two elements?

So, i am new to xcode and iOS7 and i'm trying to create simple container with two elements inside.
I prefer to make it 100% programmatically. (no IB)
I want to create container with two elements Image and Label.
I want to achieve variable width depends on the text element inside.
Here is example:
Based on user action i want to change text on the fly. Let's assume longer text, and main container have to change width too.
And now the question is: What is best approach to to that?
UIView with subviews or something else i'm just expecting direction.
Code examples with be gratefully appreciated.
Thank you in advance.
What you have described is exactly what a UIButton does automatically: it is a container containing an image and a title (text) and it resizes itself automatically when the text changes.
Let us assume, however, that you want to do this yourself. That is, let's say you want a UIView ("container") containing two other UIViews (subviews). Then we need to discuss this requirement:
Based on user action i want to change text on the fly. Let's assume longer text, and main container have to change width too.
This is not going to happen automatically. You can use constraints (auto layout) to describe the size / position of the subviews in relation to the superview, but it works the other way: the superview changes, and the subviews obey. So you will have to change the superview size manually after you change the text.
You can still use auto layout to help you. Let's say the text is in a UILabel. Well, a UILabel wants to change width automatically when the text changes. So far so good. But you must still change the container view width yourself. You can call systemLayoutSizeFittingSize: to learn what the size of the container should be, using constraints, working from the inside out; but then you will have to change its size yourself to that size.
(You can easily create the view, the subviews, and the auto layout constraints in code.)
If you don't want to use autolayout, then you will just calculate the sizes and positions of everything when the text changes and adjust it all yourself (in code). You can learn the size the label needs to be, to fit its text, by calling sizeThatFits: (or sizeToFit which will actually resize it correctly).

Making a CustomView with a static vertical size in Cocoa

I'm making a document viewer in Objective-C, I want to have a bar at the top of the page with a bunch of buttons in it which open up menus, change pages, etc. At the moment I'm using a custom view which then just has all of the buttons inside it, but my problem is that it isn't a static vertical height, so when the window resizes it changes the size of the custom view rather than my PDFView. Is there a way I can stop it from resizing, or is there a better method I should be using to create a menu?
Thanks!
With auto layout, you can just give the view a fixed height -- from the editor menu, choose Pin, then Height. Make sure that it then only has one vertical constraint, either to the top, bottom, or centerY.
Are you using Auto-layout ? You may have to play with it.
Without seeing the code it's hard to debug the problem. Post the snippet where you're re-sizing the views if you're not using auto-layout.

Change size of window in Cocoa?

I have a window whose size I need to change when the user clicks on it. I am using [self setFrame:windowFrame display:YES animate:YES] to accomplish this.
Even though the window successfully changes size (I increase its height), it moves the contents of the window up with it. How do I prevent this from happening? I want the contents to remain in place.
I am on OSX Mountain Lion developing an app for OSX using Objective-C and Cocoa.
EDIT: Constraints and/or Springs and Struts will not work as I need to move the contents around after the window is resized.
Constraints and/or Springs and Struts will not work as I need to move the contents around after the window is resized.
In that case, you should use NSViewAnimation.
A single view animation can actually perform multiple animations to multiple views, and you can even do one to a window, despite the class's name and the fact that windows aren't views in Cocoa.
You create a view animation with initWithViewAnimations:, which takes an array of dictionaries. Each dictionary identifies the target (NSViewAnimationTargetKey) and what to do to it: Either change the target's frame (NSViewAnimationStartFrameKey and NSViewAnimationEndFrameKey) or fade the target in or out (NSViewAnimationEffectKey). For your case, you'll be changing the targets' frames.
When the user does the thing that causes the resize of the window, you'll need to compute the desired overall size of the window (taking care to adjust its frame's position so it doesn't grow off the screen), as well as the new frames—both positions and sizes—of your views. Everything that will move and/or change size, create a dictionary for it and throw it into the array. Then create the view animation.
An NSViewAnimation is a kind of NSAnimation, which provides all the methods for starting and stopping the animation, monitoring its progress, hooking into it, and chaining multiple NSAnimations together. If nothing else, you'll need to start the animation.
If you are using the Interface Builder to build these views, then I believe one approach is to set the "struts and springs." These are available under the "size inspector" and are the red arrows and bars above the "autosizing" label. Play around with these to get the effect that you want, but the general idea is that the arrows control how the size of the view adjusts to changes in the size of the parent view, and the bars control the relationship of the edges of the view to the edges of the parent view as the size changes.
In constraint-based layout, set the views around the edge of your window to be a fixed distance from their superview's edge.
Xcode will infer a lot of resizability from that; if anything still isn't resizing properly, adjust its constraints so that its width and/or height is no longer constant.
The easiest way is to move your views until blue lines show up in the editor. Each blue line corresponds to a rule in the HIG about how things should be lain out, and if you drop the view there, Xcode will create constraints matching those guidelines. For example, if you set a view 20 points from the right edge of its superview, you'll get a blue line for that, and if you drop the view there, you'll create a constraint that the view must remain that distance from that edge.
The superview isn't the only view with which you can create HIG-based constraints. You can also create guideline constraints between sibling views. For example, if you put a button next to another button at the appropriate distance, you'll get a blue line across that distance, and if you drop it, you'll create a constraint that those two buttons must remain that distance from each other.
If you want to do something really custom, the three buttons in the lower-right corner of the nib editor will let you create any constraint you want. What you have selected determines what constraints you can create; the nib editor's outline view will help you make sure you have the selection you want.
You are going to have to iterate through all of your subviews and change their frame positions based on the delta of your window frame.
so if you expand your window frame by 20 in all directions, all your subviews are going to have to increase their frame positions by (20,20) to offset the windows movement.