How to fix iOS 15 tab bar transparent after scrolling to the bottom:
In iOS 15, UIKit has extended the usage of the scrollEdgeAppearance, which by default produces a transparent background.
Since I changed the tab bar color globally in my app, prior to iOS 15, I have added the following code to my AppDelegate:
UITabBar.appearance().barTintColor = "YOUR UITABBAR COLOR"
UITabBar.appearance().tintColor = "YOUR ICONS COLOR"
UITabBar.appearance().isTranslucent = true
To restore the old look, I had adopt the new UITBar appearance APIs, UITabBarAppearance. I changed my code to:
UITabBar.appearance().barTintColor = "YOUR UITABBAR COLOR"
UITabBar.appearance().tintColor = "YOUR ICONS COLOR"
UITabBar.appearance().isTranslucent = true
if #available(iOS 15.0, *) {
let appearance = UITabBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = "YOUR UITABBAR COLOR"
UITabBar.appearance().standardAppearance = appearance
UITabBar.appearance().scrollEdgeAppearance = UITabBar.appearance().standardAppearance
}
As a result, I get the original color of my UITabBar
With iOS 15, Apple adds the scrollEdgeAppearance property for configuring the appearance of the tab bar while edge scrolling.
https://developer.apple.com/documentation/uikit/uitabbar/3750912-scrolledgeappearance?changes=latest_minor
To fix the transparent tab bar, you should create a custom scroll edge appearance and set it to the tab bar.
if #available(iOS 15.0, *) {
let appearance = UITabBarAppearance()
appearance.backgroundEffect = UIBlurEffect(style: .light)
tabBar.scrollEdgeAppearance = appearance
}
Result:
init() {
if #available(iOS 15, *) {
let tabBarAppearance: UITabBarAppearance = UITabBarAppearance()
tabBarAppearance.configureWithOpaqueBackground()
UITabBar.appearance().standardAppearance = tabBarAppearance
UITabBar.appearance().scrollEdgeAppearance = tabBarAppearance
}
}
As explained by others, you have to enable and setup scrollEdgeAppearance property.
Here is how to do it on storyboard:
it will add an entire section of scroll edge appearance properties:
Related
I have some basic styles like:
"#foo": {
backgroundColor: '#ff0000', // red
}
"#foo[if=Alloy.Globals.isSmallHeight]": {
backgroundColor: '#0000ff', // blue
}
in alloy.js I have the following:
function pxToDp(px){
return px / (Titanium.Platform.displayCaps.dpi / 160);
}
var screenWidth;
var screenHeight;
if (Ti.Platform.name == "android") {
screenWidth = pxToDp(Ti.Platform.displayCaps.platformWidth);
screenHeight = pxToDp(Ti.Platform.displayCaps.platformHeight);
} else {
screenWidth = Ti.Platform.displayCaps.platformWidth;
screenHidth = Ti.Platform.displayCaps.platformHeight;
}
Alloy.Globals.isSmallHeight= screenHeight <= 545;
This basically means the background colour of #foo is blue if the screen height is less than or equal to 545dp, and red otherwise.
This usually works fine. However, there are times when the height of the screen can change during run-time. For example:
Screen Orientation Change
Multi window (on Android)
Adjusting the splitter position while in multi window mode (Android)
The issue with this is that the styles are not re-applied to take into account the new screen width and screen height.
For example, let's say there is a screen of size 600dp x 300dp in the portrait position. #foo will correctly have a background colour of red.
However, if the orientation changes, the screen size is now: 300dp x 600dp, but the #foo does not re-check the height a background colour, and thus is still red instead of blue.
A similar issue occurs when going into split screen.
Therefore my question is, how can I reapply styles when the screen dimensions changes?
Have a look at the dynamic styles section in the documentation
http://docs.appcelerator.com/platform/latest/#!/guide/Dynamic_Styling
http://docs.appcelerator.com/platform/latest/#!/guide/Dynamic_Styles
it will give you a basic idea on how to create style at runtime and apply them. You could do this inside the orientation change event
I have a status bar app which shows a green circle in the status bar and alternates to a red circle every 10 seconds. It does this by using item.view = icon1; and item.view = icon2; to change the image. Initialised like this:
let item = NSStatusBar.systemStatusBar().statusItemWithLength(-1);
self.icon1 = IconView(imageName: "icon1", item: item);
self.icon2 = IconView(imageName: "icon2", item: item);
When you click on the green or red circle, a popover view with some settings I have made appears fine.
The problem is at each 10 second interval when the item.view changes to either the red or the green, the popover view closes and requires the user to click the green or red button again to show it.
How can I make the popover persist though status bar image changes and only disappear once the user clicks the red or green button again?
Here is my awakeFromNib() for the popover view:
override func awakeFromNib()
{
let edge = NSMinYEdge
let icon = self.icon
let icon2 = self.icon2
let icon3 = self.icon3
let rect = icon.frame
let rect2 = icon2.frame
let rect3 = icon3.frame
icon.onMouseDown = {
if (icon.isSelected)
{
self.popover?.showRelativeToRect(rect, ofView: icon, preferredEdge: edge);
return
}
self.popover?.close()
}
icon2.onMouseDown = {
if (icon2.isSelected)
{
self.popover?.showRelativeToRect(rect2, ofView: icon2, preferredEdge: edge);
return
}
self.popover?.close()
}
icon3.onMouseDown = {
if (icon3.isSelected)
{
self.popover?.showRelativeToRect(rect3, ofView: icon3, preferredEdge: edge);
return
}
self.popover?.close()
}
}
}
You have the popover attached to a view that is later removed from the view hierarchy. Instead of assigning a new view to NSStatusItem each time, use a single view and change it's properties to show different states (i.e. change it's image property).
Alternatively you can create an empty NSView and assign it to NSStatusItem view property. Then you can add and show your icons inside that view as needed. Make sure to attach the popover to this empty view instead of individual icons.
Put a breakpoint inside the popover class dealloc method to see the stack trace. You'll get a hint of why this is happening from that stack trace.
I'm developing with Titanium Appcelerator for iOS. I would like to manage manually a 'back' button using the properties of window, that can set a left and right buttons.
I'm trying with this code:
var win = Titanium.UI.currentWindow;
win.backgroundColor = '#FFF';
var b = Titanium.UI.createButton({title:'Back'});
win.setLeftNavButton(b);
b.addEventListener('click', function()
{
win.close();
});
But no button is showed.
Swanand is right but i want to add some more thing that if you use modal property of window to open then also you can use setLeftNavButton method to set button in navigation bar but if you do not want to use tab group or navigation group or even modal property then you need to add that button in window with left,top,width and height property.
You can use below example....
var win = Titanium.UI.currentWindow;
win.backgroundColor = '#FFF';
var b = Titanium.UI.createButton({
title:'Back',
width : Ti.UI.SIZE,
height : Ti.UI.SIZE,
top : 10,
left : 10
});
win.add(b);
I'm having a problem when the in-call status bar it shows, I have tried.
navigationController = new UINavigationController ();
navigationController.NavigationBarHidden = true;
navigationController.View.AutosizesSubviews = true;
navigationController.View.AutoresizingMask = UIViewAutoresizing.FlexibleHeight|UIViewAutoresizing.FlexibleMargins|
UIViewAutoresizing.FlexibleTopMargin|UIViewAutoresizing.FlexibleBottomMargin;
navigationController.View.SizeToFit ();
window.RootViewController = navigationController;
window.RootViewController.View.AutosizesSubviews = true;
navigationController.View.AutoresizingMask = UIViewAutoresizing.FlexibleHeight|UIViewAutoresizing.FlexibleMargins|
UIViewAutoresizing.FlexibleTopMargin|UIViewAutoresizing.FlexibleBottomMargin;
but is still pushing bottom all views, hiding all buttons or controls at the bottom of the view, I also tried the same code in the Root View controller and doesn't work.
I'm using flexible UI for all controls this way:
btnContacts = IOTM.GUI.CreateButton ("MainMenu/btncontacts.png", 0f,Frame.Height - (Frame.Height * 0.225f), Frame.Width, (Frame.Height * 0.075f));
and I'm also hiding Navigation Bar
Can someone help me?
There is another way to auto resize view or detect changes in status bar to reload my views?
We have a parent Split view (NSSplitView), and two subviews, Content and SideBar (the sidebar is on the right).
What would be the optimal Cocoa-friendly way to toggle the SideBar view?
I would really love it, if the suggested solution includes animation
I really don't need any suggestions related to external plugins, etc (e.g. BWToolkit)
HINT : I've been trying to do that, but still I had issues hiding the divider of the NSSplitView as well. How could I do it, while hiding it at the same time?
Here's a pretty decent tutorial that shows how to do this: Unraveling the Mysteries of NSSplitView.
Hiding the divider is done in NSSplitView's delegate method splitView:shouldHideDividerAtIndex:.
You will have to animate the frame size change yourself if you don't like the way NSSplitView does it.
Easiest way to do it is as follows - and it's animated: [SWIFT 5]
splitViewItems[1].animator().isCollapsed = true // Show side pane
splitViewItems[1].animator().isCollapsed = false // hide side pane
I wrote a Swift version of the content in the link from #Nathan's answer that works for me. In the context of my example splitView is set elsewhere, probably as an instance property on an encompassing class:
func toggleSidebar () {
if splitView.isSubviewCollapsed(splitView.subviews[1] as NSView) {
openSidebar()
} else {
closeSidebar()
}
}
func closeSidebar () {
let mainView = splitView.subviews[0] as NSView
let sidepanel = splitView.subviews[1] as NSView
sidepanel.hidden = true
let viewFrame = splitView.frame
mainView.frame.size = NSMakeSize(viewFrame.size.width, viewFrame.size.height)
splitView.display()
}
func openSidebar () {
let sidepanel = splitView.subviews[1] as NSView
sidepanel.hidden = false
let viewFrame = splitView.frame
sidepanel.frame.size = NSMakeSize(viewFrame.size.width, 200)
splitView.display()
}
These functions will probably methods in a class, they are for me. If your splitView can be nil you obviously have to check for that. This also assumes you have two subviews and the one at index 1, here as sidePanel is the one you want to collapse.
In Xcode 9.0 with Storyboards open Application Scene select View->Menu->Show sidebar. CTRL-click Show Sidebar, in sent actions delete the provided one, click on x. From the circle CTRL drag to First Responder in application scene and select toggleSideBar to connect to. Open storyboard and select the first split view item and in attributes inspector change behaviour from default to sidebar. Run and try with view menu item show/hide. All done in interface builder no code. toggleSideBar handles the first split view item. https://github.com/Dis3buted/SplitViewController
I got some artifacts with the code above, likely because it was out of context. I am sure it works where it was meant to. Anyway, here is a very streamlined implementation:
// this is the declaration of a left vertical subview of
// 'splitViewController', which is the name of the split view's outlet
var leftView: NSView {
return self.splitViewController.subviews[0] as NSView
}
// here is the action of a button that toggles the left vertical subview
// the left subview is always restored to 100 pixels here
#IBAction func someButton(sender: AnyObject) {
if splitViewController.isSubviewCollapsed(leftView) {
splitViewController.setPosition(100, ofDividerAtIndex: 0)
leftView.hidden = false
} else {
splitViewController.setPosition(0, ofDividerAtIndex: 0)
leftView.hidden = true
}
}
To see a good example using animations, control-click to download this file.
If your NSSplitView control is part of a NSSplitViewController object, then you can simply use this:
splitViewController.toggleSidebar(nil)