I am making a calculator and using my own keypad and i want there to be no keyboard that pops up when the textview is activated but i want the user to be able to move the cursor around. Any ideas are greatly appreciated.
you can change the inputView for the textfield to custom UIView. Something like below.
#IBOutlet weak var myTextField: UITextField!
let customView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
myTextField.inputView = customView
}
Related
I've read a lot of material on this topic but most of them create custom view programatically.
Is it possible to use InputAccessoryView with a custom view created in IB? In storyboard I've added textInputView, inside which I've added text view and send button etc as seen in the screenshot below.
I've following code so which removes Table View for some reason so I can't get it working. I've added tableview in the storyboard.
I've shown here only InputAccessoryView related code.
class InputAccViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var textView: UITextView!
#IBOutlet weak var textInputView: UIView!
// other code
override var canBecomeFirstResponder: Bool { return true }
override var inputAccessoryView:UIView {
get{
return self.textInputView
}
}
override func viewDidLoad() {
super.viewDidLoad()
textInputView.removeFromSuperview()
// other code
}
// other code tableview delegates etc...
}
Left screenshot is with the accessory view code which doesn't show table view. If I comment out accessory view related code it does show table view as in the right screenshot.
Seems you might be constraining the UITableView's bottom to the textInputView's top. When you are setting the textInputView as the inputAccessoryView of the UIViewController this no longer works as expected. When setting the textInputView as the inputAccessoryView make sure you constraint the bottom of UITableView to the bottom of UIViewController's view.
I am making a function that the height of a UIView increases and decreases when a button is pressed.
When the height of the UIView was reduced, the value created a layout in the storyboard, When the height of the UIView is increased, the value will be the height of the UITextView.
The picture above is before the UIView is stretched. Press the button at the bottom of the photo to stretch the UIView
The picture above is after the UIView is stretched. If you press the button at the bottom of the picture above, the UIView will shrink again.
The first thing I am curious about is the code to make the height of the UIView increase.
#IBOutlet weak var bookInfoView: UIView!
#IBOutlet weak var bookInfoVieweBtn: UIButton!
#IBOutlet weak var bookInfoTextView: UITextView!
#IBAction func bookInfoViewBtnTapped(_ sender: Any) {
print("##bookInfoViewBtnTapped!")
let f = bookInfoView.frame
let textView = bookInfoTextView.frame
bookInfoView.frame = CGRect(x: f.origin.x, y: f.origin.y, width: f.width, height: textView.height)
}
If you press the button using the code above, it does nothing. What should I do?
1.Set some default value for the height of your the view your are trying to expand. Then if you are using StoryBoard make an IBOutlet to your ViewConroller, and remove the weak reference (that's because we are going to deactivate the height anchor and if it is weak and you deactivate it, the ARC will dealocate it. If your are going for it programatically just store the height anchor in a local variable. So it should like something like this:
#IBOutlet var yourViewHeightAnchor: NSLayoutConstraint!
2. Add a target to your button or if your using StoryBoard or Xib drag a IBAction to you ViewController. When the button is clicked, your only job is to deactive/active the height anchor. ( The activation will serve for collapse)
#IBAction func expandClicked(_ sender: Any) {
yourViewHeightAnchor.isActive.toggle()
}
If you wish to use some animation for expanding/collapsing, your expandClicked function should look something like this:
#IBAction func expandClicked(_ sender: Any) {
UIView.animate(withDuration: 0.6, animations: {
self.yourViewHeightAnchor.isActive.toggle()
self.view.layoutIfNeeded()
})
}
Follow below steps:-
Define height constraint in your storyboard.
create IBOutlet of height constraint
Then on button press, increase/decresse your height of textview like:-
textViewHeightConstant.constant = someValue
I am trying to hide and remove the space of the MainUIView.I tried to make the MainUIView heightConstarint to 0 . But it is not hiding the views inside them.
I want to hide all the view and labels inside the MainUIView.
hope you understand my problem.Thank you in advance
Here is my code
#IBOutlet weak var heightConstarint:NSLayoutConstraint!
//#IBOutlet weak var viewhide: UIView!
override func viewDidLoad() {
super.viewDidLoad()
heightConstarint.constant = 0
//self.viewhide.setNeedsUpdateConstraints()
self.view.layoutIfNeeded()
}
Updating Constraints will Never work in
override func viewDidLoad(){}
If you want to change constraints programmatically then you must put your code in
override fun viewWillLayoutSubviews(){}
So your code will look like
override func viewWillLayoutSubviews() {
clipToBounds = true
heightConstarint.constant = 0
//self.viewhide.setNeedsUpdateConstraints()
self.view.layoutIfNeeded()
}
I don't know updating constraints will work or not in viewDidLoad. But there are another constraints for MainUIView.
I think you should remove top or bottom space.
I have created a uiview in storyboard and have placed it in some random point(autoLayout not applied) . Now in viewDidLoad() Im trying to place it at the center of the screen. But its not moving from that place and replaced at center Why? is this because of some order viewController Life Cycle ? But when I Create a UIView programmatically and placed it in center it works .??
class ViewController: UIViewController {
#IBOutlet weak var view1: UIView!
override func viewDidLoad() {
super.viewDidLoad()
view1.center = view.center
}
}
Your guess is correct. You need to do this in viewWillAppear. viewWillLayoutSubviews is also a good place to put this.
use viewDidLayoutSubviews
- (void) viewDidLayoutSubviews {
self.view1.center = self.view.center
}
What I'm trying to do is to create something similar to the "find on page" search function in Safari on iPad.
I'm using a UIToolbar with some items in it and attached it to the keyboard by setting it as an inputAccessoryView on the UITextField. Works like a charm, but there is one thing I can't figure out. In Safari, when you search for something, the keyboard disappears but the tool bar remains on the bottom of the screen.
Does anyone have a clue on how to accomplish this? The only solution I can think of is to respond to a keyboard dismissed event and then pull out the UIToolBar and create a custom animation that moves it to the bottom of the screen. But this is hacky. I am looking for a more elegant solution. Something that can make me decide what to do with the input accessory view when the keyboard gets dismissed.
It's done like this:
Assign your UIToolbar to a property in your view controller:
#property (strong, nonatomic) UIToolbar *inputAccessoryToolbar;
In your top view controller, add these methods:
- (BOOL)canBecomeFirstResponder{
return YES;
}
- (UIView *)inputAccessoryView{
return self.inputAccessoryToolbar;
}
And then (optionally, as it usually shouldn't be necessary), whenever the keyboard gets hidden, just call:
[self becomeFirstResponder];
That way, your inputAccessoryToolbar will be both your view controller's and your text view's input accessory view.
I've ended up with UIToolBar that is not assigned as input accessory view, and slide up and down on UIKeyboardWillShowNotification / UIKeyboardWillHideNotification
Update to Swift 4, based on prior answers. If you add toolbar via storyboards you can do this
class ViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
#IBOutlet var toolbar: UIToolbar!
override var canBecomeFirstResponder: Bool {
get {
return true
}
}
override var inputAccessoryView: UIView {
get {
return self.toolbar
}
}
override func viewDidLoad() {
super.viewDidLoad()
textField.inputAccessoryView = toolbar
}
}
In this case, whenever text field resigns first responder, it defaults first responder to main view. Keep in mind, you might want to explicitly resign first responder, and set main view as first responder if there are multiple UI elements and first responder defaults to undesired view after resignation.
Adding to #arik's answer, here is the Swift version:
class ViewController: UIViewController {
#IBOutlet var textField: UITextField!
// Input Accessory View
private var inputAccessoryToolbar: UIToolBar?
override func canBecomeFirstResponder() -> Bool {
return true
}
override var inputAccessoryView: UIView? {
return inputAccessoryToolbar
}
override func viewDidLoad() {
super.viewDidLoad()
inputAccessoryToolbar = UIToolbar(frame: CGRectMake(0, 0, view.frame.size.width, 50))
textField.inputAccessoryView = inputAccessoryToolbar
}
// UITextFieldDelegate
func textFieldShouldReturn(textField: UITextField) -> Bool {
becomeFirstResponder()
return true
}
}
Thanks for the clean solution!
You may also need to work around the bug with the inputAccessoryView not respecting the safe area margins and thus not making room for home indicator thing on iPhone X: iPhone X how to handle View Controller inputAccessoryView?
I found the easiest solution when you have a UIToolbar from a xib and you are also using that UIToolbar as the inputAccessoryView of a text field is to embed the toolbar in a UIView when you return it from your overridden inputAccessoryView, and make the containing UIView taller by the safeAreaInsets.bottom. (Other solutions suggest constraining the bottom of the toolbar to the safe area in a subclass, but this leads to constraint conflicts and also means the area under the toolbar is the wrong colour.) However, you have to also bear in mind that the text field can have focus even when there is no keyboard on the screen (for instance if there is an external keyboard), so you need to change the inputAccessoryView of the text view to this toolbar-within-a-UIView in that case as well. In fact it will probably make things simpler to just always use the containing view and adjust the size of it appropriately. Anyway, here's my override of inputAccessoryView:
override var inputAccessoryView: UIView? {
if toolbarContainerView == nil {
let frame=CGRect(x: toolBar.frame.minX, y: toolBar.frame.minY, width: toolbar.frame.width, height: toolBar.frame.height+view.safeAreaInsets.bottom)
toolbarContainerView = UIView(frame: frame)
}
if (toolbar.superview != toolbarContainerView) {
//this is set to false when the toolbar is used above the keyboard without the container view
//we need to set it to true again or else the toolbar will appear at the very top of the window instead of the bottom if the keyboard has previously been shown.
toolbar.translatesAutoresizingMaskIntoConstraints=true
toolbarContainerView?.addSubview(toolbar)
}
return toolbarContainerView
}
It would probably be a good idea to override viewSafeAreaInsetsDidChange to adjust the size of toolbarContainerView in that case, too.