iOS开发之UIMenuController
阅读原文时间:2023年07月17日阅读:3

1、简介

  用于剪切、复制、粘贴、选择、选择ALL和DELETE命令的菜单界面。

  UITextField、UIWebView、UITextView自带有这种UIMenuController效果;

2、相关API

#import
#import
#import

NS_ASSUME_NONNULL_BEGIN

typedef NS_ENUM(NSInteger, UIMenuControllerArrowDirection) {
UIMenuControllerArrowDefault, // up or down based on screen location
UIMenuControllerArrowUp NS_ENUM_AVAILABLE_IOS(3_2),
UIMenuControllerArrowDown NS_ENUM_AVAILABLE_IOS(3_2),
UIMenuControllerArrowLeft NS_ENUM_AVAILABLE_IOS(3_2),
UIMenuControllerArrowRight NS_ENUM_AVAILABLE_IOS(3_2),
} __TVOS_PROHIBITED;

@class UIView, UIMenuItem;

NS_CLASS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED @interface UIMenuController : NSObject

//初始化懒加载
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) UIMenuController *sharedMenuController;
#else

  • (UIMenuController *)sharedMenuController;
    #endif

//菜单的显示和隐藏
@property(nonatomic,getter=isMenuVisible) BOOL menuVisible; // default is NO

  • (void)setMenuVisible:(BOOL)menuVisible animated:(BOOL)animated; //可动画

//设置显示区域

  • (void)setTargetRect:(CGRect)targetRect inView:(UIView *)targetView;
    //编辑菜单箭头指向的方向。
    @property(nonatomic) UIMenuControllerArrowDirection arrowDirection NS_AVAILABLE_IOS(3_2); // default is UIMenuControllerArrowDefault

@property(nullable, nonatomic,copy) NSArray *menuItems NS_AVAILABLE_IOS(3_2); // default is nil. 编辑菜单中的自定义菜单项。
//刷新Menu

  • (void)update;
    //返回编辑菜单的框架
    @property(nonatomic,readonly) CGRect menuFrame;

@end

UIKIT_EXTERN NSNotificationName const UIMenuControllerWillShowMenuNotification __TVOS_PROHIBITED; //将要显示
UIKIT_EXTERN NSNotificationName const UIMenuControllerDidShowMenuNotification __TVOS_PROHIBITED; //已经显示
UIKIT_EXTERN NSNotificationName const UIMenuControllerWillHideMenuNotification __TVOS_PROHIBITED; //将要隐藏
UIKIT_EXTERN NSNotificationName const UIMenuControllerDidHideMenuNotification __TVOS_PROHIBITED; //已经隐藏
UIKIT_EXTERN NSNotificationName const UIMenuControllerMenuFrameDidChangeNotification __TVOS_PROHIBITED; //视图更新

//自定义菜单项
NS_CLASS_AVAILABLE_IOS(3_2) __TVOS_PROHIBITED @interface UIMenuItem : NSObject
//标题 和 响应方法

  • (instancetype)initWithTitle:(NSString *)title action:(SEL)action NS_DESIGNATED_INITIALIZER;
    @property(nonatomic,copy) NSString *title;
    @property(nonatomic) SEL action;

@end

3、自定义MenuLabel

#import "MenuLabel.h"

@implementation MenuLabel

  • (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
    [self setUI];
    }
    return self;
    }

  • (void)awakeFromNib{
    [super awakeFromNib];
    [self setUI];
    }

  • (void)setUI{
    self.userInteractionEnabled = YES;
    // self.text = @"";
    [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGes:)]];
    }

  • (void)tapGes:(UITapGestureRecognizer *)ges{
    [self becomeFirstResponder];
    UIMenuController *menu = [UIMenuController sharedMenuController];
    menu.menuItems = @[[[UIMenuItem alloc] initWithTitle:@"点赞" action:@selector(tap:)],
    [[UIMenuItem alloc] initWithTitle:@"留言" action:@selector(reply:)],
    [[UIMenuItem alloc] initWithTitle:@"踩一踩" action:@selector(down:)],
    [[UIMenuItem alloc] initWithTitle:@"踩一踩" action:@selector(down:)]];
    [menu setTargetRect:self.bounds inView:self];
    [menu setMenuVisible:YES animated:YES];
    }

  • (BOOL)canBecomeFirstResponder{
    return YES;
    }

  • (BOOL)canPerformAction:(SEL)action withSender:(id)sender{
    if ( (action == @selector(copy:) && self.text) // 需要有文字才能支持复制
    || (action == @selector(cut:) && self.text) // 需要有文字才能支持剪切
    || action == @selector(paste:)
    || action == @selector(tap:)
    || action == @selector(reply:)
    || action == @selector(down:)) return YES;
    return NO;
    }

  • (void)cut:(UIMenuController *)menu
    {
    //UIPasteboard 粘贴板
    // 将label的文字存储到粘贴板
    [UIPasteboard generalPasteboard].string = self.text;
    // 清空文字
    self.text = nil;
    NSLog(@"cut");
    }

  • (void)copy:(UIMenuController *)menu
    {
    // 将label的文字存储到粘贴板
    [UIPasteboard generalPasteboard].string = self.text;
    NSLog(@"copy");
    }

  • (void)paste:(UIMenuController *)menu
    {
    // 将粘贴板的文字赋值给label
    self.text = [UIPasteboard generalPasteboard].string;
    NSLog(@"paste");
    }

  • (void)tap:(UIMenuController *)menu{
    NSLog(@"tap");
    }

  • (void)reply:(UIMenuController *)menu{
    NSLog(@"reply");
    }

  • (void)down:(UIMenuController *)menu{
    NSLog(@"down");
    }

@end

MenuLabel.m文件

  ps:自定义UIMenuItem过多是自动分页;

    部分选择文本可以继承TextView自定义类;

    注意事项:自身可交互、成为第一响应者、显示前设置好位置等属性;

self.userInteractionEnabled = YES;  
\[self becomeFirstResponder\];

    实现UIResponder类中的一个方法:

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender;