Overlay an UIButton over an UIWebView in Swift - ios

So I have a view that loads a UIWebView and I want to overlay UIButton the user can tap on to go to another view.
I managed to place the button over the web view but I can't seem to be able to tap on it.
Here's my code:
class ButtonView: UIView {
var button: UIButton!
override init(frame: CGRect) {
super.init(frame: frame)
button = UIButton(frame: CGRectMake(0, 0, 50, 50))
button.layer.zPosition = 10
self.addSubview(button)
}
required init(coder aDecoder: NSCoder) {
fatalError("Init(coder:) has not been implemented")
}
}
class MyViewController : UIViewController, UIWebViewDelegate {
var buttonView = ButtonView()
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
self.loadWebView() //This just loads a url to the web view...
webView.layer.zPosition = 1
buttonView = ButtonView(frame: CGRectMake(0, 0, 100, 100))
buttonView.layer.zPosition = 100
buttonView.button.addTarget(self, action: "buttonEvent:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(buttonView)
}
func buttonEvent(sender: AnyObject!){
println("Tap detected!")
}
}
So this displays the button on top of the web view as expected but I can't tap on it.
Although if I hide the web view I can tap on the button without any problems
Is this a zPosition problem? or something else?

It could work as it is as long as you replace:
self.view.addSubview(buttonView)
With:
webView.addSubview(buttonView)
So basically add the view containing the button to the web view instead

Related

Cannot call method of a button from a custom UIView

I want to call an action from a button which is inside a custom View. The view itself is part of a UIViewController. But when I tapped the view, nothing happens. I do not know where my mistake is, although my code looks like the ones on stackoverflow.
protocol StoreDelegate: class {
func didPressButton(_ sender: UIButton)
}
class Store: UIView {
weak var delegate:StoreDelegate?
var button: UIButton = {
let button = UIButton()
button.setTitle("button", for: .normal)
button.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
button.backgroundColor = .red
button.addTarget(self, action: #selector(buttonPress(_:)), for: .touchUpInside)
return button
}()
override init(frame: CGRect) {
super.init(frame:frame)
self.addSubview(button)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
#objc func buttonPress(_ sender: UIButton) {
delegate?.didPressButton(sender)
print("here")
}
}
And this is my ViewController:
class ViewController: UIViewController, StoreDelegate{
var testView = Store()
override func viewDidLoad() {
super.viewDidLoad()
testView.delegate = self
self.view.addSubview(testView)
}
func didPressButton(_ sender: UIButton) {
print("Hello")
}
}
Neither it prints "Hello" nor "Here". Maybe I have misunderstood the protocol/delegate pattern.
You need to set constraints or a frame to the view
testView.frame = ///////
It's the base behind receiving actions
You can implement override sizeToFit in Store class to match your needs:
override func sizeToFit() {
frame.size = button.frame.size
}
Then you can call it like:
testView.sizeToFit()
You may consider using autolayout for better sizing.

UIsearchBar input Keyboard Type

Does anyone know how to change the input keyboard type for the searchbar? The code
searchController.searchBar.inputView = input
doesn't work like in a text field. I have read that the subview of the searchBar is a textfield but I don't know how to access that subview to change the inputView.
I think you want to display different keyboard than standard,
Make sure you have assign delegate to keyboard.
class ViewController: UIViewController, UISearchBarDelegate, KeyboardDelegate
{
#IBOutlet weak var searchBar: UISearchBar!
override func viewDidLoad() {
let keyboardView = KeyboardView(frame: CGRect(x: 0, y: 0, width: 375, height: 165))
keyboardView.delegate = self
let searchTextField = searchBar.value(forKey: "_searchField") as! UITextField
searchTextField.inputView = keyboardView
}
func keyWasTapped(text: String) {
searchBar.text = text
}
}
My Custom Keyboard Class
protocol KeyboardDelegate: class {
func keyWasTapped(text: String)
}
class KeyboardView: UIView {
// This variable will be set as the view controller so that
// the keyboard can send messages to the view controller.
weak var delegate: KeyboardDelegate?
// MARK:- keyboard initialization
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initializeSubviews()
}
override init(frame: CGRect) {
super.init(frame: frame)
initializeSubviews()
}
func initializeSubviews() {
let xibFileName = "KeyboardView" // xib extention not included
let view = Bundle.main.loadNibNamed(xibFileName, owner: self, options: nil)?[0] as! UIView
self.addSubview(view)
view.frame = self.bounds
}
// MARK:- Button actions from .xib file
#IBAction func keyTapped(_ sender: UIButton) {
// When a button is tapped, send that information to the
// delegate (ie, the view controller)
self.delegate?.keyWasTapped(text: sender.titleLabel!.text!) // could alternatively send a tag value
}
}
You have to access like this :
if let searchBarTxtField = searchController.searchBar.valueForKey("_searchField") as UITextField {
searchBarTxtField.inputView = input
}

iOS - UIButton become first responder to open keyboard

I need to open keyboard on button click for UIButton (not using/for UITextField). I have tried to create custom button by overriding variable canBecomeFirstResponder but it's not working.
Is there any other way to do so?
Note: I want to set UIPIckerView as an input view of UIButton in key board frame.
Here is my code.
class RespondingButton: UIButton {
override var canBecomeFirstResponder: Bool {
return true
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
// common init
}
}
In my view controller, I connected button action.
class TestViewController: UIViewController {
#IBAction func testBecomeFirstResponder(button: RespondingButton){
button.becomeFirstResponder() // Not working.
}
}
Here is what I would do.
Create transparent textField 1x1px, lets say it is myTextField.
Then add your desired button. In the button action make the myTextField.becomeFirstResponder().
Create view:
let pvBackground: UIView = {
let v = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
v.backgroundColor = .white
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
In viewDidLoad:
pvBackground.addSubview(yourPickerView)//add the picker into the pvBackground
myTextField.inputView = pvBackground
I added the pickerView into the another view to be able to customize it more.
Add conformance to UIKeyInput like this. It should work.
class RespondingButton: UIButton, UIKeyInput {
override var canBecomeFirstResponder: Bool {
return true
}
var hasText: Bool = true
func insertText(_ text: String) {}
func deleteBackward() {}
}

UIElements does not firing on view highrarchy

i added two custom view classes and the elements of that class are addede to viewcontroller class but i cannot accecssing 1st element but i can access second element
hear my code
1st class
class TextField: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
let view=UIView(frame : CGRectMake(8,100,270,47))
let headerText=UILabel(frame : CGRectMake(0,0,view.bounds.width,16))
headerText.text="label"
headerText.textColor=UIColor.blackColor()
headerText.textAlignment=NSTextAlignment.Left
headerText.font = UIFont.systemFontOfSize(13.0)
headerText.numberOfLines = 0
view.addSubview(headerText)
let textField=UITextField(frame : CGRectMake(0,20,view.bounds.width,28))
textField.borderStyle=UITextBorderStyle.RoundedRect
textField.userInteractionEnabled=true
textField.keyboardType=UIKeyboardType.NamePhonePad
view.addSubview(textField)
self.addSubview(view)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
2nd class
protocol ElementDelegate {
func buttonClick(sender:UIButton)
}
class ButtonClass: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
let button=UIButton(frame: CGRectMake(10,50,270,30))
button.setTitle("Click", forState: UIControlState.Normal)
button.backgroundColor=UIColor.blueColor()
button.userInteractionEnabled=true
button.addTarget(self, action: #selector(button_click(_:)), forControlEvents: UIControlEvents.TouchUpInside)
self.addSubview(button)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func button_click(sender:UIButton){
delegate.buttonClick(sender)
}
}
my viewcontroller class
class ViewController: UIViewController,ElementDelegate {
override func viewDidLoad() {
let screenSize:CGRect=UIScreen.mainScreen().bounds
let date = TextField(frame: CGRectMake(0,10,screenSize.width,screenSize.height))
self.view.addSubview(date)
let element = Button(frame: CGRectMake(0,70,screenSize.width,screenSize.height))
element.delegate = self
self.view.addSubview(element)
}
}
when under running i added first textfield view second i added button view but when i click in textbox i cannot accessing it but button is working fine when i remove button textbox working fine why i cannot accessing both one after another
please help me.....
let date = TextField(frame: CGRectMake(0,10,screenSize.width,screenSize.height))
...
let element = Button(frame: CGRectMake(0,10,screenSize.width,screenSize.height))
You've created two subviews with exactly the same frame (size and position). The one you add second will be on top of the other, and will be taking the touch events, even if the button and textfield within them are in different places - a plain UIView will still take touch events.
Why are you making a view subclass that just holds another view inside it in a different position? Why not just position the button and textfield directly?

Create a PopUp in Swift using a custom UIView

I am trying to create a custom UIView and display it as a pop up in my main View using Swift.
My Custom UIView code is
class DatePopUpView: UIView {
var uiView:UIView?
override init() {
super.init()
self.uiView = NSBundle.mainBundle().loadNibNamed("DatePopUpView", owner: self, options: nil)[0] as? UIView
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
required override init(frame: CGRect) {
super.init(frame: frame)
}
}
And I am Calling it in my main view as:
#IBAction func date_button_pressed (sender : AnyObject?) {
var popUpView = DatePopUpView()
var centre : CGPoint = CGPoint(x: self.view.center.x, y: self.view.center.y)
popUpView.center = centre
popUpView.layer.cornerRadius = 10.0
let trans = CGAffineTransformScale(popUpView.transform, 0.01, 0.01)
popUpView.transform = trans
self.view .addSubview(popUpView)
UIView .animateWithDuration(0.5, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
popUpView.transform = CGAffineTransformScale(popUpView.transform, 100.0, 100.0)
}, completion: {
(value: Bool) in
})
}
But popUp is not Coming. I used breakpoint and noticed that value is getting assigned to my popUpView but still it is not displayed on my main View. Please Help
Please Note: I am using StoryBoard for my mainView and custom View i have made using xib.
Without additional description on what you are attempting to do, may I suggest something like the code below? Basically, you can use .hidden feature of a view (or any other control) to show/hide the view. You can set the size and positioning of the view to be popped by using the layout editor.
import UIKit
class ViewController: UIViewController {
var popped = false
var popupBtnTitle = "Show Popup"
#IBAction func popupButton(sender: UIButton) {
popped = !popped
anotherView.hidden = !popped
popupBtnTitle = popped ? "Hide Popup" : "Show Popup"
popupButtonOutlet.setTitle(popupBtnTitle, forState: UIControlState.Normal)
}
#IBOutlet weak var popupButtonOutlet: UIButton!
#IBOutlet weak var anotherView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
popped = false
anotherView.hidden = !popped
popupButtonOutlet.setTitle(popupBtnTitle, forState: UIControlState.Normal)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Resources