Tool bar with done button on top of keyboard for Iphone using Mono Touch? - iphone

I need to add done button on tool bar with UIkeyboard(type) Number Pad, to resign the keyboard while click on done button. I used Input Accessory View but it adds to normal keyboard also ,i need to add this where i have number pad.For example i have a text field it takes only numbers there i need this.Other than places i don't want to show input Accessory view.Or else i need to show tool bar with Done button for Iphone using Mono Touch.
Thank you.

public override UIView InputAccessoryView
{
get
{
if (dismiss == null)
{
UIToolbar toolbar = new UIToolbar(new RectangleF(0, 0, 320, 30));
toolbar.BarStyle = UIBarStyle.BlackTranslucent;
dismiss = new UIView(new RectangleF(-20, -120, 320, 30));
dismissBtn = new UIButton(new RectangleF(268, 1, 50, 29));
dismissBtn.SetBackgroundImage(new UIImage("Images/done_active.png"), UIControlState.Normal);
dismissBtn.AllEvents += delegate
{
HideKeyBoard();
};
toolbar.AddSubview(dismissBtn);
dismiss.AddSubview(toolbar);
dismiss.BringSubviewToFront(dismissBtn);
dismiss.BringSubviewToFront(toolbar);
}
return dismiss;
}
}

Related

UIButton Not Clickable when added UITabbar

When added UIButton on UITabbar to middle as shown in figure.
The button action on above the UITabBar unable to click
func setupMiddleButton() {
plusButton = UIButton(frame: CGRect(x: 0, y: 0, width: 64, height: 64))
var menuButtonFrame = plusButton.frame
menuButtonFrame.origin.x = tabBar.bounds.width/2 - menuButtonFrame.size.width/2
let hasNotched :Bool? = UIDevice.current.hasNotch
if hasNotched != nil {
menuButtonFrame.origin.y = tabBar.bounds.height - menuButtonFrame.height - 15
} else {
menuButtonFrame.origin.y = tabBar.bounds.height - menuButtonFrame.height - 50
}
plusButton.frame = menuButtonFrame
plusButton.setTitle("+", for: .normal)
plusButton.titleLabel?.font = UIFont.helveticaNeue(ofSize: 40)
plusButton.backgroundColor = UIColor.init(hexString: "5E71FE")
plusButton.titleEdgeInsets = UIEdgeInsets(top: 0,left: 10,bottom: 10,right: 10)
tabBar.addSubview(plusButton)
plusButton.layer.cornerRadius = menuButtonFrame.height/2
plusButton.addTarget(self, action: #selector(plusButtonAction(sender:)), for: .touchUpInside)
}
You need to override the hitTest method in your custom tab bar class like this
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
{
guard !clipsToBounds && !isHidden && alpha > 0 else { return nil }
for member in subviews.reversed()
{
let subPoint = member.convert(point, from: self)
guard let result = member.hitTest(subPoint, with: event)
else { continue }
return result
}
return nil
}
Basically the problem is that upper part is not clickable because it is outside of the bounds of main content view of tab bar.
This method will check if the tap is inside the bounds of the view, if it is it will return the view and the action for that button will get called.
Documentation by apple: Link
P.s I was facing the same issue recently and got this help which worked smooth.
I suspect that what you are trying to do is not possible, or at the least, not supported by Apple. (And thus not recommended since you might find a way to make it might work today but not in some future OS version.)
As a rule, Apple does not support you adding custom view objects to system components like tab bars, navigation bars, stack views, table/collection view controllers, etc except through a documented API.
I would suggest NOT doing what you are trying to do. instead, add a button in the content view of the tab bar controller. I don't know if you'll be able to make it partly cover the tab bar like you are trying to do however.
Add the button to the view of the UITabbarController instead of adding to the TabBar. And then reposition the button, it will work.

How do I add NSButtons from the top instead of from the bottom?

I am currently building a navigation left pane where buttons from the side are added dynamically. I have a NSView subclass that facilitates this
func addButton(_ service: String) {
let btn = NSButton()
btn.bezelStyle = .shadowlessSquare
btn.frame.size = NSSize(width: 48, height: 48)
btn.image = NSImage(named: service)
btn.imageScaling = .scaleAxesIndependently
btn.frame.origin = CGPoint(x: 0, y: self.currentY)
self.addSubview(btn)
self.currentY += 58
}
It works as desired but buttons are added from the bottom instead of the top:
Resulting App Screenshot
How do I make it so that new buttons are added from the top?
For reference, here's my storyboard with the "Servi" view containing the buttons.
Left Pane Storyboard
Y goes from bottom to top on macOS (the bottom is 0). So don't start with currentY at 0 or 10 or whatever you're starting with. Start with currentY set to one button height less than the view height, and then subtract 58 each time instead of adding.
So, you're getting something like this:
But if you do what I'm describing, you'll get something like this:
You could flip your view so that the coordinate system starts at the top left instead. Just create a new NSView subclass and override isFlipped
class FlippedView: NSView {
override var flipped:Bool {
get {
return true
}
}
}
Then add the new buttons to an instance of flippedview instead.

UIButton action is not triggered after constraint layouts changed

I have got an UIButton on a storyboard ViewController. When I load data into the form and the layout is significantly changing the button does not recognise the touch action.
I have figured out that when button is visible on the scrollview right after it if filled with data, the touch action works.
If the data too long and the button is not visible at first, just when it is scrolled into the display, the touch action does not work.
I was checking if something is above the button, but nothing. I have tried to change the zPosition of the button, not solved the problem.
What can be the issue?
I have made custom classes from the UIScrollView and the UIButton to check how the touches event triggered. It is showing the same behaviour, which is obvious. If the button is visible right at the beginning, the UIButton's touchesBegan event is triggered. If the button moves down and not visible at the beginning, it is never triggered, but the scrollview's touchesBegan is called instead.
Depending on the size of the data I load into the page sometimes the button is visible at the beginning, but the form can be still scrolled a bit. In this case the button still work, so it seems that this behaviour is not depending on if the scrollview is scrolled before or not, just on the initial visibility of the button.
Is there any layout or display refresh function which should be called to set back the behaviour to the button?
The code portion which ensures that the contentview is resized for the scroll if the filled data requires bigger space.
func fillFormWithData() {
dispDescription.text = jSonData[0]["advdescription"]
dispLongDescription.text = jSonData[0]["advlongdesc"]
priceandcurrency.text = jSonData[0]["advprice"]! + " " + jSonData[0]["advpricecur"]!
validitydate.text = jSonData[0]["advdate"]!
contentview.layoutIfNeeded()
let contentRect = CGRect(x: 0, y: 0, width: scrollview.frame.width, height: uzenetbutton.frame.origin.y+uzenetbutton.frame.height+50)
contentview.frame.size.height = contentRect.size.height
scrollview.contentSize = contentview.bounds.size
}
Ok, so another update. I have coloured the contentview background to blue and the scrollview background to white. When I load the data and resize the layout constraints, the contentview is resizing as expected, however now the scrollview is going to the bottom. After I scroll the view it is resizing to the original size which fits the screen. Now the button is only recognised when I touch the are which is blue behind. With the white background it is not recognised anymore, so it seems that the scrollview is hiding the button.
Let me get this clear the button is added in storyboard and it is a spritekit project?? If you are using zPosition?? Why don’t u connect the UIButton via the assistant editor as an IBAction then the action is always tied to the button.
You can also do it differently
Create an SKLabelNode and put it on the screen where you want to have the button and then set a name to it as myButton
override func touchesBegan(_ touches: Set<UITouch>, with event:
UIEvent?) {
if let touch = touches.first {
let location = touch.location(in: self)
let tappedNodes = nodes(at: location)
for node in tappedNodes {
if node.name == "myButton" {
// call your action here
}
}
}
}
EDIT 1:
You could also try auto resizing your scrollView.content this works also if you are adding any views via the app or programmatically
private func resizeScrollView(){
print("RESIZING THE SCROLLVIEW from \(scrollView.contentSize)")
for view in scrollView.subviews {
contentRect = contentRect.union(view.frame)
}
scrollView.contentSize = CGSize(width: contentRect.size.width, height: contentRect.size.height + 150)
print("THE CONTENT SIZE AFTER RESIZING IS: \(scrollView.contentSize)")
}
EDIT 2: I think I found the issue with your project. You need to move the MessageButton(UzenetButton) above DispDescription label in the object inspector in that way it will always be above your message textView.
At the moment the UzeneButton is at the very far back in your view hierarchy so if your textView is resizing whilst editing it covers the button that is why you cannot click on it.
See #Endre Olah,
To make situation more clear do one more thing, set clipToBound property of contentview to true.
you will notice that after loading of data your button not fully visible, it means it is shifting out of bound of its parentView (ContentView)
And that's why button is not taking your touch. However, if you carefully touch upper part of button it still do its job. Because upper part is still in bound of ContentView
Solution :
After loading of data you have to make sure that you increase height of ContentView such that button should never go out of bound of its parentView(ContentView).
FOR EXAMPLE
#IBOutlet var heightConstraintOfContentView : NSLayoutConstraint!
After loading of data
let contentRect = CGRect(x: 0, y: 0, width: scrollview.frame.width, height: uzenetbutton.frame.origin.y+uzenetbutton.frame.height+50)
heightConstraintOfContentView.constant = contentRect.size.height
contentView.layoutIfNeeded()
I use following steps when I need to use scrollview with dynamic content:
1) Firstly add a scrollView with top, bottom, trailing and leading is 0 to super view.
2) Add a view to scrollView and view's trailing, leading bottom and top space to scrollView can be set to 0 (or you can add margin optionally).
3) Now, you should add UI elements like buttons, labels with appropriate top, bottom, trailing and leading margins to each other.
4) Lastly, add equal height and equal width constraint to view with Safe Area:
and change equal height priority of view to 250:
It should solve your problem with UIScrollView.
Finally, I have found the solution in another chain, once it became clear that the scrollview's contentview is resizing on scroll event to the original size. (Not clear why this is like this, but that is the fact.)
So I had to add a height constraint to the contentview in the storyboard and create an outlet to it and adjust this constraint when the content size is changing, like this:
#IBOutlet weak var ContentViewHeight: NSLayoutConstraint!
func fillFormWithData() {
dispDescription.text = jSonData[0]["advdescription"]
dispLongDescription.text = jSonData[0]["advlongdesc"]
priceandcurrency.text = jSonData[0]["advprice"]! + " " + jSonData[0]["advpricecur"]!
validitydate.text = jSonData[0]["advdate"]!
contentview.layoutIfNeeded()
let contentRect = CGRect(x: 0, y: 0, width: scrollview.frame.width, height: uzenetbutton.frame.origin.y+uzenetbutton.frame.height+50)
contentview.bounds = contentRect
scrollview.contentSize = contentRect.size
----------- This is the key line to the success ----------
ContentViewHeight.constant = contentRect.size.height
----------------------------------------------------------
}
After this is added, it works perfectly.

Remove UINavigationBar back button extra padding?

I've removed the back button's text by manually setting it to " " on each navigation item, however there is still extra padding between the button and the navigation item's title for no reason.
Does anyone know how to get rid of this annoying spacing?
In a few real case scenarios in my app, the title does concatenate as it gets slightly too long, even though it wouldn't need to if that space were not there.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
let arrayViews = (self.navigationController?.navigationBar.subviews)
if let itemView = arrayViews?[1] {
for lbl in itemView.subviews {
lbl.frame = CGRect(x: -25, y: lbl.frame.origin.y, width: lbl.frame.size.width, height: lbl.frame.size.height)
}
}
}
You should create a custom UIBarButtonItem which uses popToViewController to go back to the previous item on your stack. That way, you can manually set the frame of your custom back button.

Disable UITextField keyboard?

I put a numeric keypad in my app for inputing numbers into a text view, but in order to input numbers I have to click on the text view. Once I do so, the regular keyboard comes up, which I don't want.
How can I disable the keyboard altogether? Any help is greatly appreciated.
The UITextField's inputView property is nil by default, which means the standard keyboard gets displayed.
If you assign it a custom input view, or just a dummy view then the keyboard will not appear, but the blinking cursor will still appear:
UIView* dummyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
myTextField.inputView = dummyView; // Hide keyboard, but show blinking cursor
If you want to hide both the keyboard and the blinking cursor then use this approach:
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
return NO; // Hide both keyboard and blinking cursor.
}
For Swift 2.x, 3.x, 4.x, 5.x
textField.inputView = UIView()
does the trick
If it's a UITextField, you can set it's enabled property to NO.
If it's a UITextView, you can implement -textViewShouldBeginEditing: in its delegate to return NO, so that it'll never start editing. Or you can subclass it and override -canBecomeFirstResponder to return NO. Or you could take advantage of its editing behavior and put your numeric buttons into a view which you use as the text view's inputView. This is supposed to cause the buttons to be displayed when the text view is edited. That may or may not be what you want.
Depending on how you have your existing buttons working this could break them, but you could prevent the keyboard from showing up setting the textView's editable property to NO
myTextView.editable = NO
I have the same problem when had 2 textfields on the same view. My purpose was to show a default keyboard for one textfield and hide for second and show instead a dropdown list.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
method simply did not work as I expected for 2 textfields , the only workaround I found was
UIView* dummyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
myTextField.inputView = dummyView;
myTextField.inputAccessoryView = dummyView;
myTextField.tintColor = myTextField.backgroundColor; //to hide a blinking cursor
This will totally hide the keyboard for a target textField (DropDownList in my case) and show a default one when user switches to the 2nd textfield (Account number on my screenshot)
There is a simple hack to it. Place a empty button
(No Text) above the keyboard and have a action Event assign to it. This will stop keyboard coming up and you can perform any action you want in the handle for the button click
To disable UITextField keyboard:
Go to Main.Storyboard
Click on the UITextField to select it
Show the Attributes inspector
Uncheck the User Interaction Enabled
To disable UITextView keyboard:
Go to Main.Storyboard
Click on the UITextView to select it
Show the Attributes inspector
Uncheck the Editable Behavior
I used the keyboardWillShow Notification and textField.endEditing(true):
lazy var myTextField: UITextField = {
let textField = UITextField()
// ....
return textField
}()
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
}
#objc func keyboardWillShow(_ notification: Notification) {
myTextField.endEditing(true)
// if using a textView >>> myTextView.endEditing(true) <<<
}
private void TxtExpiry_EditingDidBegin(object sender, EventArgs e)
{
((UITextField)sender).ResignFirstResponder();
}
In C# this worked for me, I don't use the storyboard.
In Xcode 8.2 you can do it easily by unchecking state "enabled" option.
Click on the textField you want to be uneditable
Go to attirube inspector on right side
Uncheck "enabled" for State
Or if you want to do it via code. You can simply create an #IBOutlet of this text field, give it a name and then use this variable name in the viewDidLoad func (or any custom one if you intent to) like this (in swift 3.0.1):
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
myTextField.isEditable = false
}