Shrink UITableView -> Black Background - ios

I create a UIDatePicker outside of the screen and when a button is pressed, I want it to slide into the screen (from below).
To give it enough place, I want the UITableView (inside UITableViewController) to shrink over the y-axis.
It kind of works, but the shrinking of the UITableView reveals a black background, so that the UIDatePicker is not shown. How can I fix that?
It looks like this:
import UIKit
class jSONTableViewController: UITableViewController {
#IBAction func viewDatePicker(sender: UIButton) {
// Create DatePicker
let datePicker = UIDatePicker()
datePicker.center.y = self.view.bounds.height+100
datePicker.backgroundColor = UIColor.whiteColor()
datePicker.datePickerMode = UIDatePickerMode.Date
self.view.insertSubview(datePicker, aboveSubview: self.view)
// Animate View
UIView.animateWithDuration(0.5, delay: 0, options: .CurveEaseInOut, animations: { () -> Void in
let heightOfDatepicker = datePicker.frame.height
datePicker.center.y = self.view.frame.height-(heightOfDatepicker)
self.tableView.frame = CGRectMake( self.tableView.frame.origin.x, self.tableView.frame.origin.x, self.tableView.frame.size.width, self.tableView.frame.height-heightOfDatepicker)
}, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

You are using a UITableViewController where the super view is the table view. So when you resize the table view you also rezise the super view which shows the window's background.
You can create a UIViewController and add a table view as a subview, you'll need conform to UITableViewDelegate and UITableViewDataSource too.

I think your best bet would be to use the first responder to bring up a picker from the bottom. Most of this is all done for you, you just need to do some wiring. This gives you the equivalent of how the keyboard works but with your picker instead and optional buttons.
Discussion here today on how best to do this: Add buttons to UIPickerView - Swift 1.2
This has some swift code you can perhaps just lift and use.

Related

UIStackView show/hide animation is not working properly

I'm using UIStackView and it contains 3 UIView instances, which has fixed height
I'm trying to hide these subviews by clicking button
first and second view show/hide well with proper animation
but last view doesn't animate
class ViewController: UIViewController {
private var flag: Bool = true
#IBOutlet weak var targetView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func buttonDidTapped(_ sender: Any) {
flag = !flag
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
self.targetView.isHidden = !self.flag
}
}
}
The issue is the way stack views change their frames when hiding an arranged subview.
Easiest way to see what's happening:
set your Green view to Alpha: 0.5
toggle .isHidden on the Blue view
You'll see that the 50% translucent Green view "slides up over" the Blue view... the Blue view does not "shrink in height" during the animation.
To solve your specific issue, set Clips To Bounds to true on your stack view. Now, when you toggle .isHidden on your Green view, the animation will look correct.
That will not change the "slide over" appearance if you have translucent views, but that's a different issue.
As a side note, you can simplify your code and get rid of the flag like this:
UIView.animate(withDuration: 0.5) {
// not needed
//self.view.layoutIfNeeded()
self.targetView.isHidden.toggle()
}
Try change your code from:
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
self.targetView.isHidden = !self.flag
}
to:
self.targetView.isHidden = !self.flag
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
Looks like you animate before change.

How to set the status bar height to 20pt when on a call like the App Store does?

When on a phone call while in the iOS App Store the status bar changes from 40pt tall to 20pt tall when reading an article. How do I do this in my app?
this is really an interesting question, took me sometimes to figure it out.
if you notice app store in such viewcontroller didn't have a status bar, which means the green bar should not be shown at all. this is the first hint.
you can access the status bar by UIApplication.shared.value(forKey: "statusBarWindow") as! UIWindow
according to point number one this means the status bar is not hidden but actually its statusBarWindow.frame.origin.y just shifted up.
please not you need to handle iPhone x separately
please make sure the status bar is not hidden
note that this is not the only right way, right now you have the view itself, you can change the origin or size or even try to get what inside this view and hide them or change their frames too etc.
here is an example how you can do it.
class ViewController: UIViewController {
var isHidden:Bool = false
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 0.5) { () -> Void in
let statusBarWindow = UIApplication.shared.value(forKey: "statusBarWindow") as! UIWindow
statusBarWindow.frame = CGRect(x: 0, y: -20, width: statusBarWindow.frame.size.width, height: 40.0)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override var prefersStatusBarHidden: Bool{
return isHidden
}
}
also attached an image with the result of this code, hopefully, this answer work for you too.

UINavigation with UITextField as subview

I want to make UI like following,
I tried to increase the height of UINavigationController like
[self.navigationController.navigationBar setFrame:CGRectMake(0, 0, 320, 110)];
but navigation title and BarButtonItem appears down.
i can not add hide navigation as i am using third party side menu which uses Left BarButtonItem.
i can very well keep navigation as it is and below i have added uiview as subview with same background colour as that of navigation but there is fine line appears in between...:(
You can't increase height of UINavigationBar. Add an UIView with those elements just below the UINavigationBar.
Then there will be extra line below UINavigationBar. You can remove that line. Refer How to hide iOS7 UINavigationBar 1px bottom line
or else use this code(I have just copied it from that link in swift, convert it to Objective-C)
import UIKit
class ViewController: UIViewController {
private var shadowImageView: UIImageView?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if shadowImageView == nil {
shadowImageView = findShadowImage(under: navigationController!.navigationBar)
}
shadowImageView?.isHidden = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
shadowImageView?.isHidden = false
}
private func findShadowImage(under view: UIView) -> UIImageView? {
if view is UIImageView && view.bounds.size.height <= 1 {
return (view as! UIImageView)
}
for subview in view.subviews {
if let imageView = findShadowImage(under: subview) {
return imageView
}
}
return nil
}
}
This is the result
Actually you cant change height of UINavigationBar. Your actual ViewController's view will start from 64 pixel from TopLayoutGuide (Vertical Space)
Status Bar Height is 20 Pixel
Navigation Bar Height is 44 Pixel
So to design such UI, simply do these steps
Hide NavigationBar on that view controller like
self.navigationController.navigationBarHidden = YES;
self.navigationItem.hidesBackButton = YES;
Then add View from storyboard with vertical space as 0 from TopLayoutGuide. And design it as per your requirement. So you can
simply give this look and handle it using IBOutlets and IBActions
for each item
Also you can add UILable to show title of screen.
You can't increase the size of the UINavigationBar. That is of standard size 44 (Nav Height) + 20 (size of the status bar). Here you've two options to achieve.
First, by adding menu, dashboard title label & notification icon to the UINavigationBar. Add Jobs, Conditions, and Interview as a separate view below to navigation bar.
Second by customizing the entire view, as mentioned by #Pushkraj i.e, by hiding the current Navigation Bar and adding your own view which contains all the UI elements.

Show a view as a swipe up gesture in front of another view

Hello I am developing app which has UI like below images..
I am not able to understand how to create bottom swipe up view.
I have tried swipe up gesture on bottom view to open it.
But I want to open bottom view with finger (means slow upward drag of view should reveal bottom view slowly)
I am using auto layout and storyboard. How do I achieve this ?
I have searched a lot and I got this https://github.com/crocodella/PullableView but I am not able to add this view with storyboard and auto layout.
I Just want say before solution is that this is not gonna be drag like effect for that you need to use gesture...but It gives you similar effect if you strongly need it with button click.. I think its not what you want but this give you an option if you want
For drag bottom view to top,you shold use gesture and this may help you
Drag Down UIView in iOS 5
or this
http://www.jondev.net/articles/Dragging_View_with_Finger_(iPhone)
You got the similar effect using constant property of constraints..like Give the height constraint to bottom view and use constant property on click event to swipe up and down.
Still confused!!! Here is the solution
UI setup
Constraints Setup
After that You just need to make some outlets and click event of button...
make an outlet of height constraint of bottom view
make an outlet of button to change its title to up/down
make and click event of button
After this procedure you need to code on button action, So here is that code
class ViewController: UIViewController {
// Button outlet
#IBOutlet weak var btnUp: UIButton!
// Height Constraint outlet
#IBOutlet weak var constHeightBottomView: NSLayoutConstraint!
// Boolean property to handle click
var clicked = true
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func btnUpClicked(sender: UIButton) {
if clicked{
self.clicked = !clicked
UIView.animateWithDuration(0.2, animations: {
self.btnUp.setTitle("Down", forState: .Normal)
self.constHeightBottomView.constant = 200
self.view.layoutIfNeeded()
})
}
else{
self.clicked = true
UIView.animateWithDuration(0.2, animations: {
self.btnUp.setTitle("Up", forState: .Normal)
self.constHeightBottomView.constant = 0
self.view.layoutIfNeeded()
})
}
}
}
and the output of this work would be

TableView Showing Behind Tab Bar

I am updating my app to use iOS 7 and I'm having a problem with a table view. My tab bar is translucent. The problem is when I scroll to the bottom of my table view, part of the last cell is still behind the tab bar. I'd like to have a bit of space between the last cell and the tab bar. I could fix this by using an opaque tab bar instead, but I want to keep it translucent.
Try setting
self.edgesForExtendedLayout = UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars = NO;
self.automaticallyAdjustsScrollViewInsets = NO;
Inside the tableview controller
Swift 4.x
let adjustForTabbarInsets: UIEdgeInsets = UIEdgeInsetsMake(0, 0, self.tabBarController!.tabBar.frame.height, 0)
self.yourTableView.contentInset = adjustForTabbarInsets
self.yourTableView.scrollIndicatorInsets = adjustForTabbarInsets
Check the screen shot
Check the under top Bar and Un-checke under Bottom Bar
SWIFT 3
put this inside viewDidLoad of your tableViewController:
self.edgesForExtendedLayout = UIRectEdge()
self.extendedLayoutIncludesOpaqueBars = false
self.automaticallyAdjustsScrollViewInsets = false
Swift 3.0
This is what worked for me. In your Custom ViewController:
override func viewDidLoad() {
super.viewDidLoad()
let adjustForTabbarInsets: UIEdgeInsets = UIEdgeInsetsMake(self.tabBarController!.tabBar.frame.height, 0, 0, 0);
//Where tableview is the IBOutlet for your storyboard tableview.
self.tableView.contentInset = adjustForTabbarInsets;
self.tableView.scrollIndicatorInsets = adjustForTabbarInsets;
}
Not to sure I like the solution but it works for me.
With iOS 11 I have no issue, I simply use the following in viewDidLoad():
self.collectionView.bottomAnchor.constraint(self.view.safeAreaLayoutGuide.bottomAnchor).isActive = true
However on iOS 10 I need to hack my way like this:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let tabBarHeight: CGFloat = (self.parent?.tabBarController?.tabBar.frame.size.height)!
if #available(iOS 11.0, *) {
} else {
self.collectionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -tabBarHeight).isActive = true
}
}
This is working for me
override func viewDidLoad() {
self.edgesForExtendedLayout = UIRectEdge()
self.extendedLayoutIncludesOpaqueBars = false
}
If any view shows behind a UITabBar you can grab the bottomLayoutGuide and make adjustments at runtime. What I do is have a BaseViewController that all my view controllers inherit from. Then if the tab bar is visible we adjust the view like so:
import UIKit
class BaseVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidLayoutSubviews() {
//Ensures that views are not underneath the tab bar
if tabBarController?.tabBar.hidden == false {
var viewBounds = self.view.bounds;
var bottomBarOffset = self.bottomLayoutGuide.length;
self.view.frame = CGRectMake(0, 0, viewBounds.width, viewBounds.height - bottomBarOffset)
}
}
}
Since I don't use storyboards (where you can click a checkbox in IB to fix this problem), this has been the best solution I have found.
It is really hard to resolve the issue without detail information or actual codes. I have similar issue of tabview behind UItabBar in my project. The solutions offered here do not work in my case. After exploring my codes, I found a solution for my case.
Here is brief explanation of my case. I have a UItabBar in main view with two tab buttons. In one tab view, there is table view. If user taps on a row, a detail view is presented by using navigation controller. In the detail view, the tab bar is hidden, and a toolbar is showing at the bottom.
In order to bring tab bar back and hide the toolbar when the main view is brought back, I have to explicitly show tab bar and hide toolbar in the event of viewWillAppear:
class myMainViewController: UITableViewController {
private var tabBarHidden: Bool? = {
didSet {
self.tabBarController?.tabBar.isHidden = tabBarIsHidden ?? true
}
}
private var toolBarIsHidden: Bool? {
didSet {
let hidden = toolBarIsHidden ?? true
self.navigationController?.toolbar.isHidden = hidden
self.navigationController?.setToolbarHidden(hidden, animated: true)
}
}
...
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarIsHidden = false
self.toolBarIsHidden = true
}
...
}
I finally realize that the visibility of bar at the bottom is set in the event of viewWillAppear. At that time, the tableView or scroll view's content insets are set already based on no bar at the bottom. That's why my tableView is behind the bottom bar.
The solution I found is to reset content insets in the event of viewDidAppear:
override func viewDidAppear(_ animated: Bool) {
// In the event of viewWillAppear, visibilities of tool bar and tab bar are set or changed,
// The following codes resets scroll view's content insets for tableview
let topInset = self.navigationController!.navigationBar.frame.origin.y +
self.navigationController!.navigationBar.frame.height
let adjustForTabbarInsets: UIEdgeInsets = UIEdgeInsetsMake(
topInset, 0,
self.tabBarController!.tabBar.frame.height, 0)
self.tableView.contentInset = adjustForTabbarInsets
self.tableView.scrollIndicatorInsets = adjustForTabbarInsets
}
The best approch would be to Embed TabBarController to your ViewController (Editor -> Embed In -> TabBar Controller)and set the bottom of the tableview to be bottom of safe area of viewcontroller. The other ways wont be as perfect as this one.
You need to adjust the height of the table view. Just leave 49px at the bottom, as the tabbar height is 49 px. Adjust the height of table view so that it leaves 49px space below it.

Resources