Why am I unable to interact with my Button? Swift - ios

I have the code below. I added a button and want something to happen when I press it, but it doesn't seem to work. In this case I want the system to print out "hi" and "hey". I can't seem to figure out the problem. Any help would be appreciated.
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate {
var scrollView: UIScrollView!
var containerView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
var buttonOne: UIButton!
buttonOne = UIButton(type: UIButtonType.System)
buttonOne.setTitle("Level 1", forState: UIControlState.Normal)
buttonOne.frame = CGRectMake(10, 50, 100, 100)
buttonOne.backgroundColor = UIColor.blueColor()
buttonOne.titleLabel?.font = UIFont.systemFontOfSize(17)
buttonOne.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
buttonOne.addTarget(self, action: Selector("clicked:"), forControlEvents: UIControlEvents.TouchUpInside)
self.scrollView = UIScrollView()
self.scrollView.delegate = self
self.scrollView.contentSize = CGSizeMake(0, 1000)
containerView = UIView()
scrollView.addSubview(containerView)
view.addSubview(scrollView)
containerView.addSubview(buttonOne)
}
func clicked(sender: AnyObject){
NSLog("Hey")
print("hi")
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.frame = view.bounds
containerView.frame = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}

You have put the button in a scrollview. Here, the scrollview is a superview of the button and the width of the scrollview and its content size width must be greater than or equal to the button width to take action.

You are setting the containerView's width to 0 by setting its bounds size to the contentSize of the scrollview
self.scrollView.contentSize = CGSizeMake(0, 1000)
then
containerView.frame = CGRectMake(0, 0, scrollView.contentSize.width,
scrollView.contentSize.height)

Related

UIScrollView for ViewController horizontally and vertically

My code tutorial works for scrolling horizontally with ScrollView.
I would like to make it with ViewControllers (instead of views) from my Storyboard.
And I would like to add a vertical ScrollView (To move from center to right or left = ScrollView horizontal, and to move from center to top or bottom (vertically).
Is that possible? Could someone give me a hint ?
Thanks
For information, this is my code :
import UIKit
class ViewController: UIViewController {
lazy var view0: UIView = {
let view = UIView()
view.backgroundColor = .systemTeal
let label = UILabel()
label.text = "Page 0"
label.textAlignment = .center
view.addSubview(label)
label.edgeTo(view: view)
return view
}()
lazy var view1: UIView = {
let view = UIView()
view.backgroundColor = .systemPink
let label = UILabel()
label.text = "Page 1"
label.textAlignment = .center
view.addSubview(label)
label.edgeTo(view: view)
return view
}()
lazy var view2: UIView = {
let view = UIView()
view.backgroundColor = .systemYellow
let label = UILabel()
label.text = "Page 2"
label.textAlignment = .center
view.addSubview(label)
label.edgeTo(view: view)
return view
}()
lazy var views = [view0, view1, view2]
lazy var scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.showsHorizontalScrollIndicator = false
scrollView.isPagingEnabled = true
scrollView.contentSize = CGSize(width: view.frame.width * CGFloat(views.count), height: view.frame.height)
for i in 0..<views.count {
scrollView.addSubview(views[i])
views[i].frame = CGRect(x: view.frame.width * CGFloat(i), y: 0, width: view.frame.width, height: view.frame.height)
}
scrollView.delegate = self
return scrollView
}()
lazy var pageControl: UIPageControl = {
let pageControl = UIPageControl()
pageControl.numberOfPages = views.count
pageControl.currentPage = 0
pageControl.addTarget(self, action: #selector(pageControlTapHandler(sender:)), for: .touchUpInside)
return pageControl
}()
#objc
func pageControlTapHandler(sender: UIPageControl) {
scrollView.scrollTo(horizontalPage: sender.currentPage, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(scrollView)
scrollView.edgeTo(view: view)
view.addSubview(pageControl)
pageControl.pinTo(view)
}
}
extension ViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageIndex = round(scrollView.contentOffset.x / view.frame.width)
pageControl.currentPage = Int(pageIndex)
}

Horizontal Scroll View/Page Control using Buttons

I've made a scroll view with page control using images (so far, so good)... I would like to use (3)buttons instead of images, and store the images in the button. So I can later create functions for each individual button. Having a hard time trying.
heres my code:
import UIKit
class AddImovelVC: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var scrollImageView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
var imageArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
scrollImageView.delegate = self
imageArray = [UIImage(named:"0.png"), UIImage(named:"1.png"), UIImage(named:"2.png")] as! [UIImage]
for i in 0..<imageArray.count{
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleToFill
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x:xPosition, y:0, width: self.scrollImageView.frame.width, height: self.scrollImageView.frame.width)
scrollImageView.contentSize.width = scrollImageView.frame.width * CGFloat(i+1)
scrollImageView.addSubview(imageView)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func scrollViewDidScroll(_ scrollImageView: UIScrollView) {
pageControl.currentPage = Int(scrollImageView.contentOffset.x / CGFloat(375))
}
}
Just change the UIImageView for UIButton inside the for loop, like this
let i = 0
let button = UIButton()
button.setImage(imageArray[i], for: [])
button.imageView?.contentMode = .scaleToFill
let xPosition = self.view.frame.width * CGFloat(i)
button.frame = CGRect(x:xPosition, y:0, width: self.scrollImageView.frame.width, height: self.scrollImageView.frame.width)
scrollImageView.contentSize.width = scrollImageView.frame.width * CGFloat(i+1)
scrollImageView.addSubview(button)
if you want to execute something when the user taps the button, just add button.addTarget(self, action: #selector(nameOfYourFunction), for: .touchUpInside) after creating the button.
You can use UIButton instead of UIImageView.
To set the image, use:
button.setImage(image, for: .normal)
button.setBackgroundImage(image, for: .normal)
To retrieve the image, use:
button.currentImage
button.currentBackgroundImage

How to set the custom inputview of the textview as same height as that of the default keyboard in iOS?

I want the height of custom inputView of the textView to be same height as that of default keyboard. I tried a lot, including:
self.textView.inputView?.autoresizingMask = .flexibleHeight
I couldn't find a solution. It's always coming less than that of default keyboard. (EDIT: This issue exists only for iPhone X)
My code:
class ViewController: UIViewController {
let textView = UITextView()
let button = UIButton()
var keyboardView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
textView.backgroundColor = .lightGray
button.backgroundColor = .red
self.view.addSubview(textView)
self.view.addSubview(button)
}
#objc func buttonAction() {
if self.textView.inputView == nil {
self.textView.inputView = keyboardView
self.textView.inputView?.autoresizingMask = .flexibleHeight
self.textView.reloadInputViews()
} else {
self.textView.inputView = nil
self.textView.reloadInputViews()
}
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
textView.frame = CGRect(x: 0, y: 50, width: self.view.frame.size.width - 50, height: 50)
button.frame = CGRect(x: self.view.frame.size.width - 50, y: 50, width: 50, height: 50)
}
}

How to change the size of titleView in navigation bar. Because there's a gap between titleView and backButton in navigationBar

I've added a search bar to my navigation.titleView
self.navigationItem.titleView = searchBar
There's also a BackBarButtonItem with title = ""
self.navigationItem.backBarButtonItem?.title = ""
But then there're gap between Back Button and SearchBar, like this:
I Think that the gap appears here because there's space for title of backBarButtonItem (because my title is null "" but the space still there)
So I want to ask how to omit that gap? I want to make my searchBar nearer my backBarIcon
Thank you so much!
EDIT 1:
I try to change searchBar's frame but it's not working
This is my code
//Change searchBar's frame
let titleViewFrame = (searchController.searchBar.frame)
searchController.searchBar.frame = CGRect(x: titleViewFrame.minX - 20.0, y: titleViewFrame.minY, width: titleViewFrame.width + 20.0, height: titleViewFrame.height)
override func viewDidLoad() {
super.viewDidLoad()
let container = UIView(frame: CGRect(x: 0, y: 0, width: 1000, height: 22))
let searchBar = UISearchBar()
searchBar.translatesAutoresizingMaskIntoConstraints = false
container.addSubview(searchBar)
let leftButtonWidth: CGFloat = 35 // left padding
let rightButtonWidth: CGFloat = 75 // right padding
let width = view.frame.width - leftButtonWidth - rightButtonWidth
let offset = (rightButtonWidth - leftButtonWidth) / 2
NSLayoutConstraint.activate([
searchBar.topAnchor.constraint(equalTo: container.topAnchor),
searchBar.bottomAnchor.constraint(equalTo: container.bottomAnchor),
searchBar.centerXAnchor.constraint(equalTo: container.centerXAnchor, constant: -offset),
searchBar.widthAnchor.constraint(equalToConstant: width)
])
self.navigationItem.titleView = container
}
You can't do that, there is a default space given which we cannot change if we have back button.
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
self.navigationController?.navigationBar.backIndicatorImage = UIImage(named: "back")
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "back")
self.navigationController?.navigationBar.tintColor = UIColor.lightGray
Below is the screenshot
class SearchBarContainerView: UIView {
let searchBar: UISearchBar
init(customSearchBar: UISearchBar) {
searchBar = customSearchBar
super.init(frame: CGRect.zero)
addSubview(searchBar)
}
override convenience init(frame: CGRect) {
self.init(customSearchBar: UISearchBar())
self.frame = frame
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
searchBar.frame = bounds
}
}
class MyViewController: UIViewController {
func setupNavigationBar() {
let searchBar = UISearchBar()
let searchBarContainer = SearchBarContainerView(customSearchBar: searchBar)
searchBarContainer.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 44)
navigationItem.titleView = searchBarContainer
}
}

Button Not Firing Event Inside ScrollView

UIButtons inside scrollview are not firing event. I tried setting exclusiveTouch delaysTouchesEvent, but nothing helped.
class TestViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
var categoryArr = ["Jack","Mark","Down","Bill","Steve"]
var buttonColors = [UIColor.greenColor(), UIColor.blueColor(), UIColor.blackColor(), UIColor.cyanColor(), UIColor.magentaColor()]
override func viewDidLoad() {
super.viewDidLoad()
let scrollingView = colorButtonsView(CGSizeMake(150,scrollView.frame.size.height), buttonCount: 5)
scrollView.contentSize = scrollingView.frame.size
scrollView.addSubview(scrollingView)
scrollView.showsVerticalScrollIndicator = false
scrollView.delegate = self
scrollView.pagingEnabled = true
scrollView.indicatorStyle = .Default
scrollView.canCancelContentTouches = false
scrollView.delaysContentTouches = false
scrollView.exclusiveTouch = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func colorButtonsView(buttonSize:CGSize, buttonCount:Int) -> UIView {
let buttonView = UIView()
buttonView.frame.origin = CGPointMake(0,0)
let padding = CGSizeMake(10, 10)
buttonView.frame.size.width = (buttonSize.width + padding.width) * CGFloat(buttonCount)
var buttonPosition = CGPointMake(padding.width * 0.5, padding.height)
let buttonIncrement = buttonSize.width + padding.width
for i in 0...(buttonCount - 1) {
var button = UIButton.buttonWithType(.Custom) as! UIButton
button.frame.size = buttonSize
button.frame.origin = buttonPosition
buttonPosition.x = buttonPosition.x + buttonIncrement
button.setTitle(categoryArr[i], forState: UIControlState.Normal)
button.addTarget(self, action: "showTheNextButton:", forControlEvents: UIControlEvents.TouchUpInside)
button.backgroundColor = buttonColors[i]
buttonView.addSubview(button)
}
return buttonView
}
func showTheNextButton(sender:UIButton){
print("ok show the next button")
}
}
extension TestViewController:UIScrollViewDelegate{
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
let index = round(scrollView.contentOffset.x / scrollView.frame.size.width)
print(index)
}
}
A UIButton will not accept touches if it lies outside the bounds of one of its superviews. Make sure all your views are the size and position you expect them to be
Please make the following changes:
self.scrollView.canCancelContentTouches = true
self.scrollView.delaysContentTouches = true
In your for-loop, move your let buttonView = UIView() to:
#IBOutlet weak var scrollView: UIScrollView!
var categoryArr = ["Jack","Mark","Down","Bill","Steve"]
var buttonColors = [UIColor.greenColor(), UIColor.blueColor(), UIColor.blackColor(), UIColor.cyanColor(), UIColor.magentaColor()]
let buttonView = UIView()
Then subsequently, change the following, again, in your for-loop:
Change this line: buttonView.frame.origin = CGPointMake(0,0) to
self.buttonView.frame = self.scrollView.bounds
self.buttonView.userInteractionEnabled = true
Addendum:
Comment this out: //self.scrollView.exclusiveTouch = true
I took the liberty of testing it; touches should get registered on the buttons and scrolling should also work horizontally. Enjoy.

Resources