I would like to add space to the left of the bar button.
So, I add this code.
navbar.autoresizingMask = [.flexibleWidth, .flexibleBottomMargin, .flexibleRightMargin]
navbar.delegate = self
UINavigationBar.appearance().barTintColor = UIColor(red: 0.0/255.0, green:49.0/255.0, blue:79.0/255.0, alpha:0.1)
UINavigationBar.appearance().tintColor = UIColor.white
UINavigationBar.appearance().isTranslucent = true
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName : UIColor.white]
navItem.title = prefs.value(forKey: "PROVIDER_NAME") as! String?
let image = UIImage(named: "back_image")
navItem.leftBarButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(addTapped))
After adding this code, the button image does not show well and looks no good.
Could anyone help me to solve this problem?
Hi Code given below might be useful for you.
extension UIBarButtonItem {
class func itemWith(colorfulImage: UIImage?, target: AnyObject, action: Selector) -> UIBarButtonItem {
let button = UIButton(type: .custom)
button.setImage(colorfulImage, for: .normal)
button.frame = CGRect(x: 0.0, y: 0.0, width: 44.0, height: 44.0)
button.imageEdgeInsets = UIEdgeInsetsMake(0, -50, 0, 0)
button.addTarget(target, action: action, for: .touchUpInside)
let barButtonItem = UIBarButtonItem(customView: button)
return barButtonItem
}
}
You can increase or decrease Left Padding for UIEdgeInsetsMake(0, -50, 0, 0) as per your requirement for left padding.
You can use above extension in your code as describe below.
self.navigationItem.leftBarButtonItem = UIBarButtonItem.itemWith(colorfulImage: UIImage(named: "ic_back")?.withColor(UIColor.white), target: self, action: #selector(btnBackClicked))
func btnBackClicked() {
print("your code here on back button tapped.")
}
Related
I am working with gestures first time here. Please let me know if my approach is wrong or any better solution.
I am trying to delete the collectionView Cell on swiping Left just like UITableview delete function. Deleting works fine. Now what I want is, Once I swipe the cell and tap anywhere on COllectionView it should swipe back to its original position(same like tableview delete row functionality)
I am using/trying this code
Updated viewDidLoad and tapped event
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(tapped(_:)))
self.view.addGestureRecognizer(tap)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let Cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! CustomCell
Cell.backgroundColor = UIColor.white
let leftSwipe = UISwipeGestureRecognizer(target: self, action: #selector(delete(sender:)))
leftSwipe.direction = UISwipeGestureRecognizerDirection.left
Cell.addGestureRecognizer(leftSwipe)
let tap = UITapGestureRecognizer(target: self, action: #selector(tapped(_:)))
Cell.addGestureRecognizer(tap)
Cell.deleteButton.addTarget(self, action: #selector(DeleteCell(sender:)), for: .touchUpInside)
}
func tapped(_ recognizer: UITapGestureRecognizer) {
// self.collectionView.performBatchUpdates({
//self.collectionView.reloadSections(NSIndexSet(index: 0) as IndexSet)
//}, completion: nil)
let point = recognizer.location(in: collectionView)
let indexPath = collectionView.indexPathForItem(at: point)
let cell = self.collectionView.cellForItem(at: indexPath!)
UIView.animate(withDuration: 0.4) {
cell?.contentView.frame = CGRect(x: 0, y: 0, width: (cell?.contentView.frame.width)!, height: (cell?.contentView.frame.height)!)
}
}
func delete(sender: UISwipeGestureRecognizer){
let cell = sender.view as! CustomCell
UIView.animate(withDuration: 0.4) {
cell.contentView.frame = CGRect(x: -90, y: 0, width: cell.contentView.frame.width, height: cell.contentView.frame.height)
}
}
func DeleteCell(sender : AnyObject){
let cell = sender.superview as! CustomCell
let i = self.collectionView.indexPath(for: cell)!.item
let indexpath = self.collectionView.indexPath(for: cell)
let array : NSMutableArray = []
self.collectionView.performBatchUpdates({
self.userArray.remove(at: i)
array.add(indexpath!)
self.collectionView.deleteItems(at:array as! [IndexPath])
}, completion: nil)
}
class CustomCell: UICollectionViewCell {
let deleteButton: UIButton = {
let deleteBtn = UIButton()
deleteBtn.setImage(UIImage(named: "red"), for: .normal)
deleteBtn.contentMode = .scaleAspectFit
return deleteBtn
}()
}
So here I am able to set the cell's position back to original by self.collectionView.performBatchUpdates but its not smooth animation. I tried using
UIView.animate(withDuration: 0.4) {
cell.contentView.frame = CGRect(x: 0, y: 0, width: cell.contentView.frame.width, height: cell.contentView.frame.height)
}
but it works only if swiped cell tapped, not any other cell or anywhere else. Any suggestions would be helpful!!
Right now you are accessing your cell from within itself. The reason it only works to tap on the cell you just swiped is because that is the only cell with that specific instance of UITapGestureRecognizer. To fix this, you should add that tap gesture recognizer to your whole view. Try adding this to your viewDidLoad() method:
let tap = UITapGestureRecognizer(target: self, action: #selector(tapped(_:)))
self.view.addGestureRecognizer(tap)
Finally, got the solution.
Here is the demo project I found - CollectionViewSlideLeft
Hope it will help someone like me. :)
I need to preform username and login checks upon pressing the login button. I need to do all of this with programmatically. Anyhow, my problem is that when I create a button that connects to a function, the textfields are then out of scope.
import UIKit
class ViewController: UIViewController {
var usernameTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let usernameTextField: UITextField = UITextField(frame: CGRect(x: 0, y: 0, width: 300.00, height: 30.00));
usernameTextField.center = CGPoint(x: 160, y: 80)
usernameTextField.placeholder = "username"
usernameTextField.text = ""
usernameTextField.borderStyle = UITextBorderStyle.line
usernameTextField.backgroundColor = UIColor.white
usernameTextField.textColor = UIColor.blue
self.view.addSubview(usernameTextField)
let button = UIButton(type: UIButtonType.system) as UIButton
let xPostion:CGFloat = 10
let yPostion:CGFloat = 200
let buttonWidth:CGFloat = 150
let buttonHeight:CGFloat = 45
button.frame = CGRect(x:xPostion, y:yPostion, width:buttonWidth, height:buttonHeight)
button.backgroundColor = UIColor.lightGray
button.setTitle("Submit", for: UIControlState.normal)
button.tintColor = UIColor.black
button.addTarget(self, action: #selector(ViewController.buttonAction(_:)), for: .touchUpInside)
self.view.addSubview(button)
}
func buttonAction(_ sender:UIButton!) {
let username = usernameTextField.text
print("Username value is \(String(describing: username))!")
print("Button tapped")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
How can I get a usernameTextField at buttonAction function ?
usernameTextField is not out of scope, your app will just crash since you have hidden the property of that name with a local variable inside viewDidLoad.
You should change your let-line to usernameTextField = which does not create a local variable of the same name but assigns something to the property instead:
override func viewDidLoad() {
super.viewDidLoad()
usernameTextField = UITextField(frame: CGRect(x: 0, y: 0, width: 300.00, height: 30.00));
usernameTextField.center = CGPoint(x: 160, y: 80)
usernameTextField.placeholder = "username"
usernameTextField.text = ""
usernameTextField.borderStyle = UITextBorderStyle.line
usernameTextField.backgroundColor = UIColor.white
usernameTextField.textColor = UIColor.blue
self.view.addSubview(usernameTextField)
...
}
I have a simple test application and I want to pan an image inside its view. It will not pan or zoom and I can't see what's wrong with my code.
I have followed this tutorial but implemented it in code. I've made the image width the same as the height so I can pan without necessarily zooming.
Here is my code
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate {
let scrollView: UIScrollView = {
let scrollView = UIScrollView()
return scrollView
}()
let zoomImageView: UIImageView = {
let imageView = UIImageView()
imageView.isUserInteractionEnabled = true
imageView.clipsToBounds = true
imageView.contentMode = .scaleAspectFill
imageView.image = #imageLiteral(resourceName: "lighthouse")
return imageView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let screenSize = UIScreen.main.bounds
let screenHeight = screenSize.height
scrollView.frame = CGRect(x:0, y:0, width: screenHeight, height: screenHeight)
scrollView.delegate = self
scrollView.minimumZoomScale = 1.0
scrollView.maximumZoomScale = 3.0
zoomImageView.frame = CGRect(x:0, y:0, width: screenHeight, height: screenHeight)
scrollView.addSubview(self.zoomImageView)
view.addSubview(scrollView)
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return zoomImageView
}
}
Search in your code for the term contentSize. You don't see it, do you? But the most fundamental fact about how a scroll view works is this: a scroll view without a contentSize cannot scroll (i.e. "pan" as you put it). In particular, it must have a content size larger than its own bounds size in order to be able to scroll along that axis (height or width, or both). Otherwise, there is nothing to scroll.
I want to hide the back button and set a title.
I'm using the following code:
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Einstellungen"
navigationItem.hidesBackButton = true }
But the title isn't shown and the back button is still there but if I touch it nothing happens. Can anybody help me please?
I found a solution on my own.
If I'm setting the title and the hidesBackButton from my previous ViewController everything works fine.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destinationVC = segue.destination as? ViewControllerFirstSettings {
destinationVC.navigationItem.hidesBackButton = true
destinationVC.navigationItem.title = "Einstellungen"
}
}
This code may help :
// MARK: - CUSTOM METHODS
func createNavBar() {
let leftNavigationButton = UIButton()
leftNavigationButton.setImage(UIImage(named: "ic_back.png"), forState: .Normal)
leftNavigationButton.frame = CGRectMake(10, 10, 20, 15)
leftNavigationButton.addTarget(self, action: "onBackButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
let customBarItem = UIBarButtonItem(customView: leftNavigationButton)
self.navigationItem.leftBarButtonItem = customBarItem;
//set TitleAppIcon
let GR = UITapGestureRecognizer(target: self, action: Selector("headerLogoTapAction:"))
let imageView = UIImageView(frame: CGRect(x: 90, y: 0, width: ((UIScreen.mainScreen().bounds.width)/3), height: 40))
imageView.addGestureRecognizer(GR)
imageView.userInteractionEnabled = true
navigationItem.titleView = imageView
}
I have written a class file to create a topBar for my app, I also add in buttons to the top bar after adding target to the buttons added, the same is not triggered
the line menuButton.addTarget(self, action: #selector(showMenu), for: .touchUpInside) does not trigger the function showMenu
I create a TN object(from class TopNav) in the main view file and add it to the view, but the menu button does not trigger the tap
import Foundation
import UIKit
class TopNav{
var topView: UIView = UIView()
var menuButton: UIButton = UIButton()
#objc func showMenu(sender: UIButton!) {
print("show Menu")
}
func position(){
let bounds = UIScreen.main.bounds
let width = bounds.size.width
topView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: width, height: 60.0))
topView.backgroundColor = UIColor.init(colorLiteralRed: 66/255, green: 74/255, blue: 87/255, alpha: 1.0)
menuButton = UIButton(frame: CGRect(x: (width-40), y: 20.0, width: 30.0, height: 30.0))
menuButton.setBackgroundImage( UIImage(named:"menu"), for: .normal)
menuButton.setTitle("", for: UIControlState.normal)
menuButton.addTarget(self, action: #selector(showMenu), for: .touchUpInside)
topView.addSubview(menuButton)
}
}
You may try this.
class TopNav {
func position() {
...
menuButton.addTarget(self, action: #selector(TopNav.showMenu), for: .touchUpInside)
...
}
func showMenu() {
//your code
}
}