UIview kept going at the bottom of the UIViewcontroller - swift

My LoginViewController has a UIView that has 2 UItextfield and 1 UIbutton. The moment the user start writting the UIView should go up and leave space for the keyboard. However my problem is when the keyboard disappear the UIView did not go at its initial position. Can anyone help me please Thank you ... (my code is below)
func keyboardON(sender: NSNotification) {
let info = sender.userInfo!
var keyboardSize = info[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue().size
println("keyboard height \(keyboardSize.height)")
var frame = otherContainerView.frame
println("MainScreen :\(UIScreen.mainScreen().bounds.height)")
frame.origin.y = UIScreen.mainScreen().bounds.height - keyboardSize.height - frame.size.height
otherContainerView.frame = frame
}
func keyboardNotOn(sender: NSNotification) {
let info = sender.userInfo!
var keyboardSize = info[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue().size
println("keyboard height \(keyboardSize.height)")
var frame = otherContainerView.frame
frame.origin.y = UIScreen.mainScreen().bounds.height - frame.size.height
otherContainerView.frame = frame
}

I would suggest that you change this view controller to a UITableViewController with static cells. When using a UITableViewController, the scrolling is automatically handled, thus making your problem not problem at all.
If I understand your initial question correctly, you are trying to create a login screen in a UIViewController, which is fine, but much harder than it would be to simply create a UITableViewController. The image above was made with a UITableViewController. When the text fields are selected, it slides up, and when they are deselected, it moves back to it's initial view. If you switch to a UITableViewController, (even if you place both UITextFields and the button in one cell), you won't need to do any of this programmatically. The storyboard will handle the desired changes.
import UIKit
class LoginTableViewController: UITableViewController {
#IBOutlet weak var usernameTextField : UITextField!
#IBOutlet weak var passwordTextField : UITextField!
#IBAction func login (sender: UIButton) {
//login button
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//If you choose to use 3 cells in your storyboard (like I've done with my login screen) you will return 3 here. If you choose to put all of the items in one cell, return 1 below.
return 3
}
}

Related

scroll view content offset non responsive in viewDidLoad

scrollView.contentOffset does work properly inside button func but the same code is non responsive in the viewDidLoad func
#IBOutlet weak var scrollView: UIScrollView!
#IBAction func scrollBtn(_ sender: UIButton) {
scrollView.contentOffset.x = 200
}
override func viewDidLoad() {
super.viewDidLoad()
scrollView.contentOffset.x = 200
}
i am trying to change the initial position of the scroll view
Try using it in viewWillAppear or viewDidAppear. May be the reason behind it is not working in viewDidLoad is that the view has not get rendered at the time the viewDidLoad invoked.

How would I go about adding a uiview vertically above a uiview within an inputAccessoryView?

I'm trying to add a uiview containing multiple buttons, above my current input accessory view. My current input accessory view is a growing textField (like iOS standard Text Message app).
class ViewController: UIViewController {
let textInputBar = ALTextInputBar()
// The magic sauce
// This is how we attach the input bar to the keyboard
override var inputAccessoryView: UIView? {
get {
return textInputBar
}
}
// Another ingredient in the magic sauce
override func canBecomeFirstResponder() -> Bool {
return true
}
}
Example of what I'm trying to do, the app (Facebook Messenger) has a growing textfield or textinput, and in this case, an bar of buttons bellow.
My current view, as mentioned earlier.
try this code
class ViewController: UIViewController {
#IBOutlet weak var myTextField: UITextField!
var textInputBar:UIView = ALTextInputBar()// if it is a uiview type
override func viewDidLoad() {
super.viewDidLoad()
myTextField.inputAccessoryView = textInputBar
}
}

UIView is always behind UITableView

I have a UIViewController (not a UITableViewController because I read that a view controller is best for this kind of behaviour) with a UITableView. In this view controller I want to add a floating UIView and place it above my tableview, to do so I wrote:
public override func viewDidLoad() {
super.viewDidLoad()
// add button
let fbv = liquidActionButtonInstance.addActionButton() // this is a UIView
self.view.addSubview(fbv)
liquidActionButtonInstance.delegate = self
// delegate
tableView.delegate = self
tableView.dataSource = self
}
However my floating view appears behind my UITableView, how can I add it as the first child of self.view? I've used
self.view.addSubview(fbv)
self.view.bringSubviewToFront(fbv)
Among others and none seems to work.
Edit:
I added some screenshots of my view's hierarchy.
Edit 2:
Here I put a little more code:
My ViewController without some unrelated code:
public class ActividadesTableViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var descripcionFiltrosLabel: UILabel!
#IBOutlet weak var filtrosLabelBottomConstraint: NSLayoutConstraint!
#IBOutlet weak var filtrosLabelTopConstraint: NSLayoutConstraint!
#IBOutlet weak var tableViewTopConstraint: NSLayoutConstraint!
private var liquidActionButtonInstance: FloatingActionButton = FloatingActionButton()
public var viewModel : ActividadesTableViewModeling?
public override func viewDidLoad() {
super.viewDidLoad()
// Agregar action button
self.view.insertSubview(liquidActionButtonInstance.addActionButton(),aboveSubview: tableView)
liquidActionButtonInstance.delegate = self
// set row's height
tableView.estimatedRowHeight = 70
tableView.rowHeight = UITableViewAutomaticDimension
// delegate
tableView.delegate = self
tableView.dataSource = self
// load tableview data
if let viewModel = viewModel {
viewModel.loadActividades(withFilters: nil)
}
}
}
// MARK: FloatingButton
extension ActividadesTableViewController: FloatingActionButtonDelegate {
public func performSegueFromFloatingActionButton(segueName name: String) {
performSegueWithIdentifier(name, sender: self)
}
}
// MARK: TableView
extension ActividadesTableViewController: UITableViewDataSource, UITableViewDelegate {
public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Omitting this code, just mentioning the methods
}
public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ActividadCell", forIndexPath: indexPath) as! ActividadTableViewCell
if let viewModel = viewModel {
cell.viewModel = viewModel.cellModels.value[indexPath.row]
} else {
cell.viewModel = nil
}
return cell
}
public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
}
And this is how I add the button (in a different class):
func addActionButton() -> LiquidFloatingActionButton {
let createButton: (CGRect, LiquidFloatingActionButtonAnimateStyle) -> LiquidFloatingActionButton = { (frame, style) in
let floatingActionButton = LiquidFloatingActionButton(frame: frame)
floatingActionButton.animateStyle = style
floatingActionButton.dataSource = self
floatingActionButton.delegate = self
floatingActionButton.color = ColoresKairos.principal2
return floatingActionButton
}
let cellFactory: (String) -> LiquidFloatingCell = { (iconName) in
return LiquidFloatingCell(icon: UIImage(named: iconName)!)
}
cells.append(cellFactory("iphone-action-button-group"))
cells.append(cellFactory("iphone-action-button-notepad"))
cells.append(cellFactory("iphone-action-button-check-box"))
let floatingFrame = CGRect(x: UIScreen.mainScreen().bounds.width - 56 - 16, y: UIScreen.mainScreen().bounds.height - 56 - 16, width: 56, height: 56)
let bottomRightButton = createButton(floatingFrame, .Up)
//view.addSubview(bottomRightButton)
//return view
return bottomRightButton
}
You need to add the view using addSubview(_:) AND bringToFront(_:). You can also try sending the tableView to the back using sendToBack(_:)
In your document outline menu in your storyboard, you can place your floating view below your TableView in view hierarchy. Then, you can always see your floating view placed above your tableview.
It's gonna be like this.
▼ Your ViewController
Top Layout Guide
Bottom Layout Guide
▼View
▶︎ TableView
▶︎ Floating View
Below is the code that is working along with its screenshot, I suspect that your call liquidActionButtonInstance.addActionButton() returns an empty button?
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
private var liquidButton: LiquidFloatingActionButton?
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
// Setting up the liquid button
liquidButton = createLiquidButton()
view.addSubview(liquidButton!)
}
func createLiquidButton() -> LiquidFloatingActionButton {
let frame = CGRect(x: UIScreen.mainScreen().bounds.width - 56 - 16, y: UIScreen.mainScreen().bounds.height - 56 - 16, width: 56, height: 56)
let button = LiquidFloatingActionButton(frame: frame)
button.animateStyle = .Up
button.color = UIColor.redColor()
return button
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
// UITableView Implementation, not included not relevent for the example.
}
The error here, after debugging the view hierarchy was that my tableView wasn't being added directly to the UIViewController's hierarchy, so it was added above everything else, and adding my FloatingButton as a subview of UIViewController always resulted on it being hidden by my tableView.
My tableView is added via storyboard, and as far as I know this is not the expected behaviour, but in my case just adding the following lines:
self.view.addSubview(tableView)
self.view.addSubview(liquidActionButtonInstance.addActionButton())
Solved my problem.

Scrolling Delegate in TableView

I want to make an animation like this link:
https://www.pinterest.com/pin/420523683937443901/sent/?sender=335307272165049646&invite_code=f63f81c77d28a48e6181db7df90b423a
Here is my simple screenshot:
In my case, I want when I swiping up, the blue Header View will disappear and the navigation bar will change to blue color.
Here is my code:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
#IBOutlet var headerView: UIView!
var dataSource: [String] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].map {"\($0)"}
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
headerView.backgroundColor = UIColor.blueColor()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel!.text = dataSource[indexPath.row]
return cell
}
}
I can change the views with animation like this, include: Navigation Bar, Header View of TableView, Status Bar.
But how to check when the TableView scroll down, then the Header View will change.
You must use UIScrollViewDelegate in your tableView to intercept scrollView actions with:
class YourClass: YourType, UIScrollViewDelegate {}
Check the official apple documentation
You can handle scrollview looking for scrollViewDidScroll(_:) method.
This is just an example to add more network data when the user scroll to the end, you can use it to trigger your header animation..
let threshold = 100.0 // threshold from bottom of tableView
var isLoadingMore = false // flag
func scrollViewDidScroll(scrollView: UIScrollView) {
let contentOffset = scrollView.contentOffset.y
let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height;
if !isLoadingMore && (maximumOffset - contentOffset <= threshold) {
// Get more data - API call
self.isLoadingMore = true
// Update UI
dispatch_async(dispatch_get_main_queue()) {
tableView.reloadData()
self.isLoadingMore = false
}
}
}
UPDATE:
By analizying your animation, it's not simple but not impossible :)
I can see two different states:
And the second state:
You can organize your controller by choose a UIViewController type.
This UIViewController must be composed by:
-UINavigationController (as you can see on the top of the images , choose if you want to embedded it or link a navigation controller and set your viewController as the navigation
rootViewController)
-UIPageView (you can use in your main viewController with the UIPageViewControllerDataSource and UIPageViewControllerDelegate, pay attention to the dimension , it cover the 30% of the top of your controller)
-UITableView (this is the last layout part, everytime page scroller the datasource can be changed and refreshed to the table)
P.S. The tableViewHeader can be the gray label with the date: Thursday 21 January 2016, as you can see the dimension dont change during animation.

Getting nil value on textview and button

Hello im am making an app where the user can press a button and a random link shows upp. I have in the textfile tried to name blblbl.delegate = self but when running the code it suddenly says that all of my textview and buttons has the value of nil.
class ViewController: UIViewController, UITextViewDelegate,
NSObjectProtocol {
#IBOutlet weak var firstbutton: UIButton!
#IBOutlet weak var firsttextview: UITextView!
let links = ["http://www.google.com","http://www.yahoo.com",
"http://www.discovery.com"]
var currentLinkIndex : Int = 0
override func viewDidLoad() {
Firsttextview.delegate = self
configureTextView()
super.viewDidLoad()
}
func configureTextView() {
func textView(firsttextview: UITextView!, shouldInteractWithURL
URL:
NSURL, inRange characterRange: NSRange) -> Bool {
let url = NSURL(string:links[currentLinkIndex])
UIApplication.sharedApplication().openURL(url!)
return false
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func firstaction(sender: UIButton) {
let random : Int = Int(arc4random()) % 3
Firsttextview.text = links[random]
currentLinkIndex = random
}
}
How do a solve this problem? Does i some how have to give the textview and button a value! Thanks in advance!
I guess you need to change :
Firsttextview.delegate to firsttextview.delegate and
Firsttextview.text = links[random] to firsttextview.text = links[random]
I tried to recreate your example by :
Creating a button in the storyboard
Creating the textview in the storyboard
Create + drag and drop to my ViewController Class the IBOutlet firstbutton from the button in the storyboard
Create + drag and drop to my ViewController Class the IBOutlet firsttextview from the textview in the storyboard
Create + drag and drop to my ViewController Class the IBAction firstaction from the button in the storyboard
If the button and the label are created in the storyboard, they don't need to be initialized in your code.
By doing this, your code worked for me.