我的应用允许用户选择相机拍照或创建视频,或者从图书馆/画廊中选择添加贴纸(覆盖图像)。
如果我先选择“相机”,请触摸“取消”按钮,然后选择“图书馆/画廊”,“取消”选项不会显示。
如果我首先选择“图书馆/画廊”,则“取消”按钮可见。
这是ViewController.swift文件的代码:
import UIKit
import MobileCoreServices
import Photos
class ViewController: UIViewController {
var imagePicker:UIImagePickerController!
override func viewDidLoad() {
super.viewDidLoad()
self.imagePicker = UIImagePickerController()
self.imagePicker.delegate=self
self.imagePicker.mediaTypes = ["public.image", "public.movie"]
}
@IBAction func camera(_ sender: Any) {
self.imagePicker.sourceType = .camera
self.present(self.imagePicker, animated: true, completion: nil)
}
@IBAction func gallery(_ sender: Any) {
self.imagePicker.sourceType = .photoLibrary
self.present(self.imagePicker, animated: true, completion: nil)
}
}
extension ViewController:UIImagePickerControllerDelegate, UINavigationControllerDelegate{
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
let video = info[UIImagePickerController.InfoKey.mediaURL] as? URL
let editController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "edit") as! EditViewController
self.dismiss(animated: true) {
editController.image = image
editController.video = video
self.present(editController, animated: true, completion: nil)
}
}
}
这是EditViewController.swift的代码:
import UIKit
import SwiftyImage
import Photos
import MediaWatermark
import Firebase
import Kingfisher
import MBProgressHUD
class EditViewController: UIViewController,UIScrollViewDelegate {
@IBOutlet weak var colorPalletButton: UIButton!
@IBOutlet weak var frameImageView: UIImageView!
@IBOutlet weak var frameButton: UIButton!
@IBOutlet weak var collection: UICollectionView!
@IBOutlet weak var canvasView: UIView!
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var orignalImage: UIImageView!
@IBOutlet weak var indicator: UIImageView!
var image:UIImage?
var video:URL?
private var stickerView: UIImageView!
private var stickerViewNeedsFirstResetPose = true
var stickerPanGesture:UIPanGestureRecognizer!
var stickerPinchGesture:UIPinchGestureRecognizer!
var stickerRotateGesture:UIRotationGestureRecognizer!
var stickerTapGesture:UITapGestureRecognizer!
private var frames = ["frames-1","frames-2","frames-3","frames-4"]
private var colors = ColorPallet.colors
private var stickers = [String]()
private var message:String?
private var selection = 1
private var stickersArray = [UIImageView]()
private var transparentImage:UIImage?
var playerLayer:AVPlayerLayer!
var player: AVPlayer! = nil
override func viewDidLoad() {
super.viewDidLoad()
self.collection.isHidden = true
self.indicator.alpha=0
scrollView.backgroundColor = UIColor.black
scrollView.contentOffset = CGPoint(x: 500, y: 1200)
scrollView.delegate = self
self.collection.register(UINib(nibName: "Frame", bundle: nil), forCellWithReuseIdentifier: "frame")
self.collection.layer.cornerRadius = 5
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: self.view.frame.width/3, height: self.view.frame.width/3)
layout.minimumInteritemSpacing = 10
layout.minimumLineSpacing = 10
layout.scrollDirection = .horizontal
collection.collectionViewLayout = layout
//for video
if self.image == nil{
print(self.video!)
let img = self.getThumbnailFrom(path: self.video!)
self.orignalImage.image = img
self.frameButton.isHidden = true
self.colorPalletButton.isHidden=true
}else{
self.orignalImage.image = self.image
}
Database.database().reference().child("stickers").observe(.childAdded) { (snap) in
let obj = snap.value as! [String:String]
let stickerUrl = obj["stickerURL"]
self.stickers.append(stickerUrl!)
self.collection.reloadData()
}
Database.database().reference().child("message").observe(.value) { (snap) in
let obj = snap.value as! [String:String]
let message = obj["message"]
self.message = message
}
}
func playVideo(url: URL, view: UIView) {
player = AVPlayer(url: url)
playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = view.bounds
view.layer.addSublayer(playerLayer)
player.play()
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.orignalImage!
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.setZoomScale()
if stickerViewNeedsFirstResetPose {
stickerViewNeedsFirstResetPose = false
}
}
func setZoomScale() {
var minZoom = min(self.view.bounds.size.width / self.orignalImage!.bounds.size.width, self.view.bounds.size.height / self.orignalImage!.bounds.size.height);
if (minZoom > 1.0) {
minZoom = 1.0;
}
scrollView.minimumZoomScale = minZoom;
scrollView.zoomScale = minZoom;
}
@IBAction func frameButton(_ sender: UIButton) {
self.selection = 1
self.collection.isHidden = false
self.indicator.alpha=1
UIView.animate(withDuration: 0.1) {
self.indicator.center.x = sender.frame.midX
}
self.collection.reloadData()
}
@IBAction func colorPalletButton(_ sender: UIButton) {
self.selection = 2
self.collection.isHidden = false
self.indicator.alpha=1
UIView.animate(withDuration: 0.1) {
self.indicator.center.x = sender.frame.midX
}
self.collection.reloadData()
}
@IBAction func stickersButton(_ sender: UIButton) {
self.selection = 3
self.collection.isHidden = false
self.indicator.alpha=1
UIView.animate(withDuration: 0.1) {
self.indicator.center.x = sender.frame.midX
}
self.collection.reloadData()
}
@IBAction func tap(_ sender: Any) {
self.collection.isHidden = true
self.indicator.alpha=0
}
@IBAction func close(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
@IBAction func done(_ sender: Any) {
//for video
if self.image == nil {
let hud = MBProgressHUD.showAdded(to: self.view, animated: true)
hud.label.text = "Loading..."
let img = self.getThumbnailFrom(path: self.video!)
self.transparentImage = UIImage.size(width: img!.size.width, height: img!.size.height)
.color(.clear)
.image
let resultImage = self.mergedImage()!
if let item = MediaItem(url: self.video!) {
let logoImage = resultImage
let firstElement = MediaElement(image: logoImage)
firstElement.frame = CGRect(x: 0, y: 0, width: logoImage.size.width, height: logoImage.size.height)
item.add(elements: [firstElement])
let mediaProcessor = MediaProcessor()
mediaProcessor.processElements(item: item) { [weak self] (result, error) in
encodeVideo(videoUrl: result.processedUrl!, resultClosure: { (convertedUrl) in
DispatchQueue.main.async {
hud.hide(animated: true)
self?.showAlert(title: "Share", message: "Please select to share with ?", completion: { (press) in
if press == "Instagram" {
self?.shareBackgroundImage(video: convertedUrl!)
}else if press == "Others"{
let activity = UIActivityViewController(activityItems: [convertedUrl!,self!.message!], applicationActivities: [])
self?.present(activity, animated: true, completion: nil)
}
})
}
})
}
}
}else{
//for image
self.showAlert(title: "Share", message: "Please select to share with ?", completion: { (press) in
let processedImage = self.canvasView.takeScreenshot()
if press == "Instagram" {
self.shareBackgroundImage( image: processedImage)
}else if press == "Others"{
let activity = UIActivityViewController(activityItems: [processedImage,self.message!], applicationActivities: [])
self.present(activity, animated: true, completion: nil)
}
})
}
}
private func makeStickerView(with image: UIImage, center: CGPoint) -> UIImageView {
let heightOnWidthRatio = image.size.height / image.size.width
let imageWidth: CGFloat = 100
let view = UIImageView(frame: CGRect(x: 0, y: 0, width: imageWidth, height: imageWidth * heightOnWidthRatio))
view.image = image
view.clipsToBounds = true
view.contentMode = .scaleAspectFit
view.isUserInteractionEnabled = true
//for video
if self.image == nil{
self.frameImageView.bringSubviewToFront(view)
// view.center = CGPoint(x: self.orignalImage.image!.size.width/2, y: self.orignalImage.image!.size.height/2)
view.transform = CGAffineTransform(translationX: self.frameImageView.center.x, y: self.frameImageView.center.y)
}else{
view.center = self.frameImageView.center
}
return view
}
func shareBackgroundImage(image:UIImage?=nil,video:URL?=nil) {
if let img = image{
if let pngImage = img.pngData() {
backgroundImage(pngImage, attributionURL: "")
}
}
if let v = video {
if let videoHolder = try? Data(contentsOf: v){
self.backgroundVideo(videoHolder, attributionURL: "")
}
}
}
func backgroundImage(_ backgroundImage: Data, attributionURL: String) {
guard let urlScheme = URL(string: "instagram-stories://share"),
UIApplication.shared.canOpenURL(urlScheme) else {
return
}
let pasteboardItems = [["com.instagram.sharedSticker.backgroundImage": backgroundImage,
"com.instagram.sharedSticker.contentURL": attributionURL]]
let pasteboardOptions: [UIPasteboard.OptionsKey: Any] = [.expirationDate: Date().addingTimeInterval(60 * 5)]
UIPasteboard.general.setItems(pasteboardItems, options: pasteboardOptions)
UIApplication.shared.open(urlScheme)
}
func backgroundVideo(_ backgroundVideo: Data, attributionURL: String) {
guard let urlScheme = URL(string: "instagram-stories://share"),
UIApplication.shared.canOpenURL(urlScheme) else {
return
}
let pasteboardItems = [["com.instagram.sharedSticker.backgroundVideo": backgroundVideo,
"com.instagram.sharedSticker.contentURL": attributionURL]]
let pasteboardOptions: [UIPasteboard.OptionsKey: Any] = [.expirationDate: Date().addingTimeInterval(60 * 5)]
UIPasteboard.general.setItems(pasteboardItems, options: pasteboardOptions)
UIApplication.shared.open(urlScheme)
}
private func addGestures(to stickerView: UIImageView) {
stickerPanGesture = UIPanGestureRecognizer(target: self, action: #selector(stickerDidMove))
stickerPinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(stickerDidPinch))
stickerRotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(stickerDidRotate))
stickerTapGesture = UITapGestureRecognizer(target: self, action: #selector(stickerDidTap))
stickerPinchGesture.delegate = self
stickerRotateGesture.delegate = self
stickerPanGesture.delegate = self
stickerView.addGestureRecognizer(stickerPinchGesture)
stickerView.addGestureRecognizer(stickerRotateGesture)
stickerView.addGestureRecognizer(stickerPanGesture)
stickerView.addGestureRecognizer(stickerTapGesture)
}
@objc private func stickerDidTap(tap: UITapGestureRecognizer){
let imgView = tap.view as! UIImageView
self.stickersArray = self.stickersArray.filter({$0 != imgView})
tap.view?.removeFromSuperview()
}
@objc private func stickerDidPinch(pincher: UIPinchGestureRecognizer) {
guard let stickerView = pincher.view else { return }
stickerView.transform = stickerView.transform.around(pincher.location(in: stickerView), do: { $0.scaledBy(x: pincher.scale, y: pincher.scale) })
pincher.scale = 1
if pincher.state == .began{
self.scrollView.isScrollEnabled=false
}else if pincher.state == .ended{
self.scrollView.isScrollEnabled=true
}
}
@objc private func stickerDidRotate(rotater: UIRotationGestureRecognizer) {
guard let stickerView = rotater.view else { return }
stickerView.transform = stickerView.transform.around(rotater.location(in: stickerView), do: { $0.rotated(by: rotater.rotation) })
rotater.rotation = 0
if rotater.state == .began{
self.scrollView.isScrollEnabled=false
}else if rotater.state == .ended{
self.scrollView.isScrollEnabled=true
}
}
@objc private func stickerDidMove(panner: UIPanGestureRecognizer) {
guard let stickerView = panner.view else { return }
let offset = panner.translation(in: stickerView)
stickerView.transform = stickerView.transform.translatedBy(x: offset.x, y: offset.y)
panner.setTranslation(.zero, in: stickerView)
if panner.state == .began{
self.scrollView.isScrollEnabled=false
}else if panner.state == .ended{
self.scrollView.isScrollEnabled=true
}
}
private func mergedImage() -> UIImage? {
var images: [(image: UIImage, viewSize: CGSize, transform: CGAffineTransform)] = []
for img in self.stickersArray{
if let stickerViewImage = img.image {
images.append((image: stickerViewImage, viewSize: img.bounds.size, transform: img.transform))
}
}
return self.transparentImage!.merge(in: self.transparentImage!.size, with: images)
}
func getThumbnailFrom(path: URL) -> UIImage? {
do {
let asset = AVURLAsset(url: path , options: nil)
let imgGenerator = AVAssetImageGenerator(asset: asset)
imgGenerator.appliesPreferredTrackTransform = true
let cgImage = try imgGenerator.copyCGImage(at: CMTimeMake(value: 0, timescale: 1), actualTime: nil)
let thumbnail = UIImage(cgImage: cgImage)
return thumbnail
} catch let error {
print("*** Error generating thumbnail: \(error.localizedDescription)")
return nil
}
}
}
//
extension EditViewController: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return gestureRecognizer is UIPanGestureRecognizer || gestureRecognizer is UIRotationGestureRecognizer
}
}
extension EditViewController:UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.selection == 1 ? self.frames.count : (self.selection == 2 ? self.colors.count : self.stickers.count)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "frame", for: indexPath) as! FrameCollectionViewCell
switch self.selection {
case 1:
cell.frameImage.layer.borderWidth = 0
cell.frameImage.image = UIImage(named: self.frames[indexPath.row])
case 2:
cell.frameImage.image=nil
cell.frameImage.layer.borderWidth = 15
cell.frameImage.layer.borderColor = self.colors[indexPath.row].cgColor
default:
cell.frameImage.layer.borderWidth = 0
cell.frameImage.kf.indicatorType = .activity
let image = UIImage(named: "default")
cell.frameImage.kf.setImage(with: URL(string: self.stickers[indexPath.row]), placeholder: image)
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
switch self.selection {
case 1:
self.frameImageView.layer.borderWidth = 0
self.frameImageView.image = UIImage(named: self.frames[indexPath.row])
case 2:
self.frameImageView.image=nil
self.frameImageView.layer.borderWidth = 30
self.frameImageView.layer.borderColor = self.colors[indexPath.row].cgColor
default:
let cell = collection.cellForItem(at: indexPath) as! FrameCollectionViewCell
stickerView = makeStickerView(with: cell.frameImage.image! , center: self.canvasView.center)
addGestures(to: stickerView)
//for video
if self.image == nil{
self.orignalImage.addSubview(stickerView)
}else{
//for image
self.canvasView.addSubview(stickerView)
}
self.stickersArray.append(stickerView)
break;
}
}
}
我尝试添加此代码
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { dismiss(animated: true, completion: nil)
但这并不影响操作。