I am programmatically creating a UIView that loops through a set of strings and creates buttons for them. I wish to evenly space them in that view.
func createRowOfButtons(buttonTitles: [NSString]) -> UIView {
var buttons = [UIButton]()
var rowView = UIView(frame: CGRectMake(0, 0, 320, 50))
for buttonTitle in buttonTitles{
let button = createButtonWithTitle(buttonTitle)
buttons.append(button)
rowView.addSubview(button)
}
//Below will be replaced with PureLayout
addConstraints(buttons, mainView: rowView)
return rowView
}
The addConstraints function uses NSLayoutContraint. I'd like to replace with PureLayout but when I do buttons.autoDistributeViewsAlongAxis.... i get an error that UIButton does not have a member named autoDistributeViewsAlongAxis.
So, I get that it needs to be an array but as far as I can tell I've created an array of buttons in swift.
Any thoughts?
thanks!
Related
I'm trying to use a custom view as an accessory view over the keyboard, for various reasons, in this case, it is much preferred over manual keyboard aligning because of some other features.
Unfortunately, this is a dynamic view that defines its own height. The constraints all work fine outside of the context of an accessoryView without errors, and properly resizing
When added as a keyboardAccessoryView it seems to impose a height of whatever the frame is at the time and break other height constraints
It appears as:
"<NSLayoutConstraint:0x600003e682d0 '_UIKBAutolayoutHeightConstraint' Turntable.ChatInput:0x7fb629c15050.height == 0 (active)>"
(where 0 would correspond to whatever height had been used at initialization
It is also labeled accessoryHeight which should make it easy to remove, but unfortunately, before I can do this, I'm getting unsatisfiable constraints and the system is tossing my height constraints
Tried:
in the inputAccessoryView override, I tried to check for the constraints and remove it, but it doesn't exist at this time
setting translatesAutoresizing...Constraints = false
tl;dr
Using a view as a KeyboardAccessoryView is adding its own height constraint after the fact, can I remove this?
Looks like keyboard doesn't like inputAccessoryView with height constraint. However you still can have inputAccessoryView with dynamic height by using frame (it is still possible to use constraints inside your custom inputAccessoryView).
Please check this example:
import UIKit
final class ViewController: UIViewController {
private let textField: UITextField = {
let view = UITextField()
view.frame = .init(x: 100, y: 100, width: 200, height: 40)
view.borderStyle = .line
return view
}()
private let customView: UIView = {
let view = UIView()
view.backgroundColor = .red
view.frame.size.height = 100
view.autoresizingMask = .flexibleHeight // without this line height won't change
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(textField)
textField.inputAccessoryView = customView
textField.becomeFirstResponder()
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
self.customView.frame.size.height = 50
self.textField.reloadInputViews()
}
}
}
I have a UIView called brokeView, It is draggable and rotational. I am trying to allow the user to populate the same exact view from clicking a button allowing an endless amount of the same UIView to populate. Is this possible to do in swift using the storyboard?
- Do I have to create all the views in storyboard or could I populate them through code using an array or loop?
#IBOutlet weak var brokeView: UIView!
#IBAction func showBrokenAnnotation(sender: AnyObject) {
brokeView.hidden = false
for i in 1...10 {
print(i)
let newView = UIView(frame: brokeView.bounds)
brokeView.addSubview(newView)
}
This can be done through code. Here is some pseudo code.
Updated from our conversation below - this makes it the same size as your "brokenView" and then you can set the x/y however you want.
let newView = UIView(frame: CGRect(x: 0, y: 0, width: mainView.frame.width, height: mainView.frame.height))
self.view.addSubview(newView)
I want to create a simple view over keyboard, when users tap "Attach" button in inputAccessoryView.
Something like this:
Is there an easy way to do it? Or i should create my custom keyboard?
You can add that new subview to your application window.
func attach(sender : UIButton)
{
// Calculate and replace the frame according to your keyboard frame
var customView = UIView(frame: CGRect(x: 0, y: self.view.frame.size.height-300, width: self.view.frame.size.width, height: 300))
customView.backgroundColor = UIColor.redColor()
customView.layer.zPosition = CGFloat(MAXFLOAT)
var windowCount = UIApplication.sharedApplication().windows.count
UIApplication.sharedApplication().windows[windowCount-1].addSubview(customView);
}
Swift 4 version:
let customView = UIView(frame: CGRect(x: 0, y: self.view.frame.size.height - 300, width: self.view.frame.size.width, height: 300))
customView.backgroundColor = UIColor.red
customView.layer.zPosition = CGFloat(Float.greatestFiniteMagnitude)
UIApplication.shared.windows.last?.addSubview(customView)
The trick is to add the customView as a top subview to the UIWindow that holds the keyboard - and it happens to be the last window in UIApplication.shared.windows.
Swift 4.0
let customView = UIView(frame: CGRect(x: 0, y: self.view.frame.size.height-300, width: self.view.frame.size.width, height: 300))
customView.backgroundColor = UIColor.red
customView.layer.zPosition = CGFloat(MAXFLOAT)
let windowCount = UIApplication.shared.windows.count
UIApplication.shared.windows[windowCount-1].addSubview(customView)
As Tamás Sengel said, Apple's guidelines does not support adding a view over the keyboard. The recommended way to add a view over keyboard in Swift 4 & 5 is:
1) Add view with your "Next" button in your storyboard as external view and connect in your class (see Explain Image), in my case:
IBOutlet private weak var toolBar: UIView!
2) For the textfield you want to add your custom view over keyboard, add it as accessory view in viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
phoneNumberTextField.inputAccessoryView = toolBar
}
3) Add action for "Next" button:
#IBAction func nextButtonPressed(_ sender: Any) {
descriptionTextView.becomeFirstResponder()
// or -> phoneNumberTextField.resignFirstResponder()
}
Explain Image:
Method 2: Result with image
In TableView Controller - add stricked view at bottom
Please follow this great link to handle safe area for screens like iPhone X if you want to use this method(2). Article: InputAccessoryView and iPhone X
override var inputAccessoryView: UIView? {
return toolBar
}
override var canBecomeFirstResponder: Bool {
return true
}
Do you have find some effective method to solve this problem? In iOS9,you put your customView on the top of the windows:
UIApplication.sharedApplication().windows[windowCount-1].addSubview(customView);
But if the keyboard dismisses, the top Windows will be removed, so your customView will be removed.
Looking forward for your help!
Thank you for your help!
You can definitely add the view to your application’s window, and you can also add another window entirely. You can set its frame and level. The level could be UIWindowLevelAlert.
While this can be possible with accessing the topmost window, I would avoid doing this, as it clearly interferes with Apple's guidelines.
What I would do is dismissing the keyboard and replacing its frame with a view with same dimensions.
The keyboard's frame can be accessed from keyboard notifications listed here, their userInfo contain a key that can be accessed with UIKeyboardFrameEndUserInfoKey.
I have a UIBarButtonItem and a UIView containing two UITextField controls, all within a UIToolbar.
This is a screenshot of my storyboard: http://i.8px.co/x8eC.png.
I'd like to create something similar to this: http://i.8px.co/1hvY.png.
I'm trying to make the UIView and its children expand to fill the available horizontal space in the UIToolbar with Auto Layout. I don't know how to accomplish what I want.
I experimented with a dirty solution for the UIView and was able to have it size somewhat correctly.
view.width = toolBar.frame.width - button.width
// where view is the UIView, toolBar is the UIToolBar, and button is the UIBarButtonItem
I don't believe this is very elegant. This is done programmatically, the UIView doesn't conform to the standard UIToolbar margins, and the solution doesn't apply to the UITextFields.
I'm afraid you'd have to do this programmatically.
Try this :
self.toolBarview.frame = (CGRect) {.origin = self.toolBarview.frame.origin.x, self.toolBarview.frame.origin.y, .size = [UIScreen mainScreen].bounds.size.width - self.barButton.width - 40, self.toolBarview.frame.size.height};
Here toolBarview is the UIView which has the 2 UITextField's. 40 is the buffer value that you need to subtract to give the padding.
/* EDIT */
You should give the appropriate constraints to the UITextField as shown below:
"I'm trying to make the UIView and its children expand to fill the available horizontal space in the UIToolbar with Auto Layout" You can't. The UIView is in a UIBarButtonItem, and a UIBarButtonItem is not a view. So you can't use auto layout on it. You must set its width manually.
You can do this in many way,
Do these Constraints
Then create a sub class of UITextField, and do this code
class CustomTextField: UITextField {
override func textRectForBounds(bounds: CGRect) -> CGRect {
return CGRectInset(CGRectMake(65, 0, bounds.size.width-65, bounds.size.height) , 0 , 0 )
}
override func editingRectForBounds(bounds: CGRect) -> CGRect {
return CGRectInset(CGRectMake(65, 0, bounds.size.width-65, bounds.size.height) , 0 , 0 )
}
}
In storyboard/xib, Connect textField to your CustomTextField
Create outlet for 2 textFields
#IBOutlet weak var textField1: CustomTextField!
#IBOutlet weak var textField2: CustomTextField!
in viewDidLoad() method,
var label1 : UILabel = UILabel(frame: CGRectMake(5, (textField1.frame.height/2)-15, 100, 30))
label1.textColor = UIColor.lightGrayColor();
label1.text = "From:"
var label2 : UILabel = UILabel(frame: CGRectMake(5, (textField1.frame.height/2)-15, 100, 30))
label2.textColor = UIColor.lightGrayColor();
label2.text = "To:"
textField1.addSubview(label1)
textField2.addSubview(label2)
Then you will get output like...
I have created a view, CustomView.xib, and a dedicated class, CustomView.swift. I have added it to my ViewController in Storyboard by adding a view and setting the custom class to CustomView.swift and it works perfectly. The constraints I added in StoryBoard resize the nib like I want. Now I want to create copies of it, like cells/rows in a tableView (like a twitterfeed). How can I do that, while maintaining the constraints so that it resize correctly? I guess my question boils down to: How do you duplicate UIViews created in StoryBoard? I realise that the top constraint might have to be altered as row's are added. And second, since this is a nib, how can I change the label within it? The project is on GitHub
Any help would be very much appreciated! Thank you.
import UIKit
class ScrollViewController: UIViewController {
let scrollView = UIScrollView()
override func viewDidLoad() {
super.viewDidLoad()
let height = CGFloat(200.0)
self.scrollView.frame = self.view.bounds
self.scrollView.contentSize = CGSizeMake(self.view.bounds.size.width, height*3)
self.view.addSubview(self.scrollView)
var y = CGFloat(0.0)
for i in 0..<2 {
//DO I ADD IBOUTLET(s)?
// How do I set width of frame to the View in StoryBoard (that has constraints?
//Do I tag it, give it an ID - How can I create copies of the customView from StoryBoard
let customView = CustomView(frame: CGRectMake(0, y, 320, 200))
self.scrollView.addSubview(customView)
y += height
}
}
func createCustomView(index: Int) -> UIView {
//How do I instantiate the view here without setting the frame size?
let customView = CustomView(frame: CGRectMake(0, 0, 320, 200))
if index == 0{
customView.backgroundColor = UIColor.greenColor()
//How do I change the label text, like below?
//customView.label.text = "New York"
}
if index == 1{
customView.backgroundColor = UIColor.redColor()
//How do I change the label text, like below?
//customView.label.text = "Tokyo"
}
return customView
}
}