There is a bug with my UIScrollView populated with xib files that does not accurately resize xibs to fit the view. As such, when scrolling there is a noticeable offset emanating from the right side of each presented xib element and the contexts of the next element bleed into the previous. It formats correctly on the iPhone 6, but no screen larger than it.
Given that there are no constants in my code and the dimensions should be retrieved from the view itself regardless of size (using view.frame.width and view.frame.height), I wonder if there's some larger point I'm missing about UIScrollView or wether or not it simply isn't the best solution to my problem. Is there another class for creating a sort of scrollable horizontal slide-show?
You need to add constraints in order to make it work correctly in different screen sizes.
Related
Got a map which is composed of multiple parts:
Each part is an UIButton with an Image. I positioned everything to make up the map and it first looks all right. The problem I have is about resizing the View for different screens sizes. Tried with Autoresizing and Constraints but couldn't get it to look properly for minimizing and maximizing it. The parts should always sick together and up-/downscale according to the screen size. I'm testing the behaviour directly in the Interface Builder by resizing xib's dimensions.
What works is setting all arrows in autoresizingMask for each UIButton and maximizing the view. But minimizing it distorts the map.
Unfortunately it's the first time for me working with the Interface Builder in Xcode. Here you find the source files. Thanks!
Edit:
Setting only the arrows for width and height in the autoresizingMask makes it possible to downscale without distortion. Upscaling pulls the parts apart. How to support proper up-/downscaling simultaneously?
Edit1:
Replaced the every UIButton with UIImage which resize properly in the Interface Builder! See repo here. Unfortunately on simualtor devices the Autoresizing differs and the map-parts don't stick together anymore. Setting the size of UIView in Main.storyboard exactly to xib's size the Autoresizing works perfectly (tested on multiple devices). But later on in the "real" project I'm not in control over the parent's view dimensions.
Played a litte bit with this line of code and it seems to be responsible for "blocking" Autoresizing. How to avoid that? Thanks in advance. I think I’m maybe mixing up Autoresizing with AspectFit which seems to have no effect.
I guess it would be much easier if all the Bundesländer images had the same size. Put them all on top of each other in a common view. Give all the buttons zero padding to all side. Subclass UIButton to check if the the touch event is on a non transparent pixel. Search for "irregular button ios" to find out more about it.
I am able to achieve this using this images, which have all the same size, border added to demonstrate size
and this constraints
The most important constraint might be the Aspect Ratio Constraint on MapWrapper, the view that contains all the buttons.
Using Ole Begemann's OBShapedButton
Some notes:
Your image content is perfect for factorised graphics. Export them to pdf and add them as such as single scale to your assets
you should not include the states names' in the images, but use it as the buttons titles'. To position them correctly, use title insets.
example project: https://github.com/vikingosegundo/germanStateSelection
I am creating popup that measures it's size (here only height) from the its content.
Popup consists of two half (top and bottom). I have decided to wrap top half into separate wrapper view for clean code, so I have added UILabels, UIImages etc. into it in the separate method, but now I am facing problem with it.
Their size for AutoLayout is 0! So, I have a size of popup less than needed:
But if I remove wrapper then everything is OK:
I feel that it is enough data for iOS to render it correctly, but I don't know the command to force iOS to calculate size of wrapper basing on sizes of its subviews and constraints.
I have tried invalidateIntrinsicContentSize on the wrapper, but didn't help.
I am marking up from the code, so I don't forget to set Translates autoresizing masks into constraints to false for child views.
Ok, It is figured out that I forgot to joint top and bottom of wrapper with top of top view and bottom of bottom view respectively.
I have a stack view that contains three UICollectionViews, set up to give each of them equal vertical space. That stack view is set to be the height of half of the display, so that it uses more space on larger devices. This has been set up in Interface Builder.
So, I need to set the cell size of the UICollectionView at runtime, since until we are running, I don't know what the actual size of the cells will be. I want them to be square, so I just want to take into account the height of the UICollectionView, subtract out the top and bottom section insets, and set the itemSize to the resulting size.
I attempt to do this in viewDidLayoutSubviews, since by then I figure that the initial heights of the collection views have been set. However, they appear to be set to 1000x1000 (even though they are a much more reasonable size in the storyboard), and so I compute a cell size based on a collection view height of 1000. This is too large, but I figure that I'll get called again and get another chance to recompute it. And I do, but not before UICollectionView complains loudly that the itemSize is incorrect (ie. too large to fit in the collectionView, which now has the "correct" size.)
What is the best way to get the behavior I'm looking for without the warnings from UICollectionView? Setting the collection view item size at runtime based on the eventual size of the UICollectionView is something I've struggled with in the past, and there never seems to be the "right" time to set the itemSize. I don't want to dynamically return it, if only because it's not something that changes during the life of the program. There just seems to be some inconsistencies that occur when laying out the views initially.
It seems odd to me that the collection view comes in with an initial size of 1000.0 by 1000.0, but I'm not sure how or why to fix that - perhaps it has something to do with being embedded in a stack view?
Edited to add: It is almost certainly the UIStackView that is causing the layout issues. I created a dummy project to test the size of a UICollectionView when it is the top level view vs embedded in a UIStackView. If it is not embedded, when viewDidLayoutSubviews is called, it has been properly sized to fit the bounds of its superview. However, if it is inside of a UIStackView, it stays at the default size of 1000x1000.
For now, I am working around this problem by adding the following code in viewDidLayoutSubviews:
if collectionView.bounds.size.width > view.bounds.size.width {
view.layoutIfNeeded()
}
Where collectionView is inside a UIStackView and view is the main view of the UIViewController. This allows all subsequent calculations based on the size of the view to be correct, and hopefully will not get called if the UIStackView behavior ever gets fixed.
Similar discussions here and here. Interesting point that in XCode8, the new default is to not save sizes of views in the XIB file, but instead bring everything in with an initial size of 1000x1000, to be resolved during the first layout pass. Except for UIStackViews, I guess.
Are you having sizeForItemAtIndexPath() return itemSize? I have found that implementing that function is the only reliable way to size a UICollectionViewCell dynamically at runtime.
I've read quite a few tutorials and watched numerous videos on using constraints in Xcode. For some reason, I'm still missing certain aspects that are necessary to make the user interface look the way it's supposed to for all screen sizes.
Currently, I have a UITableView laying on a view controller. The view controller is set to "Inferred" size and I have all of the different sized devices open in Assistant Editor Preview to the right so I can view the changes. I've encountered multiple problems attempting to get the constraints correct for the different screen sizes.
Problem 1: The UITableView has a width set to 600. This causes dead space to the right of the table view on the iPad preview and it causes the UITableView to extend too far on the smaller devices. If I make the width of the table view smaller so that it fits within the preview of all screen sizes and then pin the left and right edges of the table view to the edge of the Superview by specifying 0 and unchecking constrain to margins, the result I'm seeing in preview is that the entire table view disappears completely from each device size. I was surprised by this because I thought by pinning the table view to the margins, it would make the table view fit within each of the screens.
Problem 2: (This is a completely different scenario from Problem 1, above.) In this situation, I've left the size of the table view to 600 and just specified constraints for the internal components of the cell contained within the tableview. In this case, the table view is still slightly not wide enough for the iPad dimensions and it extends too far on the smaller devices which makes components in the cells to be truncated and off of center.
I've primarily been working in Storyboard with Any width, Any height set. However, if I change the setting to Compact width, Any height, I can alter the constraints to fit the smaller devices a little better, but there's still a problem with getting things to work between the 5.5 inch screen and the smaller devices.
I would like to get my UITableView to extend all the way to the edges on each device and I would like to have the view inside of the cell remain centered and keep it's relative size on each of the devices. Does anyone have any suggestions on how I can accomplish this?
if you want to make your tableview to "fill" the whole screen (device-independent) the only thing you have to do is to pin its 4 edges (top, left, bottom, right) to its superview (the viewcontrollers view in your case) with a constant of 0.
you do not specify a specific width (like in your case 600) or height.
good luck :)
When using autolayout, calling intrinsicContentSize seems to be the method to determine what CGSize is required to properly fit the views content.
However, this method is only supported for a limited number of existing UIViews.
Anytime that I make a custom view, even if it is something as simple as a UILabel inside of a container UIView, that containing view is unable to determine its intrinsicContentSize (returns -1).
I don't understand why the view is able to properly be displayed on the screen yet the view doesn't even know its own height...
The UILabel in a container view is a simple example but I'm dealing with slightly more complicated UIViews where there are maybe 15 views nested within eachother. In order to determine the size of the view which contains all of its subviews, I have to manually create my own intrinsicContentSize method and do very time consuming work where I have to sum up all the heights of the subviews plus add to that all of the constraints.
This process is terrible. It's very easy to miss out on a height somewhere by forgetting to add the height of one of the subviews or constraints. Also, the matter is further complicated by the fact that with dynamic subviews. For example, if the view has 2 columns of dynamic subviews, you need to manually find the height of the subviews+constraints for each column, compare these heights and return the larger of the two. Again, this is a simple example but often it's not so simple, causing many many migraines.
Back to what I was asking earlier. How can iOS display the view yet not even know how tall the view is? There must be some way to find out what that height is. Thanks for reading.
Here is an image to help visualize what I want.
Are all your subviews using auto-layout themselves? I mean that if your using auto-layout to place MyCompositeObject, is that composite object using constraints internally to place its many objects? I've found that if so, then the intrinsicContentSize will account for all the subviews, but if not, your UIView's intrinsic content size is going to end out returning something inaccurate and small.