I have the code below which shows a popup. The popup has a main view which is black, and one subview which is white, and that subview has some labels, button and stuff the user interacts with. I want the surrounding black part to be partially transparent (alpha = 0.7), but the white part inside it to be fully opaque (alpha = 1.0). I could not achieve that, for some reason the value of the parent overrides its child values, and I get either a fully opaque view, or a view where also the labels and buttons are partially transparent.
What Can I do?
The code which shows the popup:
#IBAction func getLocation(sender: AnyObject) {
var p = PopupViewConrtoller(list: list, callback)
var x = UINib(nibName: "PickerPopup", bundle: nil).instantiateWithOwner(p, options: nil)
self.presentViewController(p, animated: false, completion: nil)
}
I changed opacity only in the attributes inspector.
It seems, it is not possible to make main view partially transparent without affecting the subviews added to main view.
What you can do is,
-set mainView background color as clear color
-add one more subview1 to mainView with size same as main view and set the background color as blackColor with desired transparency(alpha=0.7 as in required)
-add your subview2(which is having labels, buttons etc.) to mainView but above subview1 in layer order.
I hope it will help you to achieve what you want.
I figurred it is impossible to do it the way I was trying to. Rajeev has a good idea, but the best (and the one that apple reviewers will probably approve) is using popovers. This tutorial and this tutorial were helpful.
Related
I am making a Detail screen which has several nested views in the Storyboard View Controller: ScrollView > UIView > StackView > 5 UI Views. Each UI view is a different section that contains labels and edit texts.
When I set the background of one of the UIViews in the storyboard it changes but does not reflect this change when I run the emulator or on an iPad.
Below is a picture with the emulator view on the left and the Storyboard in Xcode on the right. You can see that the emulator shows no background color on the nested UIView while the Storyboard does.
Emulator vs Storyboard
Because it was asked for here is the full Storyboard. It is tough to see but it is a tab view controller connected to three split view controllers.
Full Storyboard
By testing with only specific views I have narrowed it down to the UIStackView holding the 5 UIViews that causes the problem. I have tried attaching a controller and changing the color in code but nothing I've tried seems to change it.
class ClientDetailViewController: UIViewController {
#IBOutlet weak var basicInfoUIView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
basicInfoUIView.backgroundColor = UIColor.init(displayP3Red: 22, green: 22, blue: 22, alpha: 0.5)
}
}
I expect for each section (UIView) to be a dark gray color but instead they are all clear so the scrollview background color can be seen.
UIStackView doesn't allow changing background color:
The UIStackView is a nonrendering subclass of UIView; that is, it does not provide any user interface of its own. Instead, it just manages the position and size of its arranged views. As a result, some properties (like backgroundColor) have no effect on the stack view. Similarly, you cannot override layerClass, draw(:), or draw(:in:).
(from UIStackView)
A simple workaround is to add another UIView behind the stack view, setup the constraints to match the position and size of the stack view (equal top, left, right, bottom) and change background color of that view.
I think first you should give different background colors to your ui views then place them. Under a single stack and check whether it is working or not
I have added a screenshot where i first gave background colors to UIviews and then placed them under one stackView but they had those colors unlike you after giving them background color simply from the uielements under the controller on the left pick the Uiviews and place them under stack View
Well, check your color please. 22 should not belong to [0,1].
basicInfoUIView.backgroundColor = UIColor.init(displayP3Red: 22.0 / 255.0, green: 22.0 / 255.0, blue: 22.0 / 255.0, alpha: 0.5)
Preface: I'm doing everything programmatically. 0 interface builder.
Previously, when pushing a VC onto a navVC stack, the pushed VC would have the upper edge occluded by the navbar. I want it so the top edge of the pushed VC is under the nav bar. I found that "edgesForExtendedLayout" did what I wanted to. Except Apple says:
"Instead of this property, use the safe area of your view to determine which parts of your interface are occluded by other content. For more information, see the safeAreaLayoutGuide and safeAreaInsets properties of UIView."
I have no idea how to translate the following code:
if let nextVC = getNextVC() {
nextVC.edgesForExtendedLayout = .init(rawValue: 0)
pushViewController(nextVC, animated: true)
}
To use safeAreaLayoutGuide or safeAreaInsets. I can't use constraints because the pushed view is not in the view hierarchy yet?
I've attached some images to give an idea of what I'm dealing with.
Green = border of UINavigation controller
Yellow = border of 'nextVC'
Red = border of table inside 'nextVC'
With edgesForExtendedLayout set to "none" - right, but changing value Apple says not to change:
With edgesForExtendedLayout set to "all" - wrong, but default value Apple says to keep:
I can change the tintColor for my App (everywhere) in a setting pane.
When I change the tintColor, and after that try to return to the default tint color, some buttons in NavBar don't return to blue, how can I handle this?
To verify:
- create a new project Master/Detail
- In the detail view: add Two buttons, named: "Red Interface" and "Blue interface"
- In DetailViewController, add the actions
#IBAction func tapRed(sender: AnyObject) {
view.window!.tintColor = UIColor.redColor()
}
#IBAction func tapBlue(sender: AnyObject) {
view.window!.tintColor = nil
}
Now run the application, create a timestamp, go to detail, tap redInterface, then blue interface
That's OK in the Detail View, but when you return to Master, the "+" button item is red, not blue.
I can fix the problem by setting a real blue color instead of nil, but that's not a long term solution, if Apple change the default tintColor.
Is this a bug? Is there something I can do to bypass this problem?
A quick workaround would be to fetch the default tint color once on the initial app load and store it somewhere (i.e. in the user defaults)
From Apple's iOS 7 UI Transition Guide (Specifically under the Using Tint Color section).
By default, a view’s tint color is nil, which means that the view uses its parent’s tint. It also means that when you ask a view for its tint color, it always returns a color value, even if you haven’t set one.
That's a good workaround!
In fact, I don't even need to store the color.
If I change to
#IBAction func tapBlue(sender: AnyObject) {
view.window!.tintColor = UIButton(type:UIButtonType.System).titleColorForState(.Normal)
}
That gives me the correct blue color, even if I changed the tintColor (probably because I don't address a button in the view hierarchy)
i would ask if it is possible to change to base modal window to look like my image? (only layout test)
I can easiliy set up an image with:
var barButtonImage:UIImage = UIImage(named: "header_test.png")
var barButtonImageView = UIImageView(image: barButtonImage)
self.navigationItem.titleView = barButtonImageView
But i am not able to set it outside the view - is that possible? And if, how?
EDIT:
Thanks for the info about using clipsToBounds. I set it to titleview and bar to false, but the image is not outside the modal (but it is over the top of my UITableView in the modal window)
self.navigationItem.titleView.clipsToBounds = false
self.navigationController.navigationBar.clipsToBounds = false
You're going to have to embed your visual stuff inside another view, with that view's background set to transparent.
Or, you could play around with the "clips subviews" property of your view, to allow the round graphic to not get clipped at the edges of the superview that contains it.
I'm took the Tabbar viewcontroller in this ,I added the 5 item and .I given the image insects is (24,0,0,6).
All button images are added in xib [under the Bar item -->image]Please help.
Thanks.
Adding to a similar answer here:
iOS Tab Bar icons keep getting larger
Not sure if this is an iOS7 bug but I've noticed that image insets need to be balanced.
You have specified insets for top and right but:
if you set a top inset, in order to balance it, you need to set the negative of it to the bottom inset
if you set a right inset, in order to balance it, you need to set the negative of it to the left inset
So, instead of having image insets like (24,0,0,6), use balanced image insets such as UIEdgeInsetsMake(24,-6,-24,6)
Doing so should protect your tabBarItem image from getting whacked on every tap.
If this doesn't suit your requirements, then redesign your tabBarItem image so you can have balance insets or... no insets at all.
Here's the workaround for a bug I've encountered with UITabBarController's UITabBar. If I tap a UITabBarItem once after it's selected, the icon shrinks. What I'd like to do is disable touches. UITabBarItem only has a setting for isEnabled, which grays it out if I set it to false...not what I was looking for.
I used a derivative of this answer to figure it out. With a UITabBarController with 3 tabs, printing tabBarController.subviews, I saw 3 UITabBarButtons and a UIBarBackground. The origin of UIBarBackground's frame was always (0, 0), putting it at the front of the sorted array, so I really don't need to know what the subview is, just "where it is" and whether it will always be there. The UIBarBackground is always going to be at the front of an array of tabBarController.subviews sorted by frame.minX, so I just need to remove it from the front.
Solution
Here's what the extension looks like:
extension UITabBarController {
var buttonViews: [UIView] {
var tabBarButtons = tabBar.subviews.sorted(by: {$0.frame.minX < $1.frame.minX})
tabBarButtons.removeFirst()
return tabBarButtons
}
}
I also created a struct in my Constants file, so I don't have to remember tab names:
struct TabBarItem {
static let firstTab = 0
static let secondTab = 1
static let thirdTab = 2
}
...and finally, where to use it:
In viewDidAppear (NOT viewDidLoad), add the following line to disable the UITabBarItem that you don't want to disable, but not gray out:
tabBarController?.buttonViews[TabBarItem.firstTab].isUserInteractionEnabled = false
In viewWillDisappear, re-enable the tab, as follows:
tabBarController?.buttonViews[TabBarItem.firstTab].isUserInteractionEnabled = true