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.0 和 Xcode 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