Подтвердить что ты не робот

Показать меню вырезания iPhone на панели UILabel

  • Можем ли мы включить меню вырезания скопированной копии для UILabel, как и для UITextField?

  • Если нет, и мне нужно преобразовать мой UILabel в UITextField, как я могу включить меню вырезания скопированной копии и не разрешать изменение содержимого?

4b9b3361

Ответ 1

Я получил копию & вставляя меню, работающее на UILabel, мне просто нужно было вернуть YES для canBecomeFirstResponder, а затем вызвать [label becomeFirstResponder], когда указанный ярлык должен был появиться на экране. Что касается возврата YES из canBecomeFirstResponder, вы можете создать собственный подкласс или патч UILabel с помощью категории:

@implementation UILabel (Clipboard)

- (BOOL) canBecomeFirstResponder
{
    return YES;
}

@end

Решение категории кажется немного хакерским, но если вы знаете, что вы делаете, это может быть проще, чем подклассификация. Я также разместил образец проекта на GitHub, который показывает, как отображать простое меню на UILabel.

Ответ 2

Для Swift 3 и Swift 4 вы должны реализовать этот класс:

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)
    }
}

В вашей раскадровке просто UILabel подкласс UILabel с классом CopyableLabel

Ответ 3

образец проекта на github из-за ответа @zoul - это путь. На момент написания этого проекта этот проект фактически ничего не помещал в буфер обмена (картон). вот как:

Измените реализацию @zoul этого метода на:

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

Ответ 4

Swift 4 ☻ Xcode 9.2. Используя UIMenuController мы можем это сделать.

Я создал IBDesignable Custom 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
    }
}

Выход:

enter image description here

Ответ 5

Я создал подкласс UILabel с открытым исходным кодом, который показывает UIMenuController с опцией "Копировать" при длительном нажатии:

HTCopyableLabel на GitHub

Ответ 6

Я разработал пример проекта zoul и добавил поддержку ARC (и пару других функций), если кому-то все еще интересно:

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

CopyLabel.h/.m должен быть тем, что вы ищете

Ответ 7

Переопределите метод UITextField instance textFieldShouldBeginEditing и установите его для возврата NO, чтобы отключить редактирование.

Посмотрите UITextFieldDelegate для более подробной информации.

Ответ 8

Если у вас есть многострочный текст, вы должны использовать UITextView

Установите делегата:

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

И это должно работать волшебно :)

Ответ 9

@benvolioT github project - очень хороший пример для копирования. А для пасты настройте canPerformAction:withSender:. Подробнее см. Пример CopyPasteTile.

Ответ 10

В Swift 5.0 и Xcode 10.2

Добавьте опцию копирования в вашу UILabel прямо в вашем ViewController.

//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(_:))
}

Ответ 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(_:)))
    }
}

Это так просто!