I do not know how to convert UILabel to UIImage.[swift] [duplicate] - swift

This question already has answers here:
How to convert a UIView to an image
(24 answers)
Closed 5 years ago.
I am using UITextField.
I enter characters using the keyboard in UITextField.
When I tap the return button on the keyboard, I will display sentences in UILabel.
I would like to convert from UILabel to image after I display the characters in UILabel.
However, I do not know how to convert from UILabel to image.
Is there a better way?
#IBOutlet var messageLabel: UILabel!
#IBOutlet var messageField: UITextField!
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
messageLabel.text = messageField.text
//Here I would like to convert from UILabel to image.
//UILabel → image
}

You can use UIGraphicsBeginImageContextWithOptions to begin an Image context and then you can use UIView method func drawHierarchy(in rect: CGRect, afterScreenUpdates afterUpdates: Bool) -> Bool to draw the label contents on it:
let label = UILabel(frame: CGRect(origin: .zero, size: CGSize(width: 200, height: 50)))
label.text = "StackOverflow"
label.backgroundColor = UIColor.red.withAlphaComponent(0.2)
label.textColor = .blue
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 24)
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0)
label.drawHierarchy(in: label.bounds, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

You can create a new IBOutlet of type UIImage, messageImage, and add the image you want into there. When you want to convert the label use the isHidden function to hide messageLabel and show messageImage.
messageLabel.isHidden = true
messageImage.isHidden = false

Related

not added label to textField like right view

I'm trying to add a label to the text field but nothing is displayed
#IBOutlet weak var myTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let my = UILabel()
myLabel.text = "text"
myLabel.textColor = .black
myTextField.rightView = myLabel
myTextField.rightViewMode = .always
}
Try to add a frame to the label such as myLabel = UILabel(frame: CGRectMake(0, 0, 50, 21)).
Make sure that the Textfield is behind the Label! Besides that it should be showing properly.
set sizeToFit(), in my case it's help

UITextView Horizontal & Vertical Scroll With Proper Cursor Positioning in Swift

I am working on a project where I require to make UITextView horizontally scrollable.The problem statement is defined below
I have tried putting the UITextview within a ScrollView for horizontal scroll as suggested in other similar question solution on Stack Overflow, while the scroll works there are multiple issues related to cursor position like:
Dynamically setting the width of UITextView to match the width of content's biggest line (achievable)
Cursor doesn't show on the screen when content increase or decrease i.e while adding content in same line or deleting content in between, cursor position is not handled by UITextView perfectly the cursor jumps to line start and comes back to current position, and is not visible on screen.
UITextView should only be able to scroll Horizontally or Vertically.(Need to disable the diagonal scroll).
Attaching the current code I am experimenting with, also tried other answers in similar questions, doesn't work.:
class ViewController: UIViewController, UITextViewDelegate, UIScrollViewDelegate {
#IBOutlet weak var scroll:UIScrollView!
#IBOutlet weak var textView:UITextView!
var displayStr = ""
var strSize:CGRect!
var font:UIFont!
var maxSize:CGSize!
override func viewDidLoad() {
super.viewDidLoad()
displayStr = textView.text
textView.delegate = self
scroll.delegate = self
scroll.addSubview(textView)
textView.isEditable = true
textView.isScrollEnabled = false
maxSize = CGSize(width: 9999, height: 9999)
font = UIFont(name: "Menlo", size: 16)!
textView.font = font
updateWidth()
}
func updateWidth() {
strSize = (displayStr as NSString).boundingRect(with: maxSize, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font : font!], context: nil)
if strSize.width > self.view.frame.width {
textView.frame = CGRect(x: 0, y: 0, width: strSize.width + 50, height: view.frame.height+10)
}
scroll.frame = CGRect(x: 0, y: 100, width: view.frame.width, height: view.frame.height)
scroll.contentSize = CGSize(width: strSize.width + 30, height: strSize.height)
}
func textViewDidChange(_ textView: UITextView) {
updateWidth()
}
This is how my output looks

How to add a Show More/Show Less UIButton to control UITextView

I'm using a UITextView to display some contents. Beneath the textView, I added a UIButton that can control if the TextView will display part or all of its content.
Ideally, when button tapped, the TextView will expand its Height to accommodate the length of the content.
I haven't found a good solution. I wonder if I should use UIlabel instead of textView.
You can make this thing working this way:
1. Add a UITextView and UIButton in Storyboard.
2. If you are using Autolayout Constraints, make an outlet of UITextView height.
3. In ViewController class make outlets as:
#IBOutlet var txtView: UITextView!
#IBOutlet var btn_Show: UIButton!
#IBOutlet var textView_HeightConstraint: NSLayoutConstraint!
4. Make a method that will give you height of UITextView according to the text in it.
func getRowHeightFromText(strText : String!) -> CGFloat
{
let textView : UITextView! = UITextView(frame: CGRect(x: self.txtView.frame.origin.x,
y: 0,
width: self.txtView.frame.size.width,
height: 0))
textView.text = strText
textView.font = UIFont(name: "Fira Sans", size: 16.0)
textView.sizeToFit()
var txt_frame : CGRect! = CGRect()
txt_frame = textView.frame
var size : CGSize! = CGSize()
size = txt_frame.size
size.height = 50 + txt_frame.size.height
return size.height
}
5. On Click of Button:
#IBAction func showMore_Button_Clicked(_ sender: UIButton)
{
if sender.tag == 0
{
let height = self.getRowHeightFromText(strText: self.txtView.text)
self.textView_HeightConstraint.constant = height
self.view.layoutIfNeeded()
btn_Show.setTitle("ShowLess", for: .normal)
sender.tag = 1
}
else
{
self.textView_HeightConstraint.constant = 116
self.view.layoutIfNeeded()
btn_Show.setTitle("ShowMore", for: .normal)
sender.tag = 0
}
}
6. If you are not using AutoLayoutConstraints, just change the Frame(Height) of UITextView on click of UIButton. No need of "textView_HeightConstraint"
#IBAction func showMore_Button_Clicked(_ sender: UIButton)
{
if sender.tag == 0
{
let height = self.getRowHeightFromText(strText: self.txtView.text)
self.txtView.frame = CGRect(x: self.txtView.frame.origin.x, y: self.txtView.frame.origin.y, width: self.txtView.frame.size.width, height: height)
btn_Show.setTitle("ShowLess", for: .normal)
sender.tag = 1
}
else
{
self.txtView.frame = CGRect(x: self.txtView.frame.origin.x, y: self.txtView.frame.origin.y, width: self.txtView.frame.size.width, height: 116)
btn_Show.setTitle("ShowMore", for: .normal)
sender.tag = 0
}
}

iOS - add image and text in title of Navigation bar

I would like to create a nav bar similar to what's in the image that's attached.
The title of the nav bar will be a combination of an image and text.
Should this be done per any best practice?
How can it be done?
As this answer shows, the easiest solution is to add the text to your image and add that image to the navigation bar like so:
var image = UIImage(named: "logo.png")
self.navigationItem.titleView = UIImageView(image: image)
But if you have to add text and an image separately (for example, in the case of localization), you can set your navigation bar's title view to contain both image and text by adding them to a UIView and setting the navigationItem's title view to that UIView, for example (assuming the navigation bar is part of a navigation controller):
// Only execute the code if there's a navigation controller
if self.navigationController == nil {
return
}
// Create a navView to add to the navigation bar
let navView = UIView()
// Create the label
let label = UILabel()
label.text = "Text"
label.sizeToFit()
label.center = navView.center
label.textAlignment = NSTextAlignment.Center
// Create the image view
let image = UIImageView()
image.image = UIImage(named: "Image.png")
// To maintain the image's aspect ratio:
let imageAspect = image.image!.size.width/image.image!.size.height
// Setting the image frame so that it's immediately before the text:
image.frame = CGRect(x: label.frame.origin.x-label.frame.size.height*imageAspect, y: label.frame.origin.y, width: label.frame.size.height*imageAspect, height: label.frame.size.height)
image.contentMode = UIViewContentMode.ScaleAspectFit
// Add both the label and image view to the navView
navView.addSubview(label)
navView.addSubview(image)
// Set the navigation bar's navigation item's titleView to the navView
self.navigationItem.titleView = navView
// Set the navView's frame to fit within the titleView
navView.sizeToFit()
Use horizontal UIStackView should be much cleaner and easier
Please add the next extension to UIViewController
extension UIViewController {
func setTitle(_ title: String, andImage image: UIImage) {
let titleLbl = UILabel()
titleLbl.text = title
titleLbl.textColor = UIColor.white
titleLbl.font = UIFont.systemFont(ofSize: 20.0, weight: .bold)
let imageView = UIImageView(image: image)
let titleView = UIStackView(arrangedSubviews: [imageView, titleLbl])
titleView.axis = .horizontal
titleView.spacing = 10.0
navigationItem.titleView = titleView
}
}
then use it inside your viewController:
setTitle("yourTitle", andImage: UIImage(named: "yourImage"))
(this will align the text and the icon together to the center, if you want the text to be centered and the icon in the left, just add an empty UIView with width constraint equal to the icon width)
here is my 2 cents for Swift 4, since accepted answer didn't work for me (was mostly off the screen):
// .. in ViewController
var navBar = CustomTitleView()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// =================== navBar =====================
navBar.loadWith(title: "Budget Overview", leftImage: Images.pie_chart)
self.navigationItem.titleView = navBar
}
class CustomTitleView: UIView
{
var title_label = CustomLabel()
var left_imageView = UIImageView()
override init(frame: CGRect){
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder){
super.init(coder: aDecoder)
setup()
}
func setup(){
self.addSubview(title_label)
self.addSubview(left_imageView)
}
func loadWith(title: String, leftImage: UIImage?)
{
//self.backgroundColor = .yellow
// =================== title_label ==================
//title_label.backgroundColor = .blue
title_label.text = title
title_label.font = UIFont.systemFont(ofSize: FontManager.fontSize + 5)
// =================== imageView ===================
left_imageView.image = leftImage
setupFrames()
}
func setupFrames()
{
let height: CGFloat = Navigation.topViewController()?.navigationController?.navigationBar.frame.height ?? 44
let image_size: CGFloat = height * 0.8
left_imageView.frame = CGRect(x: 0,
y: (height - image_size) / 2,
width: (left_imageView.image == nil) ? 0 : image_size,
height: image_size)
let titleWidth: CGFloat = title_label.intrinsicContentSize.width + 10
title_label.frame = CGRect(x: left_imageView.frame.maxX + 5,
y: 0,
width: titleWidth,
height: height)
contentWidth = Int(left_imageView.frame.width)
self.frame = CGRect(x: 0, y: 0, width: CGFloat(contentWidth), height: height)
}
var contentWidth: Int = 0 //if its CGFloat, it infinitely calls layoutSubviews(), changing franction of a width
override func layoutSubviews() {
super.layoutSubviews()
self.frame.size.width = CGFloat(contentWidth)
}
}
Swift 4.2 + Interface Builder Solution
As a follow-on to Lyndsey Scott's answer, you can also create a UIView .xib in Interface Builder, use that to lay out your title and image, and then update it on-the-fly via an #IBOutlet. This is useful for dynamic content, internationalization, maintainability etc.
Create a UIView subclass with a UILabel outlet and assign your new .xib to this class:
import UIKit
class FolderTitleView: UIView {
#IBOutlet weak var title : UILabel!
/// Create an instance of the class from its .xib
class func instanceFromNib() -> FolderTitleView {
return UINib(nibName: "FolderTitleView", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! FolderTitleView
}
}
Connect the label to your outlet (title in my example) in your .xib, then in your UIViewController:
/// Reference to the title view
var folderTitleView : FolderTitleView?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Set the screen title to match the active folder
updateTitle()
}
/// Updates the title of the navigation controller.
func updateTitle() {
self.title = ""
if folderTitleView == nil {
folderTitleView = FolderTitleView.instanceFromNib()
self.navigationItem.titleView = folderTitleView
}
folderTitleView!.title.text = "Listening"
folderTitleView!.layoutIfNeeded()
}
This results in a nice self-centering title bar with an embedded image that you can easily update from code.
// worked for me
create a view and set the frame
now add the image in the view and set the frame
after adding the image, add the label in same view and set the frame
after adding the image and label to view, add same view to navigationItem
let navigationView = UIView(frame: CGRect(x: 0, y: 0, width: 50 , height: 55))
let labell : UILabel = UILabel(frame: CGRect(x: -38, y: 25, width: 150, height: 25))
labell.text = "Your text"
labell.textColor = UIColor.black
labell.font = UIFont.boldSystemFont(ofSize: 10)
navigationView.addSubview(labell)
let image : UIImage = UIImage(named: ValidationMessage.headerLogoName)!
let imageView = UIImageView(frame: CGRect(x: -20, y: 0, width: 100, height: 30))
imageView.contentMode = .scaleAspectFit
imageView.image = image
//navigationItem.titleView = imageView
navigationView.addSubview(imageView)
navigationItem.titleView = navigationView

Changing the color of the icons in a UItextField inside a UISearchBar

I'm trying to customise the appearance of the search bar in my search controller.
Setting the background and text colors works fine but I just didn't find a way to change the color of the icons in the text field, specifically the magnifying glass and the x button.
I've found this Objective-C code which should do what I want but I'm struggling to translate it to Swift:
(EDIT: Skip to the first answer for the working Swift 3 solution.)
UITextField *searchBarTextField = [self.searchDisplayController.searchBar valueForKey:#"_searchField"];
// Magnifying glass icon.
UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView;
leftImageView.image = [LeftImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
leftImageView.tintColor = [UIColor whiteColor];
// Clear button
UIButton *clearButton = [searchBarTextField valueForKey:#"_clearButton"];
[clearButton setImage:[clearButton.imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];
clearButton.tintColor = [UIColor whiteColor];
My attempt to translate to Swift:
let textField = searchController.searchBar.valueForKey("searchField") as! UITextField
// These two work fine.
textField.backgroundColor = UIColor.blackColor()
textField.textColor = UIColor.blackColor()
var glassIcon = textField.leftView
// This would work.
//glassIcon.hidden = true
// This does not have any effect.
//glassIcon?.tintColor = UIColor.whiteColor()
// My attempt to translate, but it gives an error.
glassIcon.image? = UIImage.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
var clearButton = textField.valueForKey("clearButton")!
clearButton.setImage(clearButton.imageWithRenderingMode(.AlwaysTemplate), forState: .Normal)
// This gives the error: "Cannot assign to property: 'clearButton' is immutable
clearButton.tintColor = UIColor.whiteColor()
// Sorry for the weird formatting, it glitches here in the editor.
The leftView does not seem to have an image property. How can I access that property as the Objective-C code does?
Also, if there is a better to achieve what I want please let me know.
Here is the solution:
// Text field in search bar.
let textField = searchController.searchBar.value(forKey: "searchField") as! UITextField
let glassIconView = textField.leftView as! UIImageView
glassIconView.image = glassIconView.image?.withRenderingMode(.alwaysTemplate)
glassIconView.tintColor = UIColor.white
let clearButton = textField.valueForKey("clearButton") as! UIButton
clearButton.setImage(clearButton.imageView?.image?.withRenderingMode(.alwaysTemplate), for: .normal)
clearButton.tintColor = UIColor.white
Here is the solution:
extension UITextField{
func setLeftIcon(_ icon: UIImage) {
let padding = 8
let size = 20
let outerView = UIView(frame: CGRect(x: 0, y: 0, width: size+padding, height: size) )
let iconView = UIImageView(frame: CGRect(x: padding, y: 0, width: size, height: size))
iconView.image = icon.withRenderingMode(.alwaysTemplate)
iconView.tintColor = UIColor.white
outerView.addSubview(iconView)
leftView = outerView
leftViewMode = .always
}
}