iosswift照片在屏幕上剪切剪切

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iosswift照片在屏幕上剪切剪切相关的知识,希望对你有一定的参考价值。

参考技术A 我们在ios开发中,时常需要将一些原本是方形的图片剪切成圆形或者边框是曲线的样子,表现得活泼生动一些.

注意:因为最近在尝试用Swiftl开发,所以这里的语言使用的就是Swift,OC的语法也是相近的.

这是修改之前的:

然后这是修改之后的:

第一种:通过图形绘制

extension UIImage

func createImage(isCornored: Bool = true,size: CGSize = CGSize.zero,backgroundColor: UIColor = UIColor.white,callBack: @escaping (_ image: UIImage) ->())
//在子线程中执行
DispatchQueue.global().async
let rect = CGRect(origin: CGPoint.zero, size: size)
//1. 开启上下文
UIGraphicsBeginImageContext(size)
//2. 设置颜色
backgroundColor.setFill()
//3. 颜色填充
UIRectFill(rect)
//4. 图像绘制
//切回角
let path = UIBezierPath(ovalIn: rect)
path.addClip()

self.draw(in: rect)
//5. 获取图片
let image = UIGraphicsGetImageFromCurrentImageContext()
//6 关闭上下文
UIGraphicsEndImageContext()
//回到主线程刷新UI
DispatchQueue.main.async(execute:
callBack(image!)
)



第二种:剪切圆角

//设置圆角半径(通过设置这个的大小,越接近你的矩形宽度,圆的形状越明显)
iconImageView.layer.cornerRadius = 50
//必做的一步
iconImageView.layer.masksToBounds = true
//设置边框宽度
iconImageView.layer.borderWidth = 5
//设置边框的颜色
iconImageView.layer.borderColor = UIColor.black
这两种方法都挺实用的,不过第二种比较简短,第一种适合用来提高自己的逼格吧.

在 UILabel 上显示 iPhone 剪切复制粘贴菜单

【中文标题】在 UILabel 上显示 iPhone 剪切复制粘贴菜单【英文标题】:Show iPhone cut copy paste menu on UILabel 【发布时间】:2010-11-17 18:53:38 【问题描述】:

    我们能否像 UITextField 一样为 UILabel 启用剪切复制粘贴菜单?

    如果没有,我需要将我的UILabel 转换为UITextField,如何启用剪切复制粘贴菜单并且不允许修改内容?

【问题讨论】:

选项 2 运气好吗?我目前正在尝试连接一个 UILabel 子类来支持一个非常简单的复制菜单选项,这不是一个特别直接的过程。 @BillyGray 十年后,现在这很容易 - 向下滚动到我用当前方法输入的最新答案。 【参考方案1】:

对于 Swift 你必须实现这个类:

import UIKit

class CopyableLabel: UILabel 

    override init(frame: CGRect) 
        super.init(frame: frame)
        self.sharedInit()
    

    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
        self.sharedInit()
    

    func sharedInit() 
        self.isUserInteractionEnabled = true
        let gesture = UILongPressGestureRecognizer(target: self, action: #selector(self.showMenu))
        self.addGestureRecognizer(gesture)
    

    @objc func showMenu(_ recognizer: UILongPressGestureRecognizer) 
        self.becomeFirstResponder()
    
        let menu = UIMenuController.shared
    
        let locationOfTouchInLabel = recognizer.location(in: self)

        if !menu.isMenuVisible 
            var rect = bounds
            rect.origin = locationOfTouchInLabel
            rect.size = CGSize(width: 1, height: 1)
        
            menu.showMenu(from: self, rect: rect)
        
    

    override func copy(_ sender: Any?) 
        let board = UIPasteboard.general
    
        board.string = text
    
        let menu = UIMenuController.shared
    
        menu.setMenuVisible(false, animated: true)
    

    override var canBecomeFirstResponder: Bool 
        return true
    

    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool 
        return action == #selector(UIResponderStandardEditActions.copy)
    

在您的故事板中,只需将 UILabel 子类化为 CopyableLabel

【讨论】:

固定目标矩形,gist.github.com/baryon/bd2d3e7fe1fa57d19dae1d88f7662c32【参考方案2】:

我在UILabel 上获得了复制和粘贴菜单,我只需要返回YES 以获得canBecomeFirstResponder,然后当所述标签出现在屏幕上时调用[label becomeFirstResponder]。至于从canBecomeFirstResponder返回YES,你可以创建一个自定义的子类或者使用类别修补UILabel

@implementation UILabel (Clipboard)

- (BOOL) canBecomeFirstResponder

    return YES;


@end

类别解决方案感觉有点老套,但如果您知道自己在做什么,它可能比子类化更容易。我还发布了一个sample project on GitHub,它展示了如何在UILabel 上显示一个简单的粘贴板菜单。

【讨论】:

我在 zoul 的 repo 中添加了一些额外的功能。 github.com/zhbrass/UILabel-Clipboard【参考方案3】:

由于@zoul 的回答,sample project on github 是要走的路。在撰写本文时,该项目实际上并未在剪贴板(粘贴板)上放置任何内容。方法如下:

将此方法的@zoul 实现更改为:

- (void) copy:(id)sender 
    UIPasteboard *pboard = [UIPasteboard generalPasteboard];
    pboard.string = self.text;  

【讨论】:

【参考方案4】:

Swift 4 ☻ Xcode 9.2。 通过使用UIMenuController,我们可以做到。

我创建了 IBDesignable 自定义 UILabel 类,您可以直接在情节提要上分配它

@IBDesignable
class TapAndCopyLabel: UILabel 

    override func awakeFromNib() 
        super.awakeFromNib()
        //1.Here i am Adding UILongPressGestureRecognizer by which copy popup will Appears
        let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressGesture(_:)))
        self.addGestureRecognizer(gestureRecognizer)
        self.isUserInteractionEnabled = true
    

    // MARK: - UIGestureRecognizer
    @objc func handleLongPressGesture(_ recognizer: UIGestureRecognizer) 
        guard recognizer.state == .recognized else  return 

        if let recognizerView = recognizer.view,
            let recognizerSuperView = recognizerView.superview, recognizerView.becomeFirstResponder()
        
            let menuController = UIMenuController.shared
            menuController.setTargetRect(recognizerView.frame, in: recognizerSuperView)
            menuController.setMenuVisible(true, animated:true)
        
    
    //2.Returns a Boolean value indicating whether this object can become the first responder
    override var canBecomeFirstResponder: Bool 
        return true
    
    //3.Here we are enabling copy action
    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool 
        return (action == #selector(UIResponderStandardEditActions.copy(_:)))

    
    // MARK: - UIResponderStandardEditActions
    override func copy(_ sender: Any?) 
        //4.copy current Text to the paste board
        UIPasteboard.general.string = text
    

输出:

【讨论】:

你应该使用guard recognizer.state == .began else return 这样它会在持续时间之后显示菜单控制器,而不是在你抬起手指之后。用户在手指按下时期望得到反馈。 效果很好,但同 Paul 所说的一样,将保护声明中的 .recognized 更改为 .began ,它会在您按下时弹出副本。谢谢!【参考方案5】:

我制作了一个开源 UILabel 子类,它在长按时显示带有“复制”选项的 UIMenuController:

HTCopyableLabel 在 GitHub 上

【讨论】:

【参考方案6】:

如果有人仍然感兴趣,我已经分叉了 zoul 的示例项目并添加了对 ARC(以及其他一些功能)的支持:

https://github.com/zhbrass/UILabel-Clipboard

CopyLabel.h/.m 应该是您要查找的内容

【讨论】:

【参考方案7】:

覆盖UITextField 实例的textFieldShouldBeginEditing 方法,并将其设置为返回NO 以禁用编辑。

查看UITextFieldDelegate 协议了解更多详情。

【讨论】:

问题是:如果禁用编辑,复制和粘贴将不起作用。【参考方案8】:

Swift 5.0Xcode 10.2

直接在您的 ViewController 中将复制选项添加到您的 UILabel。

//This is your UILabel
@IBOutlet weak var lbl: UILabel!

//In your viewDidLoad()
self.lbl.isUserInteractionEnabled = true
let longPress = UILongPressGestureRecognizer.init(target: self, action: #selector((longPressFunctin(_:))))
self.lbl.addGestureRecognizer(longPress)

//Write these all functions outside the viewDidLoad()
@objc func longPressFunctin(_ gestureRecognizer: UILongPressGestureRecognizer) 
    lbl.becomeFirstResponder()
    let menu = UIMenuController.shared
    if !menu.isMenuVisible 
        menu.setTargetRect(CGRect(x: self.lbl.center.x, y: self.lbl.center.y, width: 0.0, height: 0.0), in: view)
        menu.setMenuVisible(true, animated: true)
    


override func copy(_ sender: Any?) 
    let board = UIPasteboard.general
    board.string = lbl.text


override var canBecomeFirstResponder: Bool 
    return true


override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool 
    return action == #selector(copy(_:))

【讨论】:

确实有帮助。谢谢 【参考方案9】:

Swift 5.3 和 SwiftUI

为了在 SwiftUI 中实现这一点,我们可以使用 pableiros 创建与 UIViewRepresentable 组合的方法。

我们需要对 CopyableLabel 类进行两项更新,因为以下方法在 iOS 13 中已弃用。

.setTargetRect(_,in:)

.setMenutVisible(_,animated)

我们可以改用.showMenu(from:rect:) 方法轻松解决此问题。

这是更新后的CopyableLabel 类。

class CopyableLabel: UILabel 

    override init(frame: CGRect) 
        super.init(frame: frame)
        self.sharedInit()
    

    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
        self.sharedInit()
    

    func sharedInit() 
        self.isUserInteractionEnabled = true
        self.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(self.showMenu)))
    

    @objc func showMenu(sender: AnyObject?) 
        self.becomeFirstResponder()

        let menu = UIMenuController.shared

        if !menu.isMenuVisible 
            menu.showMenu(from: self, rect: self.bounds) // <-  we update the deprecated methods here
        
    

    override func copy(_ sender: Any?) 
        let board = UIPasteboard.general

        board.string = text

        let menu = UIMenuController.shared

        menu.showMenu(from: self, rect: self.bounds) // <- we update the deprecated methods here
    

    override var canBecomeFirstResponder: Bool 
        return true
    

    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool 
        return action == #selector(UIResponderStandardEditActions.copy)
    

然后为了让这个类与 SwiftUI 一起工作,我们所要做的就是创建一个简单的UIViewRepresentable

struct CopyableLabelView: UIViewRepresentable 

    let text: String
    private let label = CopyableLabel(frame: .zero)

    init(text: String) 
        self.text = text
    

    func makeUIView(context: Context) -> UILabel 
        // Set the text for the label
        label.text = text

        // Set the content hugging priority so the UILabel's view is
        // kept tight to the text.
        label.setContentHuggingPriority(.required, for: .horizontal)
        label.setContentHuggingPriority(.required, for: .vertical)
        return label
    

    func updateUIView(_ uiView: UILabel, context: Context) 
        // Handle when the text that is passed changes
        uiView.text = text
    

  

【讨论】:

【参考方案10】:

如果你有多行文本,你应该使用UITextView

设置委托:

func textView(_ textView: UITextView,
              shouldChangeTextIn range: NSRange,
              replacementText text: String) -> Bool 
    return false

它应该可以神奇地工作:)

【讨论】:

这并不总是正确的。我有一个带有多行文本的扩展单元格,并且文本视图在文本到达某个点后用于扩展单元格非常糟糕。在那种情况下,uilabels 会好很多【参考方案11】:

2019 ...

保存任何输入:

public class SomeComplexCustomView: UIView 

    @IBOutlet var oneOfYourLabels: UILabel!
    ... your other labels, boxes, etc

    public func makeThatLabelCopyable() 
        oneOfYourLabels.isUserInteractionEnabled = true
        addGestureRecognizer(UITapGestureRecognizer(
          target: self, action: #selector(self.copyMenu(sender:))))
        addGestureRecognizer(UILongPressGestureRecognizer(
          target: self, action: #selector(self.copyMenu(sender:))))

        // or use oneOfYourLabels.addGesture... to touch just on that item 
    

    public override var canBecomeFirstResponder: Bool  return true 

    @objc func copyMenu(sender: Any?) 
        becomeFirstResponder()
        UIMenuController.shared.setTargetRect(bounds, in: self)
        // or any exact point you want the pointy box pointing to
        UIMenuController.shared.setMenuVisible(true, animated: true)
    

    override public func copy(_ sender: Any?) 
        UIPasteboard.general.string = oneOfYourLabels.text
        // or any exact text you wish
        UIMenuController.shared.setMenuVisible(false, animated: true)
    

    override public func canPerformAction(
      _ action: Selector, withSender sender: Any?) -> Bool 
        return (action == #selector(copy(_:)))
    

就这么简单!


一个微妙之处:

改善工程的一个细节:

注意我们开启了第一响应者:

 public override var canBecomeFirstResponder: Bool  return true 

通常,在带有此类标签的给定屏幕上,您将拥有或不会拥有这样的可复制链接。

所以你很可能会有类似的东西:

var linkTurnedOnCurrently: Bool = false

func doShowThatLink( blah ) 
    linkAvailableOnThisScreen = true
    ... the various code above ...


func doShowThatLink( blah ) 
    linkAvailableOnThisScreen = false
    ... perhaps de-color the link, etc ...

因此,实际上不是这样:

 public override var canBecomeFirstResponder: Bool  return true 

一定要这样做:

 public override var canBecomeFirstResponder: Bool 
    if linkTurnedOnCurrently  return true 
    return super.canBecomeFirstResponder
 

(请注意,它不是类似于“return linkTurnedOnCurrently”。)

【讨论】:

谢谢@rob!是的,这是一个很棒的公式。这是一个很好的例子,在 SO 上的答案可能已经过时了!这就是今天的方法,而且很简单,谢天谢地。 其实@Rob,请看我在答案末尾添加的详细信息【参考方案12】:

@benvolioT's github project 是非常好的复制示例。对于粘贴,自定义canPerformAction:withSender:。 有关更多信息,请参阅示例 CopyPasteTile。

【讨论】:

以上是关于iosswift照片在屏幕上剪切剪切的主要内容,如果未能解决你的问题,请参考以下文章

FabricJS 防止 canvas.clipTo 剪切 canvas.backgroundImage

iOS oc-剪切板

手机有啥软件可以调节照片的像素分辨率和大小?

IOS Photos 应用程序如何在一个屏幕上显示数百张照片?

富头像上传编辑器----很好用的上传照片和拍照功能

如何使用 opengl 和 pyglet 设置剪切平面