I have an NSWindow with 2 NSViews (an NSSplitView and a custom NSView). Accessing the data to populate these views can take some time. During this period, I'd like to gray out the content of these views.
My first approach was to have a black third NSView that covered the other 2 and achieve the graying out effect by changing its alpha value. However I've since learned having a hierarchy with sibling views is undefined.
What is the best approach here?
Cache the NSBitmapImageRep of the 2 views, then replace them with the 3rd view, using the cached image(s) as background
Set the alpha value for each view separately (still not quite sure how to get the black background for the graying effect)
Something I haven't considered
I'd use a child window. Set its content view to a plain black view (hopefully with status and progress information in subviews), and its alpha value to the desired fade-out, and add it as a child window of the window whose content you want to fade out.
I'd teach the views how to draw themselves in a disabled state, but there are other suggestions here:
How can I darken everything displayed in a single NSView?
Related
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.
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.
Attached 1 is a screenshot from an app called GeniusScan where you can photograph any document and an adjustable rectangular grid shows on the imageview. You can easily adjust the borders of the grid with your fingers to select the portion of the image that you want to scan. It will be then transformed into the correct prospective.
1- How can I draw and interact with the grid on the imageview?
2- How can I return the corner points of the grid to my view controller.
Update: I found a wonderful class called BJImageCropper which allows to use fingers to ajust the borders, but only for a box like rectangle. Can anyone suggest how it can be updated to support shapes like in the GeniusScan app?
Dude:
I created a demo that solves both questions:
1- How can I draw and interact with the grid on the imageview?
By Adding 4 views that will act as interactive control points by adding UIPanGestureRecognizer and then drawing the grid using CAShapeLayer on top of your view.
2- How can I return the corner points of the grid to my view controller.
You must keep references to the four control points of your grid.
Here's the link to my code.
This isn't actually drawing on top of UIImageView. It's actually an overlay (view) on top of the UIImageView. You need to keep track of 4 points (have 4 views as subview of the layer), track their positions, once moved, use drawRect: to draw lines based on the 4 points.
The way I've implemented it in my app is, I overlay the UIImageView with a transparent 'SelectionView' (a custom view that I wrote). The selectionView contains 4 custom subview of class 'Vertex'. The vertex talk back to the selectionView via protocol method every time user touches/moves it (it's actually not important which vertex moved, just that it moved):
- (void)vertexMoved:(Vertex *)vertex;
Then the selectionView knows that it needs to re-draw, so it calls setNeedsDisplay which calls internally calls drawRect (you should never call drawRect) where I do the actual drawing of the bounding rect. Basically, iterate through each vertex and draw a line using Quartz APIs and fill it with semi transparent/hollow color.
This is how I am doing it atleast, I am sure there are other ways.
I wanna do something like THIS in my ipad application, what is the best way to do the followings:
The shadow under the upper bar.
The padding for the papers (top, left, right & bottom)
The background (as a notepad) : please think about the cells: they must still scrolled inside the paper and cropped before reaching to the paper bottom edge.
I'm looking for the optimal solution that avoids overriding as much as possible.
EDIT :
I tried to use UIViewController (with UITableVIew and has the delegate methods) inside UISplitViewController, And I tried adding UIImageView at the top of the table but this view will scroll with the cells and it'll hide when I scroll down. I tried to use viewForHeaderInSection function also for upper shadow (under the bar) but what about the papers bottom edge (what if I put one image including the shadow and the papers bottom edge and has the padding as a background for the UITableView or UITableViewController, and change this image when rotate to the portrait orientation? is this a good and possible solution?)
My guess:
Create the background in an image editing app
Cut 4 images, for header, footer, left and right sides
Create a UIViewController with 4 UIVIews and add the correct images as background
In the middle of all 4 add a UITableView
This way the images won't move and if you position the UIViews with the background properly, your TableView will scroll inside the notebook (assuming you are trying to create a notebook)
If you app is iOS 6.0 only, autolayout will be a great help. Check apple developer video on it to learn how to use this feature: WWDC 2012 Session 232 - Auto Layout by Example
One easy way to do this is from the xib:
1. In xib create image .On image view you can put background whatever you want as a image.
2. create table view above the image view and set table view background color as a clear color.
This will do it.
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.