Can constraints in Xcode 6 be dynamic? - autolayout

I'm biting the bullet and have begun using auto layout. Not as difficult to get used to than I feared. I am having trouble with this though.
Is it possible for view 2 to 'anchor' to the bottom of view 1.. UNLESS view 1 is hidden, in which case it should anchor to the top of the containing view? How would I set constraints for this?
If View1.hidden = NO:
If View1.hidden = YES:

Perhaps the easiest way to solve this issue is to manipulate constraint priorities.
I won't go into detail regarding how the Auto Layout system works – if you need that, check out WWDC sessions 202: Introduction to Auto Layout for iOS and OS X and 228: Best Practices for Mastering Auto Layout, both from 2012. Also, check out objc.io's great article on Auto Layout.
In short, constraints can be assigned priorities. A priority is represented by a floating point number in the range [0, 1000], inclusive. The special priority of 1000 means "required;" all other priorities are optional.
How can we use this to help? In Interface Builder (IB), create two different constraints for the top of your blue view. The first one should relate the top of the blue view to the bottom of the red view, with a distance of 0 points – that is, the top of the blue view should be flush with the bottom of the red view. We'll call this constraint the "unhidden" constraint.
The second constraint should go from the top of the blue view to the top of the superview, again with a distance of 0 points – that is, the top of the blue view should be flush with the top of its superview. We'll call this constraint the "hidden" constraint.
If you're following along, you've realized that it is impossible to satisfy both of these constraints simultaneously unless the red view's height is exactly equal to 0. That won't happen, though (I assume you're not resizing the red view, just hiding or unhiding it), so how can these constraints coexist? The answer lies in priorities. Make sure that, in IB, the priority of the unhidden constraint is 950 – remember, this optional, but at the high priority of 950. However, set the priority of the hidden constraint to something less than 950 – maybe 450, for example.
Next, you'll need to create outlets to these two constraints (how to do so is outside the scope of this answer – it's the same as creating outlets to anything in IB). I recommend naming them as I've named them here. So, in your header file, you might see the following:
...
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *unhiddenConstraint;
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *hiddenConstraint;
...
Now the only thing left is to alter the priorities of these constraints at the appropriate times – namely, when you hide or unhide the red view. So, in your view controller, add a method like this:
- (void)setRedViewHidden:(BOOL)hidden {
if (hidden) {
self.unhiddenConstraint.priority = 450;
self.hiddenConstraint.priority = 950;
self.redView.hidden = YES;
} else {
self.hiddenConstraint.priority = 450;
self.unhiddenConstraint.priority = 950;
self.redView.hidden = NO;
}
}
Then, whenever you want to hide the red view, you just call this method with the proper argument. Setting the priorities on the constraints will implicitly mark the layout as dirty, causing a new layout pass to occur on the next turn of the UI loop.
This is not a beginner use of the Auto Layout engine. Let me know if you have any lingering questions about this solution.

Related

how to use view order in set style javafx?

i'm struggling with a vertical box i added a transition to, it stays at the back of the other nodes like label and imageview. i tried using toFront() but it didn't work. also i tried using .setStyle("-fx-view-order: [number]") but i was lost a bit in what the numbers represent exactly is it the order of nodes ascending or descending.
#1
vb.setStyle("-fx-view-order: 0");
img.setStyle("-fx-view-order: 1");
didn't work
#2
vb.setStyle("-fx-view-order: 1");
img.setStyle("-fx-view-order: 0");
didn't work
The easiest way to get a Node to render on top is to move it to the end of the child node list for its parent Node.
Note the documentation for -fx-view-order mentions: "The parent traverses its children in decreasing viewOrder order." To me that means higher view order is behind (drawn first) relative to lower view order. However, this is all relative to the parent node, not the Scene. Give us a reproducible example of what you are doing.
Also, what version of JavaFX are you using? -fx-view-order was not in JavaFX 8 (JDK 8)
https://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html#node

Qt Layout, resize to minimum after widget size changes

Basically I've got a QGridLayout with a few widgets in it. The important ones are 2 labels, which I use for drawing images to the screen. Well, if the user wants, he can change the resolution of the incoming images, thus, forcing the Labels to resize.
Let's assume the initial size of the label is 320x240. The user changes the VideoMode to 640x480, the label and the entire GUI resizes perfectly. But when the user switches back to 320x240, the label shrinks, but the Layout/Window does NOT.
I've played around with sizePolicies and sizeHints, and resize(0,0), but nothing did the trick. Could somebody help me with this?
Here some screenshots to clarify the problem:
You need to set the size constraint of the layout holding all your widgets to "SetFixedSize". Although the name doesn't sound like it will work, it ensures that your layout will only use the space it needs. You will not have the problem like you do in your second screenshot.
Example:
mainLayout.setSizeConstraint(QLayout::SetFixedSize);
QLayout::setSizeConstraint(QLayout::SetFixedSize) solves this problem well when you prefer keeping your widget's size fixed at all times--that is, if you'd like it to always be fixed to its "packed" size (which may still vary as the child widgets change size). That is what the "fixed" means there: "fixed" to the correct size, even as the latter varies. (In Qt terms, what I'm calling the "packed" size is simply the widget's sizeHint.)
But a constraint may be too strong a solution in some instances. In particular, if you apply it to a top-level window, then the user will not be free to resize the window. If you don't like that, you can instead perform the "set size to sizeHint" operation instantaneously each time it's needed, rather than imposing it as an unrelenting constraint. The way to do that is to call QWidget::adjustSize().
http://doc.qt.io/qt-5/qwidget.html#adjustSize
Note that if the container whose children are changing size is not the top-level window, then adjustSize() may have to be called recursively on the container and its parents. (In my case I had to do that, anyway. I also tried the size-constraint scheme, and found that applying the constraint at only the topmost level was successful in compacting all levels. I haven't enough knowledge of Qt to comment usefully on these observations, so I merely share them.)
You need to store the original size of your widget parent window before applying any changes to the layout and restore it when the user switches back to the original.
Notice that you need to work with the widget parent window size and not the widget parent size.
in your widget before applying the layout changes:
minimumWindowSize = this->window().size();
when you finished reorganizing the widget to the compact size
this->window().resize(minimumWindowSize);
So that is exactly what i'm doing in mu project.
Resolution os doesn't matter. I have only to have a widget for rendering video, or image in your case.
void MainWindow::resizeEvent(QResizeEvent* event)
{
QMainWindow::resizeEvent(event);
if ((player != 0) && ((player->isPlaying()) || player->isLoaded() || player>isLoaded())){
renderer->resize(ui->mainVideoWidget->width(),ui->mainVideoWidget->height());
resizeFilter();
}
}

How do you make Interface Builder respect a custom view's intrinsic content size in constraint based layout?

Interface Builder in XCode 4.5 respects the intrinsicContentSize for some views, e.g. NSButton, but I can't convince it to respect it on my own custom subviews. This causes IB to add extra constraints trying to force the layout drawn in IB, which then causes the intrinsic sizes to not be used when the program is run.
For example, consider a button centered in a window, and a custom view centered in a window…
You can see that the custom view gets four constraints, presumably because IB doesn't know the view's intrinsicContentSize. You can change which extra constraints are added, e.g. you can force it to be width and height instead, but you can't delete them.
I'm coping with this now by searching and deleting the extra constraints in my awakeFromNib, but there must be a better way to do this.
Set a placeholder intrinsic content size — a "guess," if you will — in Interface Builder.
Select your custom view.
Show the size inspector (⌘Shift5).
Change the "Intrinsic Size" drop-down from "Default (System Defined)" to "Placeholder."
Enter reasonable guesses at your view's runtime width and height.
These constraints are removed at compile-time, meaning they will have no effect on your running app, and the layout engine will add constraints as appropriate at runtime to respect your view's intrinsicContentSize.
How to actually do this, 2019
import UIKit
#IBDesignable class TagPerson: ShadowRoundedImageView {
override var intrinsicContentSize: CGSize {
var s = super.intrinsicContentSize
s.height = 40
s.width = 40
return s
}
override func prepareForInterfaceBuilder() {
invalidateIntrinsicContentSize()
}
}
However, there is a problem. Xcode is buggy. You can sometimes reset it by:
The above will of course work flawlessly at runtime. But it randomly fails to work in interface builder (even with 11+).
To make it cycle, try
The usual 'Refresh all views'
Attach and delete a pointless constraint to one of your intrinsic size views. (I've noticed if you have a number of them, doing this to one is usually enough to make Xcode cycle, then they all work.)
And finally:
Xcode has an "intrinsic size placeholder" feature.
Select one or more of your intrinsic-size elements. Toggle the bizarre placeholder thing back and fore a few times. Often that makes it cycle and the view will then work correctly.
At worst, restarting Xcode with the usual clean-everything will, sometimes, get it working.
Ok, the point here is to make Xcode use the intrinsicContentSize of your custom view in IB.
This can be achieved by adding a placeholder view inside your custom view in IB with a fixed width and height (you can center it horizontally and vertically as well)
Then select your custom view and tap "Size To Fit Content" form the Edit Menu in IB.
At this point all extra size defining constraints will be deletable leaving only positioning ones.
That way IB will size your custom view to fit the placeholder view and and Autolayout would depend on your view's override of - (CGSize)intrinsicContentSize in run time to determine your custom view's size.
Last step is to delete the placeholder view to allow your view to display its content and size correctly:
- (void)viewDidLoad
{
[super viewDidLoad];
[_placeholderView removeFromSuperview];
}
I know this is a hack but hopefully it helps you.

flex 4 - depth property not working as expected

I am developing an isometric game.
I have a parent UIComponent (WorldMap). The player can choose MapElement s (game items) and drop them in the playable area WorldMap. This MapElement also is a UIComponent which contains child controls such as Sprite, Image, Label and custom Flex components to hold various information.
Now, I have written a logic to determine which one should appear in back and which one should appear in front in the Isometric area which I am calling idx (index) and I am seeting this value to the depth property of the MapElement.
I have added three components in the order shown in below pic and I have set the depth property each of them as 11077,11168 and 10630. If the depth property worked properly the 3rd item should have gone behind the 1st item but it seems like they are appearing in the order of they have added (default behavior)
If I am not wrong the depth value can be anything
Can some one help me?
I am aware of another solution using swapChildren, swapChildrenAt and and also addChildAt methods (which I don't want to use for my project specific reason) but I need to find out whats wrong with the depth
The problem, as I think, in your WorldMap component which, as you said, is UIComponent. Diving deeper to depth property shows that depth setter launches invalidateLayering method, which is empty in UIComponent and overrides with logic only in Group which is main container for every Flex 4 component. And here's example:
http://www.tink.ws/blog/flex-4-uicomponent-depth/
So, it looks like, you need to use at least Group or SkinnableContainer as your WorldMap in order to achieve depth property to work correctly.
Use UIComponent.addChildAt(child:DisplayObject, index:int). addChildAt adds a child DisplayObject instance to this DisplayObjectContainer instance. The child is added at the index position specified. An index of 0 represents the back (bottom) of the display list for this DisplayObjectContainer object.

Making a Flex DataGrid scroll smoothly

I've noticed that the default behaviour for a DataGrid's vertical scroll bar is to scroll one row at a time. This is all well and good when the rows are all uniform and small (e.g. displaying a single line of text), but gets really ugly as soon as you have rows with variable heights.
I'm curious, is there a way to make DataGrid scrolling "smooth"? For instance, is there a way to have the DataGrid scroll by a set number of pixels, lines of text, etc. rather than scrolling one row at a time?
So far, the only solution I've managed to come up with is to place the DataGrid in a Canvas and have the Canvas do the scrolling instead of the DataGrid. The issue with this approach, though, is that as soon as the Canvas scrolls far enough, the DataGrid headers scroll off-screen. Ideally, I'd like to get the smooth-scrolling nature of the Canvas, but also keep the DataGrid headers visible. Is that possible?
The way that ItemRenderer's work in Flex 3 makes smooth scrolling difficult to achieve. Basically Flex recycles item renderers scrolled off of the top of the list as the display objects used for new data at the bottom of the list. Adobe's implementation of most list components in Flex 3 creates and adds these items as they come on to the screen rather than just off the screen, so they "pop in" and smooth scrolling isn't available. I'm not sure why they couldn't have done it in a similar manner for items +/- one position above or below the current scroll pane, but they didn't, and we're stuck with sticky scrolling by default.
Work-arounds do exist, though the one you've noted (dropping the datagrid into a canvas) negates the display-object saving intention of item renderers and incurs a performance cost. This will be fixed for most list-based Flex components in Flex 4, though it won't be fixed immediately for DataGrid. The DataGrid / AdvancedDataGrid component is maintained by a separate team based in India, last time I heard, and so it tends to be a bit behind the rest of the SDK.
I'd recommend trying something similar to this implementation of a smooth-scrolling list by Alex Harui. I'm not sure exactly how well it'd work for DataGrid or AdvancedDataGrid, but this is the most intuitive technique I can think of for making the list scroll correctly.
Try this... It's still based on Alex's code that was mentioned above. His should still be a great start for removing the snap-to-row behavior. Original source:
http://blogs.adobe.com/aharui/2008/03/smooth_scrolling_list.html
Alex's original some code for smooth vertical scrolling but that was not an issue I had with the DataGrid. It was smooth scrolling horizontally that I needed. I am using the DataGrid in an unorthodox manner for analyzing plain text reports output by our database (great way of providing visual feedback on a document). The code below allows content to go off screen and the user can scroll without that snap-to-column behavior.
You can adapt this to use the same math routines for vertical scrolling and then it will make scrolling possible and ignore the snap to row behavior. In particular switch the usage of the listContent.move method to move the contents vertically and use a inverse of the rounded pixel value you calculate from the vertical scroll bar (as opposed to my using the horizontal).
This method is bit simpler than Alex's method from the link above - a lot less code so try adapting and see how it works.
override protected function scrollHandler(event:Event):void
{
// Override the default scroll behavior to provide smooth horizontal scrolling and not the usual "snap-to-column" behavior
var scrEvt:ScrollEvent = event as ScrollEvent;
if(scrEvt.direction == ScrollEventDirection.HORIZONTAL) {
// Get individual components of a scroll bar for measuring and get a horizontal position to use
var scrDownArrow:DisplayObject = horizontalScrollBar.getChildAt(3);
var sctThumb:DisplayObject = horizontalScrollBar.getChildAt(2);
// I replaced maxHorizontalScrollPosition in Alex's code with "1300" to fix my exact application. In other situations you may finding using some property or different value is more appropriate. Don't rely on my choice.
var hPos:Number = Math.round((sctThumb.y - scrDownArrow.height) / (scrDownArrow.y - sctThumb.height - scrDownArrow.height) * 1300);
// Inverse the position to scroll the content to the left for large reports
listContent.move(hPos * -1, listContent.y);
}
// Go ahead and use the default handler for vertical scrolling
else {
super.scrollHandler(event);
}
}

Resources