ios 在 UILabel 上显示 iPhone 剪切复制粘贴菜单
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1246198/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Show iPhone cut copy paste menu on UILabel
提问by
Can we enable the cut copy paste menu for a
UILabel
as it is for aUITextField
?If not, and I need to convert my
UILabel
toUITextField
, how can I enable the cut copy paste menu and not allow the content to be modified?
我们可以启用剪切复制粘贴菜单的
UILabel
,因为它是一个UITextField
?如果没有,我需要将我的转换
UILabel
为UITextField
,如何启用剪切复制粘贴菜单并且不允许修改内容?
回答by zoul
I got the copy?&?paste menu working on a UILabel
, I just had to return YES
for canBecomeFirstResponder
and later call [label becomeFirstResponder]
when the said label was to come on screen. As for returning YES
from canBecomeFirstResponder
, you can create a custom subclass or patch UILabel
using a category:
我得到了拷贝?&?粘贴菜单上的工作UILabel
,我不得不回YES
了canBecomeFirstResponder
,后来打电话[label becomeFirstResponder]
时说,标签是来在屏幕上。至于YES
从返回canBecomeFirstResponder
,您可以UILabel
使用类别创建自定义子类或补丁:
@implementation UILabel (Clipboard)
- (BOOL) canBecomeFirstResponder
{
return YES;
}
@end
The category solution feels a bit hackish, but if you know what you're doing it might be easier than subclassing. I have also put up a sample project on GitHubthat shows how to display a simple pasteboard menu on an UILabel
.
类别解决方案感觉有点hackish,但如果您知道自己在做什么,它可能比子类化更容易。我还在GitHub 上放置了一个示例项目,展示了如何在UILabel
.
回答by pableiros
For Swift you have to implement this class:
对于 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
self.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(self.showMenu)))
}
@objc func showMenu(sender: AnyObject?) {
self.becomeFirstResponder()
let menu = UIMenuController.shared
if !menu.isMenuVisible {
menu.setTargetRect(bounds, in: self)
menu.setMenuVisible(true, animated: true)
}
}
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)
}
}
In your storyboard just subclass the UILabel
with CopyableLabel
class
在您的故事板中,只需将UILabel
withCopyableLabel
类子类化
回答by benvolioT
The sample project on githubdue to @zoul's answer is the way to go. At the time of this writing, that project does not actually put anything on the clipboard (pasteboard). here is how:
由于@zoul 的回答,github 上的示例项目是要走的路。在撰写本文时,该项目实际上并未在剪贴板(粘贴板)上放置任何内容。方法如下:
Change @zoul's implementation of this method to:
将此方法的@zoul 实现更改为:
- (void) copy:(id)sender {
UIPasteboard *pboard = [UIPasteboard generalPasteboard];
pboard.string = self.text;
}
回答by Hyman
Swift 4 ? Xcode 9.2.
By using UIMenuController
we can do it.
斯威夫特 4 ? Xcode 9.2。通过使用UIMenuController
我们可以做到。
I have created IBDesignable
Custom UILabel
class which you can assign on storyboard directly
我创建了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
}
}
Output:
输出:
回答by codeperson
I've made an open source UILabel subclass that shows a UIMenuController with a "Copy" option upon long press:
我制作了一个开源 UILabel 子类,它在长按时显示一个带有“复制”选项的 UIMenuController:
HTCopyableLabelon GitHub
GitHub 上的HTCopyableLabel
回答by zhbrass
I've forked zoul's sample project and added support for ARC (and a couple of other features) if anyone's still interested:
如果有人仍然感兴趣,我已经分叉了 zoul 的示例项目并添加了对 ARC(以及其他一些功能)的支持:
https://github.com/zhbrass/UILabel-Clipboard
https://github.com/zhbrass/UILabel-Clipboard
CopyLabel.h/.m should be what you're looking for
CopyLabel.h/.m 应该是你要找的
回答by Alex Reynolds
Override the UITextField
instance's textFieldShouldBeginEditing
method, and set it to return NO
in order to disable editing.
覆盖UITextField
实例的textFieldShouldBeginEditing
方法,并将其设置为返回NO
以禁用编辑。
Take a look at the UITextFieldDelegate
protocol for more details.
查看UITextFieldDelegate
协议以获取更多详细信息。
回答by mukaissi
If you have multiline text, you should use UITextView
如果你有多行文本,你应该使用 UITextView
Set the delegate:
设置委托:
func textView(_ textView: UITextView,
shouldChangeTextIn range: NSRange,
replacementText text: String) -> Bool {
return false
}
And it should work magically :)
它应该神奇地工作:)
回答by Fattie
2019 ...
2019...
Save anyone typing:
保存任何人输入:
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(_:)))
}
}
It's that easy!
就这么简单!
One subtlety:
一个微妙之处:
One detail for better engineering:
更好的工程设计的一个细节:
Notice we turn on first responder:
注意我们开启了第一响应者:
public override var canBecomeFirstResponder: Bool { return true }
Often, on a given screen with such a label, you either will or won't have a copyable link like this.
通常,在带有此类标签的给定屏幕上,您要么会拥有这样的可复制链接,要么不会。
So you'll very likely have something like:
所以你很可能会有这样的事情:
var linkTurnedOnCurrently: Bool = false
func doShowThatLink( blah ) {
linkAvailableOnThisScreen = true
... the various code above ...
}
func doShowThatLink( blah ) {
linkAvailableOnThisScreen = false
... perhaps de-color the link, etc ...
}
Thus, in fact instead of this:
因此,实际上而不是这样:
public override var canBecomeFirstResponder: Bool { return true }
be sure to do this:
一定要这样做:
public override var canBecomeFirstResponder: Bool {
if linkTurnedOnCurrently { return true }
return super.canBecomeFirstResponder
}
(Note that it is notsomething like "return linkTurnedOnCurrently".)
(请注意,这是不是有点像“回归linkTurnedOnCurrently”。)
回答by iOS
In Swift 5.0and Xcode 10.2
在Swift 5.0和Xcode 10.2 中
Add copy option to your UILabel directly in your ViewController.
直接在 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(_:))
}