I am making an iMessage app with images for a keyboard app like custom emojis. I have setup outlets on my iMessage story board and connected the button. In my MessageViewController I have the code below in my IBOulet. I want to resize the image smaller but I can't seem to figure this one out. Any help is greatly appreciated!
#IBAction func button(_ sender: Any) {
label.text = "button pressed"
let layout = MSMessageTemplateLayout()
layout.image = UIImage(named: "270a.png")
let message = MSMessage()
message.layout = layout
activeConversation?.insert(message, completionHandler: nil)
}
When you add an image to message template you can request a width and height, but it will scale the image up or down (respecting the aspect ratio) to a size that it thinks is best.
If the image resource you have isn't the size you want, you can attempt to create a new image in memory, but MSMessageTemplateLayout will modify this as it sees fit.
let original = UIImage(named: "background")
// use CGContext to create new image in memory
// 10 x 10 is super small, so messages app will scale this up
let image = CGSize(width: 10, height: 10).image { context, frame in
original?.draw(in: frame, blendMode: .luminosity, alpha: 1)
}
let message = MSMessage()
let layout = MSMessageTemplateLayout()
layout.image = image
message.layout = layout
self.activeConversation?.insert(message, completionHandler: nil)
I like to use this extension to make it a little easier working with CGContext:
https://gist.github.com/mathewsanders/94ed8212587d72684291483905132790
Related
Is there a way to use UITabBarSystemItem icons with other buttons (e.g. UIButton, UIBarButtonItem) just with code, that is, without using external images?
I found a workaround for this, by accessing UITabBarItem subviews and retrieving the UIImageView that contains the icon.
func getImageFrom(tabBarSystemItem: UITabBarSystemItem, blueColored: Bool) -> UIImage? {
let tabBar = UITabBar()
let item = UITabBarItem(tabBarSystemItem: tabBarSystemItem, tag: 0)
tabBar.items = [item]
if blueColored { // gray otherwise
tabBar.selectedItem = item
}
let itemView = tabBar.subviews[0]
let imageView = itemView.subviews[0] as? UIImageView
//let label = itemView.subviews[1] as? UILabel // this is 'item' label
return imageView?.image
}
Usage:
let buttonImage = getImageFrom(tabBarSystemItem: .more, blueColored: true)
It's worthy to mention that using icons improperly may violate iOS Human Interface Guidelines and cause your app to be rejected from App Store. Read.
I currently have an image set into my UIImageView the following way:
art_image.image = UIImage(named:(artworkPin.title!))
where art_image is the image View and artworkPin.title refers to the name of the image. However, I want to add a second image to the UIImageView if it exists I thought of programming it as
art_image.image = UIImage(named:(artworkPin.title + "1")?)
would this work? In this case I would name a second image the name of the first image but with a '1' on the end. Example: 'Photo.jpeg' and 'Photo1.jpeg' would both be in the image view if Photo1.jpeg existed.
Thanks for your help.
I came across a similar task myself once. What I did was, I created a UIScrollView with the frame of the UIImageView and its contentSize would be imageView.frame.size.width * numberOfImages.
let scrollView = UIScrollView(frame: view.bounds)
view.addSubview(scrollView)
scrollView.contentSize = CGSize(width: scrollView.bounds.size.width * CGFloat(numberOfImages), height: scrollView.bounds.size.height))
for i in 0...<numberOfImages.count-1 {
let imageView = UIImageView(frame: CGRect(x: scrollView.bounds.size.width * CGFloat(i), y: scrollView.bounds.origin.y, width: scrollView.bounds.size.width, height: scrollView.bounds.size.height))
imageView.image = UIImage(named: "artwork" + "\(i)")
scrollView.addSubview(imageView)
}
You can animate it to scroll with a Timer if you want.
scrollView.setContentOffset(scrollPoint, animated: true)
you can only show 1 image inside the imageivew at a time, so if you have the lines as follows:
art_image.image = UIImage(named:(artworkPin.title!))
art_image.image = UIImage(named:(artworkPin.title! + "1")?)
art_image would consist only of Photo1 provided such an image exists and that the artworkPin.title unwrapped is also not nil otherwise you could see some different results.
if you do want to add multiple images to an image view for the purpose of animation, you need to use the animationImages property of UIImageView which takes an array of UIImages for example
art_image.animationImages = [UIImage.init(named:"Photo")!,
UIImage.init(named:"Photo1")!]
Hope this helps
EDIT
var imagesListArray = [UIImage]()
for position in 1...5
{
if let image = UIImage.init(named: ("Photo\(position)"))
{
imagesListArray.append(image)
}
}
art_image.animationImages = imagesListArray
art_image.animationDuration = 3.0
art_image.startAnimating()
This would be a safer a way to add the images so it will ONLY add an image if it is not nil and adds Photo1, Photo2 ..... Photo5
With regards to your other questions:
If you want the user to be able to
What do you mean by animation?
I have added two more lines of code, and it gives this result:
art_image.animationDuration = 1.0
art_image.startAnimating()
It will give you something like this:
If you want the user to swipe, then you need to make some changes such as:
using a scrollview, collectionview for example is the easiest or using a gesture recognizer on swipe you need to change the image
EDIT
Have a look at this example. Imagine each button is your annotation so when I tap it, the image changes.
I have 3 images named Photo11.png, Photo21.png and Photo31.png and this is my code inside the button handler
#IBAction func buttonTapped(_ sender: UIButton)
{
if let image = UIImage.init(named: sender.currentTitle!+"1")
{
art_image.image = image
}
}
As you can see I am setting the image with the title of my button + "1" as so it displays either Photo11.png or Photo21.png etc
I'd like to be able to place a background image behind the three sign-in buttons (for Google, Facebook, and Email) of the FirebaseUI login screen. FirebaseUI login is a drop-in authentication solution for iOS, Android, and Web. I'm having trouble with iOS.
There's a little bit of advice on Github, but not enough.
I first initialize my var customAuthPickerViewController : FIRAuthPickerViewController! near the top of the ViewController.swift file.
Then, this is the function in my ViewController.swift file, but it's not working. When I click the logout button, the app crashes, and no background image is ever shown.
// Customize the sign-in screen to have the Bizzy Books icon/background image
func authPickerViewController(for authUI: FIRAuthUI) -> FIRAuthPickerViewController {
customAuthPickerViewController = authPickerViewController(for: authUI)
backgroundImage = UIImageView(image: UIImage(named: "bizzybooksbee"))
backgroundImage.contentMode = UIViewContentMode.scaleAspectFill
customAuthPickerViewController.view.addSubview(backgroundImage)
return customAuthPickerViewController
}
The background image "bizzybooksbee" is a Universal Image Set with 1x, 2x, and 3x images already loaded in my Assets.xcassets folder.
Here's a picture of what the login screen looks like without trying to implement the background image.
UPDATE: I'm able to get the image to show, with the code I gave in the comments below, but it shows OVER the sign-in buttons, as in the pic below.
Here's an image of the "heirarchy," with Jeffrey's help:
Here's the solution!
Remove the junk that doesn't work from ViewController.swift:
func authPickerViewController(for authUI: FIRAuthUI) -> FIRAuthPickerViewController {
customAuthPickerViewController = authPickerViewController(for: authUI)
backgroundImage = UIImageView(image: UIImage(named: "bizzybooksbee"))
backgroundImage.contentMode = UIViewContentMode.scaleAspectFill
customAuthPickerViewController.view.addSubview(backgroundImage)
return customAuthPickerViewController
}
Create a .swift "subclass" of FIRAuthPickerViewController that you can name anything, and add your background image/customization there:
import UIKit
import FirebaseAuthUI
class BizzyAuthViewController: FIRAuthPickerViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let width = UIScreen.main.bounds.size.width
let height = UIScreen.main.bounds.size.height
let imageViewBackground = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height))
imageViewBackground.image = UIImage(named: "bizzybooksbee")
// you can change the content mode:
imageViewBackground.contentMode = UIViewContentMode.scaleAspectFill
view.insertSubview(imageViewBackground, at: 0)
}}
In your ViewController.swift (or whatever you call it), in the section where you login, change authViewController to equal your new subclass, add a line for the navigation controller, and pass it into the self.present:
let authViewController = BizzyAuthViewController(authUI: authUI!)
let navc = UINavigationController(rootViewController: authViewController)
self.present(navc, animated: true, completion: nil)
I also made a YouTube tutorial which shows how to do this in depth.
I have a UIView canvas which I would like to save a screen shot of it and it's subviews (which are the colorful shapes) on the camera roll when I press the UIBarButton shareBarButton. This works on the simulator, however, it does not produce the image in the way I like:
Ideally what I would like the snapshot to look like (except w/out the carrier, time, & battery status on the top of the screen).
What the snapshot in the camera roll actually looks like.
I want the snapshot to look exactly like the way it looks on the iPhone screen. So if part of the shape goes beyond the screen, the snapshot will capture only the part of the shape that is visible on screen. I also want the snapshot to have the size of the canvas which is basically the size of the view except slightly shorter height:
canvas = UIView(frame: CGRectMake(0, 0, view.bounds.height, view.bounds.height-toolbar.bounds.height))
If someone could tell what I'm doing wrong in creating the snapshot that would be greatly appreciated!
My code:
func share(sender: UIBarButtonItem) {
let masterpiece = canvas.snapshotViewAfterScreenUpdates(true)
let image = snapshot(masterpiece)
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
}
func snapshot(masterpiece: UIView) -> UIImage{
UIGraphicsBeginImageContextWithOptions(masterpiece.bounds.size, false, UIScreen.mainScreen().scale)
masterpiece.drawViewHierarchyInRect(masterpiece.bounds, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
In the first instance I would try snap-shotting the UIWindow to see if that solves your issue:
Here is a UIWindow extension I use (not specifically for camera work) - try that.
import UIKit
extension UIWindow {
func capture() -> UIImage {
UIGraphicsBeginImageContextWithOptions(self.frame.size, self.opaque, UIScreen.mainScreen().scale)
self.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
I call it like:
let window: UIWindow! = UIApplication.sharedApplication().keyWindow
let windowImage = window.capture()
I would like to use Apple's built-in emoji characters (specifically, several of the smileys, e.g. \ue415) in a UILabel but I would like the emojis to be rendered in grayscale.
I want them to remain characters in the UILabel (either plain text or attributed is fine). I'm not looking for a hybrid image / string solution (which I already have).
Does anyone know how to accomplish this?
I know you said you aren't looking for a "hybrid image solution", but I have been chasing this dragon for a while and the best result I could come up with IS a hybrid. Just in case my solution is somehow more helpful on your journey, I am including it here. Good luck!
import UIKit
import QuartzCore
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// the target label to apply the effect to
let label = UILabel(frame: view.frame)
// create label text with empji
label.text = "🍑 HELLO"
label.textAlignment = .center
// set to red to further show the greyscale change
label.textColor = .red
// calls our extension to get an image of the label
let image = UIImage.imageWithLabel(label: label)
// create a tonal filter
let tonalFilter = CIFilter(name: "CIPhotoEffectTonal")
// get a CIImage for the filter from the label image
let imageToBlur = CIImage(cgImage: image.cgImage!)
// set that image as the input for the filter
tonalFilter?.setValue(imageToBlur, forKey: kCIInputImageKey)
// get the resultant image from the filter
let outputImage: CIImage? = tonalFilter?.outputImage
// create an image view to show the result
let tonalImageView = UIImageView(frame: view.frame)
// set the image from the filter into the new view
tonalImageView.image = UIImage(ciImage: outputImage ?? CIImage())
// add the view to our hierarchy
view.addSubview(tonalImageView)
}
}
extension UIImage {
class func imageWithLabel(label: UILabel) -> UIImage {
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0.0)
label.layer.render(in: UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img!
}
}