I got this transition issue with iOS 9, I've attached a GIF below.
It looks like the custom textView is presuming x-axis of the tab bar top before segue and then settling to its original position.
However there's no issue with iOS 11, but same with iOS 10.
I also suspect this might be caused by the push segue, since it transitions fine with the other kinds of segue (without any height settling glitch).
I'm using Auto-layout. The comment textView is pinned to buttom of superView. Any tip would be highly appreciated.
Here's the code that's dismissing UITabBar on push.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "previewVC" {
let destinationController = segue.destination as! PostViewController
destinationController.hidesBottomBarWhenPushed = true
}
}
Try another solution.
Use Your text as input accessory view of UIViewController so remove that bottom view from storyboard
Add Following in your view controller
var viewAcc: UIView?
var sendButton: UIButton!
var inputTextField: UITextField!
override var inputAccessoryView: UIView? {
return viewAcc
}
override var canBecomeFirstResponder: Bool {
return true
}
In View Did load method add following code
Note:Please change constraints according to your requirement
viewAcc = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44))
viewAcc?.backgroundColor = UIColor.white
inputTextField = UITextField (frame: CGRect(x:8, y:0, width:UIScreen.main.bounds.width, height: 44 ))
inputTextField.inputAccessoryView = nil
inputTextField.delegate = self as? UITextFieldDelegate
inputTextField.placeholder = "Enter message..."
viewAcc?.backgroundColor = .white
viewAcc?.addSubview(inputTextField);
let topBorderView = UIView()
topBorderView.backgroundColor = UIColor(white: 0.5, alpha: 0.5)
viewAcc?.addSubview(topBorderView)
viewAcc?.addConstraintsWithFormat(format: "H:|[v0]|", views: topBorderView)
viewAcc?.addConstraintsWithFormat(format: "V:|[v0(0.5)]", views: topBorderView)
sendButton = UIButton(type: .system)
sendButton.isEnabled = true
sendButton.titleLabel?.font = UIFont.systemFont(ofSize: 16)
sendButton.setTitle("Send", for: .normal)
sendButton.contentEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
sendButton.addTarget(self, action: #selector(handleSend), for: .touchUpInside)
viewAcc?.addSubview(sendButton)
inputTextField.translatesAutoresizingMaskIntoConstraints = false
sendButton.translatesAutoresizingMaskIntoConstraints = false
viewAcc?.addConstraint(NSLayoutConstraint(item: inputTextField, attribute: .left, relatedBy: .equal, toItem: viewAcc, attribute: .left, multiplier: 1, constant: 8))
viewAcc?.addConstraint(NSLayoutConstraint(item: inputTextField, attribute: .top, relatedBy: .equal, toItem: viewAcc, attribute: .top, multiplier: 1, constant: 7.5))
viewAcc?.addConstraint(NSLayoutConstraint(item: inputTextField, attribute: .right, relatedBy: .equal, toItem: sendButton, attribute: .left, multiplier: 1, constant: -2))
viewAcc?.addConstraint(NSLayoutConstraint(item: inputTextField, attribute: .bottom, relatedBy: .equal, toItem: viewAcc, attribute: .bottom, multiplier: 1, constant: -8))
viewAcc?.addConstraint(NSLayoutConstraint(item: sendButton, attribute: .right, relatedBy: .equal, toItem: viewAcc, attribute: .right, multiplier: 1, constant: 0))
viewAcc?.addConstraint(NSLayoutConstraint(item: sendButton, attribute: .bottom, relatedBy: .equal, toItem: viewAcc, attribute: .bottom, multiplier: 1, constant: -4.5))
As your text view is not subview of view controller so it will work as expected
EDIT IPHONE X SUPPORT
lazy var viewAcc: SafeAreaInputAccessoryViewWrapperView = {
return SafeAreaInputAccessoryViewWrapperView(for: button)
}()
Hope it is helpful
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
What is this UI name?
It's just like a sticking on the keyboard...
and like a messenger apps UITextField...
I don't know this UI name.
What is that?
This is done with input accessory view of UIViewController
Use Your text as input accessory view of UIViewController so remove that bottom view from storyboard
Add Following in your view controller
var viewAcc: UIView?
var sendButton: UIButton!
var inputTextField: UITextField!
override var inputAccessoryView: UIView? {
return viewAcc
}
override var canBecomeFirstResponder: Bool {
return true
}
In View Did load method add following code
Note:Please change constraints according to your requirement
viewAcc = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44))
viewAcc?.backgroundColor = UIColor.white
inputTextField = UITextField (frame: CGRect(x:8, y:0, width:UIScreen.main.bounds.width, height: 44 ))
inputTextField.inputAccessoryView = nil
inputTextField.delegate = self as? UITextFieldDelegate
inputTextField.placeholder = "Enter message..."
viewAcc?.backgroundColor = .white
viewAcc?.addSubview(inputTextField);
let topBorderView = UIView()
topBorderView.backgroundColor = UIColor(white: 0.5, alpha: 0.5)
viewAcc?.addSubview(topBorderView)
viewAcc?.addConstraintsWithFormat(format: "H:|[v0]|", views: topBorderView)
viewAcc?.addConstraintsWithFormat(format: "V:|[v0(0.5)]", views: topBorderView)
sendButton = UIButton(type: .system)
sendButton.isEnabled = true
sendButton.titleLabel?.font = UIFont.systemFont(ofSize: 16)
sendButton.setTitle("Send", for: .normal)
sendButton.contentEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
sendButton.addTarget(self, action: #selector(handleSend), for: .touchUpInside)
viewAcc?.addSubview(sendButton)
inputTextField.translatesAutoresizingMaskIntoConstraints = false
sendButton.translatesAutoresizingMaskIntoConstraints = false
viewAcc?.addConstraint(NSLayoutConstraint(item: inputTextField, attribute: .left, relatedBy: .equal, toItem: viewAcc, attribute: .left, multiplier: 1, constant: 8))
viewAcc?.addConstraint(NSLayoutConstraint(item: inputTextField, attribute: .top, relatedBy: .equal, toItem: viewAcc, attribute: .top, multiplier: 1, constant: 7.5))
viewAcc?.addConstraint(NSLayoutConstraint(item: inputTextField, attribute: .right, relatedBy: .equal, toItem: sendButton, attribute: .left, multiplier: 1, constant: -2))
viewAcc?.addConstraint(NSLayoutConstraint(item: inputTextField, attribute: .bottom, relatedBy: .equal, toItem: viewAcc, attribute: .bottom, multiplier: 1, constant: -8))
viewAcc?.addConstraint(NSLayoutConstraint(item: sendButton, attribute: .right, relatedBy: .equal, toItem: viewAcc, attribute: .right, multiplier: 1, constant: 0))
viewAcc?.addConstraint(NSLayoutConstraint(item: sendButton, attribute: .bottom, relatedBy: .equal, toItem: viewAcc, attribute: .bottom, multiplier: 1, constant: -4.5))
Goto Storyboard select your tableview and set keyboard dismiss mode to interactive that's it
Now you can drag to dismiss keyboard and textfield along with your finger
EDIT IPHONE X SUPPORT
lazy var viewAcc: SafeAreaInputAccessoryViewWrapperView = {
return SafeAreaInputAccessoryViewWrapperView(for: button)
}()
Here is complete demo https://github.com/29satnam/InputAccessoryView
Hope it is helpful
I have been trying to implement interactive keyboard like in 'iMessages' app Something like this;
I need to continuously get exact frame of keyboard when sliding it up or down.
I have already tried; keyboardWillChangeFrame, keyboardDidChangeFrame, keyboardWillShowForResizing, keyboardWillHideForResizing, keyboardWillShow, keyboardWillBeHidden None of them continuously return the frame. What is the best way to catch that frame?
That's a tricky & Simple.
ViewController inherits UIResponder
open class UIViewController : UIResponder, NSCoding, UIAppearanceContainer, UITraitEnvironment, UIContentContainer, UIFocusEnvironment
So it can become first responder since it can have input accessory view too.
What you have to do is
1) Go to Storyboard -> ViewController and then select your tableview and change keyboard dismiss type to
2) In your Viewcontroller
Add following code
var viewAcc : UIView? // That contains TextFied and send button
override var inputAccessoryView: UIView? {
return viewAcc
}
override var canBecomeFirstResponder: Bool {
return true
}
For you I have created simple Textfield and send button as example you can modify it with your's
func setupView () {
self.tblChatDetail.contentInset = UIEdgeInsetsMake(0, 0, 20, 0)
viewAcc = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44))
viewAcc?.backgroundColor = UIColor.white
textView = UITextView (frame: CGRect(x:0, y:0, width:0,height: 44 - 0.5))
textView.textContainerInset = UIEdgeInsetsMake(4, 3, 3, 3)
textView.delegate = self
viewAcc?.backgroundColor = .lightGray
viewAcc?.addSubview(textView);
sendButton = UIButton(type: .system)
sendButton.isEnabled = true
sendButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 17)
sendButton.setTitle("Send", for: .normal)
sendButton.contentEdgeInsets = UIEdgeInsets(top: 6, left: 6, bottom: 6, right: 6)
sendButton.addTarget(self, action: #selector(ChatDetailViewController.sendMessage), for: UIControlEvents.touchUpInside)
viewAcc?.addSubview(sendButton)
textView.translatesAutoresizingMaskIntoConstraints = false
sendButton.translatesAutoresizingMaskIntoConstraints = false
viewAcc?.addConstraint(NSLayoutConstraint(item: textView, attribute: .left, relatedBy: .equal, toItem: viewAcc, attribute: .left, multiplier: 1, constant: 8))
viewAcc?.addConstraint(NSLayoutConstraint(item: textView, attribute: .top, relatedBy: .equal, toItem: viewAcc, attribute: .top, multiplier: 1, constant: 7.5))
viewAcc?.addConstraint(NSLayoutConstraint(item: textView, attribute: .right, relatedBy: .equal, toItem: sendButton, attribute: .left, multiplier: 1, constant: -2))
viewAcc?.addConstraint(NSLayoutConstraint(item: textView, attribute: .bottom, relatedBy: .equal, toItem: viewAcc, attribute: .bottom, multiplier: 1, constant: -8))
viewAcc?.addConstraint(NSLayoutConstraint(item: sendButton, attribute: .right, relatedBy: .equal, toItem: viewAcc, attribute: .right, multiplier: 1, constant: 0))
viewAcc?.addConstraint(NSLayoutConstraint(item: sendButton, attribute: .bottom, relatedBy: .equal, toItem: viewAcc, attribute: .bottom, multiplier: 1, constant: -4.5))
}
Just run and Bang on !!
I'm working with a iMessage application and have programmatically added a view. However I can't seem to work out the correct constraints for making it the correct size at all times. For example, the view moves down a few hundred px if I leave the extension for another and come back to it. I think this has something to do with the .isActive. My goal is to make the view automatically resize to always be the right size or take up the full available height and width.
func createBrowser() {
let controller = MSStickerBrowserViewController(stickerSize: .small)
addChildViewController(controller)
view.addSubview(controller.view)
controller.view.translatesAutoresizingMaskIntoConstraints = false
controller.stickerBrowserView.backgroundColor = UIColor.blue
controller.stickerBrowserView.dataSource = self
view.topAnchor.constraint(equalTo: controller.view.topAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: controller.view.bottomAnchor).isActive = true
view.leftAnchor.constraint(equalTo: controller.view.leftAnchor).isActive = true
view.rightAnchor.constraint(equalTo: controller.view.rightAnchor).isActive = true
view.centerXAnchor.constraint(equalTo: controller.view.centerXAnchor).isActive = true
view.centerYAnchor.constraint(equalTo: controller.view.centerYAnchor).isActive = true
}
Screenshot: https://d17oy1vhnax1f7.cloudfront.net/items/1F2B0s3v0s1k3E2L0Z07/Screen%20Shot%202016-09-19%20at%2011.42.51%20AM.png
to better explain things I've put together the following. This demonstrates two methods of fixing the layout for subviews. When using constraints, I prefer to create the constraints as an array and activate them all in one go, as you will see in the code for createredSquareWithConstraints. A constraint is simply a linear equation relating the features of one view to that of another. In "pseudocode", for example, the first constraint in my array could be written:
"Set the leading margin of the subview equal to 1 times the leading margin of the container view plus a constant of 0."
(This is why I was getting confused earlier as it looked to me as though you were setting the containing view's constraints based on the characteristics of one of its subviews.)
While it remains perfectly valid to use layout constraints, I think the preferred methodology these days is to override the viewWillTransitionToSize() delegate method, which simply asks you to specify, given a size for the containing view, what the frame of a view controller's subviews should be. As such, I've included an implementation of this too, creating a yellow square with an initial frame that is then modified whenever viewWillTransitionToSize is called. I personally find this a lot less fiddly that using layout constraints.
If you lay around with the buttons and rotate the screen you should see that either method achieves the same thing. [NB I have labelled one square as constrained and one as unconstrained, but in reality they are of course both constrained, just in different ways. I would add that this is clearly not how you would do things in practice - you should choose one methodology and stick to it otherwise your code will be all over the place!].
Hope that helps!
import UIKit
class ViewController: UIViewController {
var constrainedredSquare : UIView!
var unconstrainedRedSquare : UIView!
var methodOneButton : UIButton!
var methodTwoButton : UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = UIColor.blue
func getButton(name: String) -> UIButton {
let button : UIButton = UIButton()
button.backgroundColor = UIColor.white
button.layer.cornerRadius = 3
button.clipsToBounds = true
button.setTitle(name, for: UIControlState.normal)
button.setTitleColor(UIColor.black, for: UIControlState.normal)
return button
}
self.methodOneButton = getButton(name: "Red - Constraints")
self.methodTwoButton = getButton(name: "Yellow - viewWillTransitionToSize")
self.methodOneButton.addTarget(self, action: #selector(self.createRedSquareWithConstraints), for: .touchUpInside)
self.methodTwoButton.addTarget(self, action: #selector(self.createYellowSquareWithoutConstraints), for: .touchUpInside)
self.methodOneButton.frame = CGRect(origin: CGPoint(x: 200, y: 100), size: CGSize(width: 300, height: 300))
self.methodTwoButton.frame = CGRect(origin: CGPoint(x: self.view.frame.width - 500, y: 100), size: CGSize(width: 300, height: 300))
self.view.addSubview(self.methodOneButton)
self.view.addSubview(self.methodTwoButton)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
if let _ = self.unconstrainedRedSquare {
self.unconstrainedRedSquare.frame = CGRect(origin: CGPoint.zero, size: size)
}
self.methodOneButton.frame = CGRect(origin: CGPoint(x: 200, y: 100), size: CGSize(width: 300, height: 300))
self.methodTwoButton.frame = CGRect(origin: CGPoint(x: size.width - 500, y: 100), size: CGSize(width: 300, height: 300))
}
func createYellowSquareWithoutConstraints() {
if let _ = self.unconstrainedRedSquare {
self.unconstrainedRedSquare.removeFromSuperview()
}
else
{
if let _ = constrainedredSquare {
self.constrainedredSquare.removeFromSuperview()
}
self.unconstrainedRedSquare = UIView()
self.unconstrainedRedSquare.backgroundColor = UIColor.yellow
self.unconstrainedRedSquare.frame = CGRect(origin: CGPoint.zero, size: self.view.frame.size)
self.view.addSubview(self.unconstrainedRedSquare)
self.view.bringSubview(toFront: self.methodOneButton)
self.view.bringSubview(toFront: self.methodTwoButton)
}
}
func createRedSquareWithConstraints() {
if let _ = self.constrainedredSquare {
self.constrainedredSquare.removeFromSuperview()
}
else
{
if let _ = self.unconstrainedRedSquare {
self.unconstrainedRedSquare.removeFromSuperview()
}
let redSquare : UIView = UIView()
redSquare.backgroundColor = UIColor.red
self.view.addSubview(redSquare)
self.view.bringSubview(toFront: self.methodOneButton)
self.view.bringSubview(toFront: self.methodTwoButton)
let rsConstraints : [NSLayoutConstraint] = [NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.leading, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.trailing, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.top, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.bottom, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.width, multiplier: 1.0, constant: 0),
NSLayoutConstraint(item: redSquare, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.height, multiplier: 1.0, constant: 0)]
redSquare.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(rsConstraints)
}
}
}
You can use my extension to UIView. It allows to add extra padding on any side (only if you want to):
public extension UIView {
typealias ConstraintsTupleStretched = (top:NSLayoutConstraint, bottom:NSLayoutConstraint, leading:NSLayoutConstraint, trailing:NSLayoutConstraint)
func addSubviewStretched(subview:UIView?, insets: UIEdgeInsets = UIEdgeInsets() ) -> ConstraintsTupleStretched? {
guard let subview = subview else {
return nil
}
subview.translatesAutoresizingMaskIntoConstraints = false
addSubview(subview)
let constraintLeading = NSLayoutConstraint(item: subview,
attribute: .Left,
relatedBy: .Equal,
toItem: self,
attribute: .Left,
multiplier: 1,
constant: insets.left)
addConstraint(constraintLeading)
let constraintTrailing = NSLayoutConstraint(item: self,
attribute: .Right,
relatedBy: .Equal,
toItem: subview,
attribute: .Right,
multiplier: 1,
constant: insets.right)
addConstraint(constraintTrailing)
let constraintTop = NSLayoutConstraint(item: subview,
attribute: .Top,
relatedBy: .Equal,
toItem: self,
attribute: .Top,
multiplier: 1,
constant: insets.top)
addConstraint(constraintTop)
let constraintBottom = NSLayoutConstraint(item: self,
attribute: .Bottom,
relatedBy: .Equal,
toItem: subview,
attribute: .Bottom,
multiplier: 1,
constant: insets.bottom)
addConstraint(constraintBottom)
return (constraintTop, constraintBottom, constraintLeading, constraintTrailing)
}
}
Usage:
view.addSubviewStretched(tableView)
let BorderedBackgroundInset = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1)
view?.addSubviewStretched(calendar.view, insets: BorderedBackgroundInset)
I am stumbled upon an issue in an application that i am making. I need to place one view into another view programmatically on button click.
Now i need to move View 1 to the centre of View 2 on a button click with an animation. I tried to reposition the View1 to View 2 but i am not able to do it properly.
This is the Final result that i am trying to achieve.
CODE FOR CREATING THE RED VIEW
My.cellSnapshot = snapshopOfCell(cell)
var center = cell.center
My.cellSnapshot!.center = center
My.cellSnapshot!.alpha = 0.0
ingredientsTableView.addSubview(My.cellSnapshot!)
func snapshopOfCell(inputView: UIView) -> UIView {
UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, false, 0.0)
inputView.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext() as UIImage
UIGraphicsEndImageContext()
let cellSnapshot : UIView = UIImageView(image: image)
cellSnapshot.layer.masksToBounds = false
cellSnapshot.layer.cornerRadius = 0.0
cellSnapshot.layer.shadowOffset = CGSizeMake(-5.0, 0.0)
cellSnapshot.layer.shadowRadius = 5.0
cellSnapshot.layer.shadowOpacity = 0.4
return cellSnapshot
}
Please help me in solving the problem.
Thanks in advance
You can move the view for 0.5 seconds.
UIView.animateWithDuration(0.5, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
redView.center = greenView.center
}, completion: nil)
i created a sample project and set up a target view as well as a button to start the animation in storyboard like this:
then in code i added the view to move and the button target code like this:
var sourceView: UIView!
#IBOutlet weak var destinationView: UIView!
var sourceViewPositioningConstraints = [NSLayoutConstraint]()
override func viewDidLoad() {
super.viewDidLoad()
sourceView = UIView()
sourceView?.backgroundColor = UIColor.redColor()
sourceView?.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(sourceView)
// size constraints
NSLayoutConstraint(item: sourceView, attribute: .Width, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 0.25, constant: 0).active = true
NSLayoutConstraint(item: sourceView, attribute: .Width, relatedBy: .Equal, toItem: sourceView, attribute: .Height, multiplier: 16/9, constant: 0).active = true
// positioning constraints
sourceViewPositioningConstraints += [NSLayoutConstraint(item: sourceView, attribute: .Top, relatedBy: .Equal, toItem: topLayoutGuide, attribute: .BottomMargin, multiplier: 1, constant: 0)]
sourceViewPositioningConstraints += [NSLayoutConstraint(item: sourceView, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: 0)]
NSLayoutConstraint.activateConstraints(sourceViewPositioningConstraints)
}
#IBAction func move(sender: UIButton) {
// deactivate current positioning constraints
NSLayoutConstraint.deactivateConstraints(sourceViewPositioningConstraints)
sourceViewPositioningConstraints.removeAll()
// add new positioning constraints
sourceViewPositioningConstraints += [NSLayoutConstraint(item: sourceView, attribute: .CenterX, relatedBy: .Equal, toItem: destinationView, attribute: .CenterX, multiplier: 1, constant: 0)]
sourceViewPositioningConstraints += [NSLayoutConstraint(item: sourceView, attribute: .CenterY, relatedBy: .Equal, toItem: destinationView, attribute: .CenterY, multiplier: 1, constant: 0)]
NSLayoutConstraint.activateConstraints(sourceViewPositioningConstraints)
// animate constraint changes
UIView.animateWithDuration(1) {
self.view.layoutIfNeeded()
}
}
if you are not using autolayout for your movable view you can simply use something like this:
override func viewDidLoad() {
super.viewDidLoad()
sourceView = UIView()
sourceView?.backgroundColor = UIColor.redColor()
sourceView.frame = CGRect(x: 40, y: 40, width: 100, height: 100)
view.addSubview(sourceView)
}
#IBAction func move(sender: UIButton) {
// animate constraint changes
UIView.animateWithDuration(1) {
self.sourceView.center = self.destinationView.center
}
}
I'm experiencing a weird bug with the appearance of my inputAccessoryView. While in the middle of a transition, it appears like so:
After the transition, it appears as it should:
I override the property like so:
override var inputAccessoryView: UIView! {
get {
if composeView == nil {
composeView = CommentComposeView(frame: CGRectMake(0, 0, 0, MinimumToolbarHeight - 0.5))
self.setupSignals()
}
return composeView
}
}
I'm wondering if anyone can point out any obvious flaw in what I'm doing or provide some more information on how to ensure my view appears as it should, before, during, and after transitions.
Thanks!
EDIT
Here's my CommentComposeView:
import UIKit
class CommentComposeView: UIToolbar {
var textView: SAMTextView!
var sendButton: UIButton!
private var didSetConstraints: Bool = false
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.initialize()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.initialize()
}
private func initialize() {
textView = SAMTextView(frame: CGRectZero)
sendButton = UIButton.buttonWithType(.System) as UIButton
self.barStyle = .Black
self.translucent = true
textView.backgroundColor = UIColor.presentOffWhite()
textView.font = UIFont.presentLightMedium()
textView.layer.borderWidth = 0.5
textView.layer.cornerRadius = 5
textView.placeholder = "Comment"
textView.scrollsToTop = false
textView.textContainerInset = UIEdgeInsetsMake(4, 3, 3, 3)
textView.keyboardAppearance = .Dark
textView.keyboardType = .Twitter
self.addSubview(textView)
sendButton = UIButton.buttonWithType(.System) as UIButton
sendButton.enabled = false
sendButton.titleLabel!.font = UIFont.presentBoldLarge()
sendButton.setTitle("Send", forState: .Normal)
sendButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
sendButton.setTitleColor(UIColor.presentCyan(), forState: .Highlighted)
sendButton.setTitleColor(UIColor.presentLightGray(), forState: .Disabled)
sendButton.contentEdgeInsets = UIEdgeInsetsMake(6, 6, 6, 6)
self.addSubview(sendButton)
RAC(self.sendButton, "enabled") <~ self.textView.rac_textSignal()
.map { text in
return (text as NSString).length > 0
}
textView.setTranslatesAutoresizingMaskIntoConstraints(false)
sendButton.setTranslatesAutoresizingMaskIntoConstraints(false)
}
override func updateConstraints() {
super.updateConstraints()
if !didSetConstraints {
// TODO: Replace raw constraints with a friendlier looking DSL
self.addConstraint(
NSLayoutConstraint(item: textView, attribute: .Left, relatedBy: .Equal, toItem: self, attribute: .Left, multiplier: 1, constant: 8)
)
self.addConstraint(
NSLayoutConstraint(item: textView, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1, constant: 7.5)
)
self.addConstraint(
NSLayoutConstraint(item: textView, attribute: .Right, relatedBy: .Equal, toItem: sendButton, attribute: .Left, multiplier: 1, constant: -2)
)
self.addConstraint(
NSLayoutConstraint(item: textView, attribute: .Bottom, relatedBy: .Equal, toItem: self, attribute: .Bottom, multiplier: 1, constant: -8)
)
self.addConstraint(
NSLayoutConstraint(item: sendButton, attribute: .Right, relatedBy: .Equal, toItem: self, attribute: .Right, multiplier: 1, constant: 0)
)
self.addConstraint(
NSLayoutConstraint(item: sendButton, attribute: .Bottom, relatedBy: .Equal, toItem: self, attribute: .Bottom, multiplier: 1, constant: -4.5)
)
}
}
}
This is iOS8 issue with inputAccessoryView autolayout. Issue is that UIToolbar's subview of clas _UIToolbarBackground is not positioned properly during initial layout. Try to do next things:
Make CommentComposeView subclassing UIView, not UIToolbar, add instance of UIToolbar as subview.
Use autolayout masks (not actual constraints) inside your CommentComposeView
Override -layoutSubviews in your CommentComposeView like this:
- (void)layoutSubviews
{
[super layoutSubviews];
contentToolbar.frame = self.bounds;
sendButton.frame = CGRectMake(0.f, 0.f, 44.f, self.bounds.size.height);
textView.frame = CGRectMake(44.f, 0.f, self.bounds.size.width - 44.f, self.bounds.size.height);
}