iOS: UITextField's inputAccessoryView is not updated after rotating - ios

I have written a custom UITextField, and added a button above the keyboard using the inputAccessoryView.
Here is the code:
class CustomTextField: UITextField {
var button: UIButton?
var buttonContainer: UIView?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
redraw()
}
override init(frame: CGRect) {
super.init(frame: frame)
redraw()
}
private func redraw() {
button = UIButton()
button?.setTitle("BUTTON TEST", for: .normal)
button?.backgroundColor = .red
let dividend: CGFloat = isPortraitOrientation ? 56 : 1
let divisor: CGFloat = isPortraitOrientation ? 326 : 18
let buttonHeight = ((UIScreen.main.bounds.width - 48) * dividend) / divisor
button?.frame = CGRect(origin: CGPoint(x: 24, y: 0), size: CGSize(width: UIScreen.main.bounds.width - 48, height: buttonHeight))
buttonContainer = UIView()
buttonContainer?.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: buttonHeight + 10)
buttonContainer?.backgroundColor = .clear
inputAccessoryView = buttonContainer!
buttonContainer?.addSubview(button!)
}
func updateView() {
redraw()
}
}
And in the controller:
class CustomViewController: UIViewController {
#IBOutlet weak var textField: CustomTextField!
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: nil) { _ in
self.textField.updateView()
}
}
}
Both button and buttonContainer are displayed correctly when I first rotate the screen, then begin editing the text field. But they are not correctly redrawn when rotating the phone.
Thanks for your help.

Related

How to change navigationBar height & use custom view

I have a custom navigationBar view like this.
And I use sizeThatFits seems not work.
How to achieve this?
class ListVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let height: CGFloat = 140
let bounds = self.navigationController?.navigationBar.bounds
self.navigationController?.navigationBar.frame = CGRect(x: 0, y: 0, width: bounds?.width ?? UIScreen.main.bounds.width, height: height)
}
}
class CustomNavi: UINavigationBar {
override init(frame: CGRect) {
super.init(frame: frame)
self.commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
self.commonInit()
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
return CGSize(width: UIScreen.main.bounds.width, height: 140)
}
private func commonInit() {
let bundle = Bundle.init(for: CustomNavi.self)
if let viewToAdd = bundle.loadNibNamed("CustomNavi", owner: self, options: nil), let contentView = viewToAdd.first as? UIView {
addSubview(contentView)
contentView.frame = self.bounds
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
}
}

when using CHTWaterfallLayout ,In My collection view cell , subview is not placing properly specially Y co-ordinate.scrolling makes it worse

this is the code where i am configuring the cell.
cell.configure(image: models[indexPath.item].image, tagText: models[indexPath.item].tag, priceIcon: models[indexPath.item].priceIcon, value: models[indexPath.item].price)
and this is my code for cell.
//
// ImageCollectionViewCell.swift
// tr0ve-iOSApp
//
//
//
// ImageCollectionViewCell.swift
// MyCollectionView
//
import UIKit
class ImageCollectionViewCell: UICollectionViewCell {
static let identifier = "ImageCollectionViewCell"
let itemView = UIView()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(itemView)
contentView.clipsToBounds = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
itemView.frame = contentView.bounds
}
override func prepareForReuse() {
super.prepareForReuse()
itemView.subviews.forEach { view in
view.removeFromSuperview()
}
}
func configure (image: UIImage?, tagText: String, priceIcon: UIImage, value: Float){
let imageView = UIImageView(image: image)
let priceTagView = UIView(frame: CGRect(x: 5, y: contentView.frame.size.height-50, width: 60, height: 20))
priceTagView.backgroundColor = .black
let valueLabel = UILabel(frame: CGRect(x: 20, y: 5, width: 35, height: 10))
valueLabel.textColor = .white
valueLabel.text = String(value)
valueLabel.font = UIFont.systemFont(ofSize: 12, weight: .regular)
let priceIconView = UIImageView(frame: CGRect(x: 5, y: 5, width: 10, height: 10))
priceIconView.image = priceIcon
priceTagView.addSubview(priceIconView)
priceTagView.addSubview(valueLabel)
let tag = UILabel(frame: CGRect(x: 100, y: contentView.frame.size.height-50, width: 20, height: 20))
tag.text = tagText
tag.textColor = .white
tag.textAlignment = .center
if tagText == "UC" {
tag.backgroundColor = .green
}
else {
tag.backgroundColor = .blue
}
itemView.addSubview(imageView)
itemView.addSubview(priceTagView)
itemView.addSubview(tag)
}
}
[in this image i want to add subview in cell's bottom, and in tried it using image's frame and by contentView's frame. but it is doing good for some cells and bad for the other ones. and when i scroll everyhing meshes up.1

Button and Image Alignment issues in UIButton

So I have a UIBarbuttonItem that I am currently designing based off of a layout that I have done.
import Foundation
import UIKit
class LocationManager: UIBarButtonItem {
var viewController: MainViewController?
lazy var customButton : UIButton = {
let customButton = UIButton(type: .system)
customButton.setImage(UIImage(named: "downArrow"), for: .normal)
customButton.imageEdgeInsets = UIEdgeInsetsMake(0, 20, 0, -10)
guard let customFont = UIFont(name: "NoirPro-SemiBold", size: 20) else {
fatalError("""
Failed to load the "CustomFont-Light" font.
Make sure the font file is included in the project and the font name is spelled correctly.
"""
)
}
customButton.semanticContentAttribute = UIApplication.shared
.userInterfaceLayoutDirection == .rightToLeft ? .forceLeftToRight : .forceRightToLeft
customButton.titleLabel?.font = customFont
customButton.setTitleColor(UIColor.black, for: .normal)
return customButton
}()
override init() {
super.init()
setupViews()
}
#objc func setupViews(){
customView = customButton
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
I correctly do the job of using both an image and title and setting the image insets for the button and on load the appearance is great. However, when I leave the screen and come back it seems as though everything is thrown out of wack the image gets moved back and sometimes there will be two images and one will have a distorted size.
Is there anything wrong with my custom button implementation that I am missing.
I have included images for before and after
I suggest you to make your custom button class, then make title and image by adding subviews. In this case UIImageView and UILabel. Because UIButton inherits from UIView you can easy do this. I've never had problems using this way.
Here is the code I've written for you:
import UIKit
class ViewController: UIViewController {
lazy var customButton: CustomButton = {
let button = CustomButton(frame: CGRect(x: 50,
y: 200,
width: view.frame.width - 100,
height: 50))
// This mask for rotation
button.autoresizingMask = [.flexibleLeftMargin,
.flexibleRightMargin,
.flexibleTopMargin,
.flexibleBottomMargin]
button.attrTitleLabel.text = "San Francisco, CA"
button.addTarget(self, action: #selector(chooseCity), for: .touchUpInside)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
view.addSubview(customButton)
}
#objc func chooseCity() {
print("Choose city button has pressed")
}
}
class CustomButton: UIButton {
private let arrowImageSize: CGSize = CGSize(width: 20, height: 20)
private let sideOffset: CGFloat = 10
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
addSubview(attrTitleLabel)
addSubview(arrowImageView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
lazy var attrTitleLabel: UILabel = {
let label = UILabel()
label.font = UIFont(name: "NoirPro-SemiBold", size: 20)
label.textColor = .black
return label
}()
lazy var arrowImageView: UIImageView = {
let iv = UIImageView()
iv.image = UIImage(named: "arrow_down")
iv.contentMode = .scaleAspectFit
return iv
}()
override func layoutSubviews() {
super.layoutSubviews()
arrowImageView.frame = CGRect(x: self.frame.width - arrowImageSize.width - sideOffset,
y: self.frame.height/2 - arrowImageSize.height/2,
width: arrowImageSize.width,
height: arrowImageSize.height)
attrTitleLabel.frame = CGRect(x: sideOffset, y: 0, width: self.frame.width - sideOffset*2 - arrowImageSize.width, height: self.frame.height)
}
}
How it looks:

Didn't tapped on textfield

I create programmatically custom textfield
import UIKit
class SearchTextField: UITextField, UITextFieldDelegate {
let padding = UIEdgeInsets(top: 0, left: 40, bottom: 0, right: 5);
init(frame: CGRect, tintText: String, tintFont: UIFont, tintTextColor: UIColor) {
super.init(frame:frame)
self.frame = frame
delegate = self
backgroundColor = .white
textColor = tintTextColor
placeholder = tintText
font = tintFont
createBorder()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
delegate = self
}
func createBorder() {
self.layer.cornerRadius = 6
self.layer.borderColor = UIColor(red: 169/255, green: 169/255, blue: 169/255, alpha: 1).cgColor
self.layer.borderWidth = 1
}
override func textRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
}
and add it like a subview to my view which is a subview of Google maps view
import UIKit
import GoogleMaps
class MapViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var mapView: GMSMapView!
var customSearchBar: SearchTextField!
let searchBarTextColor = UIColor(red: 206, green: 206, blue: 206, alpha: 1)
override func viewDidLoad() {
super.viewDidLoad()
let camera = GMSCameraPosition.camera(withLatitude: 55.75, longitude: 37.62, zoom: 13.0)
mapView.camera = camera
mapView.isUserInteractionEnabled = true
addTopBarView(mapView: mapView)
}
func addTopBarView(mapView: GMSMapView) {
//heigt of topBar is 14% of height of view^ width is the same
let topBarFrame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height * 0.14)
let topBarView = UIView(frame: topBarFrame)
addTopBarViewBackground(view: topBarView)
addTitleForTopBarView(view: topBarView)
addProfileIconForTopBarView(view: topBarView)
addSettingsIconForTopBarView(view: topBarView)
addSearchBar(view: topBarView)
topBarView.isUserInteractionEnabled = true
mapView.addSubview(topBarView)
}
func addSearchBar(view: UIView) {
let frameCustomSearchBar = CGRect(x: 10, y: 45, width: view.frame.width - 20, height: 40)
let fontCustomSearchBar = UIFont(name: "HelveticaNeueCyr", size: 28) ?? UIFont.italicSystemFont(ofSize: 14)
let textColorCustomSearchBar = UIColor(red: 206/255, green: 206/255, blue: 206/255, alpha: 1)
customSearchBar = SearchTextField(frame: frameCustomSearchBar, tintText: NSLocalizedString("find_petrole", comment: ""), tintFont: fontCustomSearchBar, tintTextColor: textColorCustomSearchBar)
customSearchBar.delegate = self
customSearchBar.isUserInteractionEnabled = true
customSearchBar.isEnabled = true
let iconPinView = UIImageView(image: #imageLiteral(resourceName: "icon_pin"))
iconPinView.frame = CGRect(x: 10, y: 10, width: 12, height: 20)
customSearchBar.addSubview(iconPinView)
let iconAddView = UIImageView(image: #imageLiteral(resourceName: "icon_add"))
iconAddView.frame = CGRect(x: customSearchBar.frame.width - 34, y: 10, width: 20, height: 20)
customSearchBar.addSubview(iconAddView)
view.addSubview(customSearchBar)
}
The textfield(customSearchBar) i see but it doesn't clickable, when i tapped on it nothing happens. I saw a few such problems here but did not find anything that help me.
You need inspect UIView Hierarchy using View Debugging feature of xcode and you need to check that textfield does not overlap with other view.
Run the app. View Debugging works in the simulator and on devices, but it's important to note that it needs to be an iOS 8 simulator or device. That said, you may allow earlier deployment targets in your project, just make sure you run on iOS 8 when you try View Debugging.
Navigate to the screen/view that you want to inspect within the running app.
In the Navigators Panel (left column), select the Debug Navigator (sixth tab). Next to your process, you'll see two buttons – press the rightmost button and select View UI Hierarchy
I guess it's because you put the UITextField under other touchable views so the touch event was intercepted.
if you make the custom textField hierarchy by a non-defalut isUserInteractionEnabled object, remember to enable it.

Dismissing of search bar

I have some problem. I have UITableView and header of tableView is searchController with 1 red view (Inside of this view will be some icon).
After staring of search appears cancel button.
And now I press cancel button and search bar resize to full screen size and red view is disappear.
How to solve this problem?
Here is my headerView class:
lazy var searchController = UISearchController(searchResultsController: nil).then {
//return UISearchController().then {
$0.dimsBackgroundDuringPresentation = false
$0.searchBar.placeholder = "Искать по имени"
$0.searchBar.tintColor = .black
$0.searchBar.searchBarStyle = .minimal
$0.searchBar.backgroundColor = .white
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes([NSFontAttributeName : UIFont.appleSystemRegular(15)], for: .normal)
$0.searchBar.setValue("Отмена", forKey:"_cancelButtonText")
}
lazy var contentView: UIView = {
let view = UIView()
view.backgroundColor = .red
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
setupConstrains()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
fileprivate func setupViews() {
addSubview(contentView)
addSubview(searchController.searchBar)
}
func setupConstrains() {
searchController.searchBar.frame = CGRect(x: 0, y: 0, width: self.frame.width - 80, height: 44)
contentView.frame = CGRect(x: self.frame.width - 65, y: 0, width: 50, height: 44)
}
Remove searchcontroller and try to search only searchbar delegate.
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
}

Resources