美文网首页iOS 杂货铺
UILabel 实现整体拷贝功能

UILabel 实现整体拷贝功能

作者: Yasic | 来源:发表于2017-11-26 19:29 被阅读188次

iOS 有三个控件自身就可以支持拷贝粘贴等,包括 UITextField,UITextView,UIWebView。而 UILabel 本身是不能响应用户事件也无法复制的,但是可以通过以下设置从而响应系统事件或者是自定义的事件。

首先需要创建一个 UILabel 的子类,并且使其可以成为第一响应者,从而接收用户手势事件。

@interface YasicEditableLabel : UILabel

@end

@implementation YasicEditableLabel

- (BOOL)canBecomeFirstResponder
{
    return YES;
}
@end

接下来要实现 UILabel 的父类 UIResponder 的方法 - (BOOL)canPerformAction:(SEL)action withSender:(nullable id)sender,这个方法表明了当前 View 可以响应哪些方法。而 UIResponder 也定义了一个协议专门表示一些跟编辑有关的方法

@protocol UIResponderStandardEditActions <NSObject>
@optional
- (void)cut:(nullable id)sender NS_AVAILABLE_IOS(3_0);
- (void)copy:(nullable id)sender NS_AVAILABLE_IOS(3_0);
- (void)paste:(nullable id)sender NS_AVAILABLE_IOS(3_0);
- (void)select:(nullable id)sender NS_AVAILABLE_IOS(3_0);
- (void)selectAll:(nullable id)sender NS_AVAILABLE_IOS(3_0);
- (void)delete:(nullable id)sender NS_AVAILABLE_IOS(3_2);
- (void)makeTextWritingDirectionLeftToRight:(nullable id)sender NS_AVAILABLE_IOS(5_0);
- (void)makeTextWritingDirectionRightToLeft:(nullable id)sender NS_AVAILABLE_IOS(5_0);
- (void)toggleBoldface:(nullable id)sender NS_AVAILABLE_IOS(6_0);
- (void)toggleItalics:(nullable id)sender NS_AVAILABLE_IOS(6_0);
- (void)toggleUnderline:(nullable id)sender NS_AVAILABLE_IOS(6_0);

- (void)increaseSize:(nullable id)sender NS_AVAILABLE_IOS(7_0);
- (void)decreaseSize:(nullable id)sender NS_AVAILABLE_IOS(7_0);

@end

其中 copy 就是我们要实现的方法。所以要在自定义的 UILabel 中实现下面两个方法

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    return (action == @selector(copy:));
}

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

在第一个方法中返回一个 BOOL 值用于表明对不同的 action 的响应情况,注意如果这里对 copy 返回 YES,而并没有自己实现 copy 方法,后面调用到这个方法的时候就会报 unrecognized selector 错误。

copy 方法里我们用到了 UIPasteboard 对象,也就是管理剪切板的类,它可以通过 generalPasteboard 方法获取到一个系统级别的类,也可以通过下面方法获取到一个有特殊名称的剪切板从而限制可以被获取到的范围,第二个参数用于决定当剪切板不存在时是否创建。

UIPasteboard *pboard = [UIPasteboard pasteboardWithName:@"Yasic" create:YES];

UIPasteboard 还可以获取到一个应用内范围的剪切板。

UIPasteboard *pboard = [UIPasteboard pasteboardWithUniqueName];

同时支持拷贝到剪切板的类有

  • UIPasteboardTypeListString 字符串及数组, 包含 kUTTypeUTF8PlainText
  • UIPasteboardTypeListURL URL及数组,包含 kUTTypeURL
  • UIPasteboardTypeListImage 图形及数组, 包含 kUTTypePNG 和 kUTTypeJPEG
  • UIPasteboardTypeListColor 颜色及数组

这里我们保存到剪切板的字符串中。

接下来还需要确定什么类型的手势能弹起选项弹窗

-(void)attachTapHandler
{
    self.userInteractionEnabled = YES;  
    UITapGestureRecognizer *touch = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
    touch.numberOfTapsRequired = 2;
    [self addGestureRecognizer:touch];
}

-(void)handleTap:(UIGestureRecognizer*) recognizer
{
    [self becomeFirstResponder];
    UIMenuController *menu = [UIMenuController sharedMenuController];
    [menu setTargetRect:self.frame inView:self.superview];
    menu.arrowDirection = UIMenuControllerArrowLeft;
    menu.menuVisible = YES;
}

要注意要弹出弹窗之前首先要成为第一响应者,然后通过 UIMenuController 弹出弹窗,UIMenuController 的 setTargetRect: inView 方法主要用于展示弹窗的位置和弹窗所在 View,arrowDirection 可以指定弹窗方向,最终通过 menuVisible 方法展示弹窗。

这里其实并不需要向 UIMenuController 手动添加选项元素,对于系统支持的方法如 copy、paste 等都是只要在 canPerformAction 中返回了 YES 就会在弹窗选项中自动添加。

那么自然,我们也可以自己实现出现在弹窗的方法,只需要改动下面的方法就可以

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    return (action == @selector(myCopy:));
}

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

-(void)handleTap:(UIGestureRecognizer*) recognizer
{
    [self becomeFirstResponder];
    UIMenuItem *copyLink = [[UIMenuItem alloc] initWithTitle:@"myCopy" action:@selector(myCopy:)];
    [[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObjects:copyLink, nil]];
    [[UIMenuController sharedMenuController] setTargetRect:self.frame inView:self.superview];
    [[UIMenuController sharedMenuController] setMenuVisible:YES animated: YES];
}

这里 UIMenuController 部分动态加入了一个叫做 myCopy 的方法,从而在弹窗中就可以展示这个选项了。

相关文章

  • UILabel 实现整体拷贝功能

    iOS 有三个控件自身就可以支持拷贝粘贴等,包括 UITextField,UITextView,UIWebView...

  • 拷贝

    一、拷贝: 任何实现拷贝功能都需要实现NSCopying协议。 1、深拷贝: 开辟一个新空间,对对象本身进行拷贝以...

  • iOS 中的copy

    iOS 关于拷贝: 如何让自定义的类实现拷贝功能?实现 协议 -(id) copyWith...

  • iOS面试基础

    1.iOS如何令自己所写的对象具有拷贝功能? 想让自己所写的对象具有拷贝功能,则需实现 NSCopying 协议。...

  • UILabel实现长按复制功能

    1. 创建 UILabel 的子类 2. 增加 UILongPressGestureRecognizer 手势 3...

  • UILabel如何实现复制功能?

    项目遇到一个需求,就是在物流查询功能中能够复制物流单号。因为显示的物流单号用的是UILabel,所以不像UITex...

  • UIlabel 实现长按复制功能

    先上图,这是最终功能实现效果图 其实很简单,首先创建一个继承了UILabel的MLLongPressLabel,然...

  • 使用CADisplayLink实现UILabel动画特效

    使用CADisplayLink实现UILabel动画特效 使用CADisplayLink实现UILabel动画特效

  • 让自己创建的类具备Copy功能

    对于对象具有拷贝功能,则需实现 NSCopying 协议。 声明该类遵从 NSCopying 协议 实现 NSCo...

  • NSCopying的理解

    想要让自己写的对象具有copy功能,需要实现NSCopying协议。copy分深拷贝与浅拷贝,深拷贝可以理解为:在...

网友评论

    本文标题:UILabel 实现整体拷贝功能

    本文链接:https://www.haomeiwen.com/subject/vzhlbxtx.html