UIMenuController的介绍

  • 什么是UIMenuController?

    UIMenuController是UIKit里面的控件

    UIMenuController的作用在开发中弹出的菜单栏

    后面介绍了菜单栏显示中文的设置

菜单栏

有哪些控件是自带UIMenuController菜单栏效果的呢?

  • UITextField

  • UITextView

  • UIWebView

有些读者问我这个动图是怎么添加的: 我用的是licecap 这个软件

下面送个几个好用的软件

主要介绍两种:

一种是控制器为第一响应者

另一种是当前UI控件为第一响应者 (把方法封装在控件里面)

具体看代码,注释里我会详细讲解,如果实在不懂不妨动手敲一遍

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UILabel *label;

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

//首先要允许label可以跟用户交互

self.label.userInteractionEnabled = YES;

//给label添加一个敲击手势

[self.label addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelClick)]];

}

/** 点击label触发的方法 */

- (void)labelClick

{

//控制器不需要调用这个方法, 但是其他乱七八糟的UI控件就需要调用这个方法 \

因为控制器默认是第一响应者

//[self becomeFirstResponder];

//显示menu 从来没有让menu跟控制器有关系 , 因为是第一响应者, 所以会调用第一响应者的方法

//不一定调用控制器的方法, 因为现在控制器是第一响应者

// 获得菜单

UIMenuController *menu = [UIMenuController sharedMenuController];

// 菜单最终显示的位置

CGRect rect = CGRectMake(100, 100, 100, 100);

[menu setTargetRect:rect inView:self.label];

//为什么要设置2个参数  为了通用 \

一个是矩形框, 一个是在哪个View上面

//传了矩形框, 要告诉坐标原点在哪, 坐标原点就在view上\

以tagreView的左上角为坐标原点

// 苹果设计2个参数 是因为矩形框一旦修改 出现的位置在哪里都是可以的

/*

targetRect:menuController指向的矩形框

targetView:targetRect以targetView的左上角为坐标原点

*/

// 显示菜单

[menu setMenuVisible:YES animated:YES];

/*

得通过第一响应者,来告诉MenuController它内部应该显示什么内容

*/

}

#pragma mark - 第一响应者 + UIMenuController

/**

* 说明控制器可以成为第一响应者

* 因为控制器是因为比较特殊的对象,它找控制器的方法,不找label的方法

*/

- (BOOL)canBecomeFirstResponder

{

return YES;

}

/**

* 通过这个方法告诉UIMenuController它内部应该显示什么内容

* 返回YES,就代表支持action这个操作

*/

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

{

//打印, 将一个方法转换成字符串 你就会看到许多方法

NSLog(@"%@",NSStringFromSelector(action));

if (action == @selector(cut:)

|| action == @selector(copy:)

|| action == @selector(paste:)) {

return YES;

}

return NO;

}

//监听事情需要对应的方法 冒号之后传入的是UIMenuController

- (void)cut:(UIMenuController *)menu

{

NSLog(@"%s %@", __func__, menu);

}

- (void)copy:(UIMenuController *)menu

{

NSLog(@"%s %@", __func__, menu);

}

- (void)paste:(UIMenuController *)menu

{

NSLog(@"%s %@", __func__, menu);

}

上面只是简单的介绍了UIMenuController的基本知识,下面正在带你运用到开发中的知识,封装一个自定义控件里面实现, 附上大概效果:

上代码,代码有具体的注释,还有具体的用法,所以认真阅读代码即可,就不附上demo了

#import "JHLabel.h"

@implementation JHLabel

/** 不管控件是通过xib stroyboard 还是纯代码  提供两种初始化的操作都调用同一个方法 */

- (instancetype)initWithFrame:(CGRect)frame

{

if (self = [super initWithFrame:frame]) {

[self setupTap];

}

return self;

}

/** 不管控件是通过xib stroyboard 还是纯代码  提供两种初始化的操作都调用同一个方法 */

- (void)awakeFromNib

{

[self setupTap];

}

/** 设置敲击手势 */

- (void)setupTap

{

self.text = @"author:会跳舞的狮子";

//已经在stroyboard设置了与用户交互,也可以用纯代码设置

//    self.userInteractionEnabled = YES;

//当前控件是label 所以是给label添加敲击手势

[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelClick)]];

}

/** 点击label触发的方法 */

- (void)labelClick

{

// 让label成为第一响应者 \

一定要写这句话  因为这句话才是主动让label成为第一响应者

[self becomeFirstResponder];

// 获得菜单

UIMenuController *menu = [UIMenuController sharedMenuController];

// 设置菜单内容 \

因为menuItems是数组 官方没有给出需要传入什么对象,但是以经验可以判断出需要传入的是UIMenuItem对象 \

而且显示是按顺序的

menu.menuItems = @[

[[UIMenuItem alloc] initWithTitle:@"顶" action:@selector(ding:)],

[[UIMenuItem alloc] initWithTitle:@"回复" action:@selector(reply:)],

[[UIMenuItem alloc] initWithTitle:@"举报" action:@selector(warn:)]

];

// 菜单最终显示的位置 \

有两种方式: 一种是以自身的bounds  还有一种是以父控件的frame

[menu setTargetRect:self.bounds inView:self];

//    [menu setTargetRect:self.frame inView:self.superview];

// 显示菜单

[menu setMenuVisible:YES animated:YES];

}

#pragma mark - UIMenuController相关

/**

* 让Label具备成为第一响应者的资格

*/

- (BOOL)canBecomeFirstResponder

{

return YES;

}

/**

* 通过第一响应者的这个方法告诉UIMenuController可以显示什么内容

*/

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

{

if ( (action == @selector(copy:) && self.text) // 需要有文字才能支持复制

|| (action == @selector(cut:) && self.text) // 需要有文字才能支持剪切

|| action == @selector(paste:)

|| action == @selector(ding:)

|| action == @selector(reply:)

|| action == @selector(warn:)) return YES;

return NO;

}

#pragma mark - 监听MenuItem的点击事件

/** 剪切 */

- (void)cut:(UIMenuController *)menu

{

//UIPasteboard 是可以在应用程序与应用程序之间共享的 \

(应用程序:你的app就是一个应用程序 比如你的QQ消息可以剪切到百度查找一样)

// 将label的文字存储到粘贴板

[UIPasteboard generalPasteboard].string = self.text;

// 清空文字

self.text = nil;

}

/** 赋值 */

- (void)copy:(UIMenuController *)menu

{

// 将label的文字存储到粘贴板

[UIPasteboard generalPasteboard].string = self.text;

}

/** 粘贴 */

- (void)paste:(UIMenuController *)menu

{

// 将粘贴板的文字赋值给label

self.text = [UIPasteboard generalPasteboard].string;

}

//如果方法不实现,是不会显示出来的

- (void)ding:(UIMenuController *)menu

{

NSLog(@"%s %@", __func__, menu);

}

- (void)reply:(UIMenuController *)menu

{

NSLog(@"%s %@", __func__, menu);

}

- (void)warn:(UIMenuController *)menu

{

NSLog(@"%s %@", __func__, menu);

}

@end

上面的代码,menu只显示在label的上面 而一般菜单栏我们都是显示在cell的中间, 下面的这幅图详细讲解了显示在cell的中间

/** 点击cell的时候调用 */

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

// 取出cell

UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

UIMenuController *menu = [UIMenuController sharedMenuController];

// 设置菜单内容

menu.menuItems = @[

[[UIMenuItem alloc] initWithTitle:@"顶" action:@selector(ding:)],

[[UIMenuItem alloc] initWithTitle:@"回复" action:@selector(reply:)],

[[UIMenuItem alloc] initWithTitle:@"举报" action:@selector(warn:)]

];

// 显示位置

CGRect rect = CGRectMake(0, cell.height * 0.5, cell.width, 1);

[menu setTargetRect:rect inView:cell];

// 显示出来

[menu setMenuVisible:YES animated:YES];

}

#pragma mark - 获得当前选中的评论

- (JHComment *)selectedComment

{

// 获得被选中的cell的行号

NSIndexPath *indexPath = self.tableView.indexPathForSelectedRow;

NSInteger row = indexPath.row;

// 获得评论数据

NSArray *comments = self.shortComments;

if (indexPath.section == 0 && self.longComments.count) {

comments = self.longComments;

}

return comments[row];

}

#pragma mark - UIMenuController处理

- (BOOL)canBecomeFirstResponder

{

return YES;

}

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

{

if (!self.isFirstResponder) { // 文本框弹出键盘, 文本框才是第一响应者

if (action == @selector(ding:)

|| action == @selector(reply:)

|| action == @selector(warn:)) return NO;

//如果是文本框,那么这些显示都不返回

}

return [super canPerformAction:action withSender:sender];

}

- (void)ding:(UIMenuController *)menu

{

NSLog(@"ding - %@ %@",

self.selectedComment.user.username,

self.selectedComment.content);

}

- (void)reply:(UIMenuController *)menu

{

NSLog(@"reply - %@ %@",

self.selectedComment.user.username,

self.selectedComment.content);

}

- (void)warn:(UIMenuController *)menu

{

NSLog(@"warn - %@ %@",

self.selectedComment.user.username,

self.selectedComment.content);

}

#注: 这里的self.selectedComent

# (点语法  要么调用set方法要么调用get方法, 这里直接用点语法是没有提示的,我已经进行了声明)

#/** 写方法声明的目的是为了使用点语法提示 */

#- (JHComment *)selectedComment;

iOS-你真的会用UIMenuController吗?(详细)的更多相关文章

  1. ios开发——实用技术篇&Pist转模型详细介绍

    Pist转模型详细介绍 关于Plist转模型在iOS开发中是非常常见的,每开一一个项目或者实现一个功能都要用到它,所以今天就给大家讲讲Plist怎么转成模型数据, 前提:必须有一个Plist文件或者通 ...

  2. ios申请真机调试( xcode 5)详细解析

    已经有开发证书的直接跳过第一步 第一步:申请"开发证书" 进入苹果开发者99美元账号: 选择:Certificates, Identifiers & Profiles 关于 ...

  3. iOS开发——实用OC篇&多种定时器详细介绍

    多种定时器详细介绍   在软件开发过程中,我们常常需要在某个时间后执行某个方法,或者是按照某个周期一直执行某个方法.在这个时候,我们就需要用到定时器. 然而,在iOS中有很多方法完成以上的任务,到底有 ...

  4. ios 类似的效果淘宝商品详细页面

    今天试着写ios 分类似影响淘宝的商品详细页面 我使用第三方库EGORefreshTableHeaderView有一个下拉效果刷新PWLoadMoreTableFooterView上拉电阻负载许多其他 ...

  5. iOS树状视图(折叠单元格)详细使用

    RATreeView是一个第三方的iOS树视图(通俗的讲就是折叠单元格),它是对UITableView的封装,定义自己的委托和数据源的法,RATreeView是高度可定制的,并且有很多功能.很多朋友都 ...

  6. iOS开发融云即时通讯集成详细步骤

    1.融云即时通讯iOS SDK下载地址   http://rongcloud.cn/downloads  选择iOS   SDK下载 2.进行应用开发之前,需要先在融云开发者平台创建应用,如果您已经注 ...

  7. iOS的Ping++支付接入步骤(详细)

    Ping++ SDK 代码下载地址: https://github.com/CoderLeezhen/PingppDemo 参考链接: https://www.pingxx.com/guidance/ ...

  8. 开发IOS应用真的一定要买苹果电脑设备吗?

    不要忘记目的 如果你想开发ios或者苹果的app,网上很多网友都会建议你买一个苹果硬件--苹果电脑,一部分建议你安装黑苹果.这两种方案中前一种费用很高,后一种费时费力(甚至到最后都要转向购买apple ...

  9. 利用Qt开发跨平台APP(二)(iOS,使用Qt5.9,很详细,有截图)

    本文将手把手教你如何使用Qt编译出iOS应用程序. Qt是一个优秀的跨平台开发工具.我们利用Qt可以很方便地将一次编写的应用,多次编译到不同平台上,如Windows.Linux.MAC.Android ...

随机推荐

  1. Sql Server2000,2005,2008各版本主要区别

    Emerson回来之后,在过程中遇到的一些问题,再次做一些整理,包括本篇的Sql Server各版本之间的区别和另一篇数据库函数. (博文内容来自网络) 数据类型 SQL Server 2008 数据 ...

  2. EQueue 2.3.2

    EQueue 2.3.2版本发布(支持高可用) 前言 前段时间针对EQueue的完善终于告一段落了,实在值得庆祝,自己的付出和坚持总算有了成果.这次新版本主要为EQueue实现了集群功能,基本实现了B ...

  3. 越狱开发:用iosOpenDev配置越狱开发环境 编写第一个hello world-b

    上网搜索越狱环境搭建,查到iosOpenDev软件,是个很方便的编写插件,而且可以直接用Xcode创建的工具,便开始着手学习如何去安装 集合了网上的方法后,我安装的时候发现: 1.作者最后更新的时间是 ...

  4. AVR GCC对端口的操作指南

    1. AVR GCC for AVR I.I/O端口API1. BV用法:BV(pos);说明:将位定义转换成屏蔽码(MASK).与头文件io.h里的位定义一起使用.例如,置位WDTOE和WDE可表示 ...

  5. oralce闪回

    Oracle闪回操作 1. 记录当前时间或SCN 在数据库变动前记录时间或SCN SQL> select  to_char(sysdate,'YYYY-MM-DD HH24:mi:ss') fr ...

  6. 【Java】整理关于java的String类,equals函数和比较操作符的区别

    初学 Java 有段时间了,感觉似乎开始入了门,有了点儿感觉但是发现很多困惑和疑问而且均来自于最基础的知识折腾了一阵子又查了查书,终于对 String 这个特殊的对象有了点感悟大家先来看看一段奇怪的程 ...

  7. ServletContextListener作用(转)

    ServletContext 被 Servlet 程序用来与 Web 容器通信.例如写日志,转发请求.每一个 Web 应用程序含有一个Context,被Web应用内的各个程序共享.因为Context可 ...

  8. lc面试准备:Remove Duplicates from Sorted List II

    1 题目 Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct ...

  9. python functools模块

    functools.partial 作用: functools.partial 通过包装手法,允许我们 "重新定义" 函数签名 用一些默认参数包装一个可调用对象,返回结果是可调用对 ...

  10. iOS 多线程学习笔记 —— GCD

    本文复制.参考自文章:iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用 ,主要为了加强个人对知识的理解和记忆,不做他用.原作者声明: 著作权声明:本文由http:// ...