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. 原生js实现tab选项卡里内嵌图片滚动特效代码

    <!DOCTYPE HTML><html lang="en-US"><head><meta charset="UTF-8&quo ...

  2. iOS代码实现:创建按钮,绑定按钮事件,读取控件值

    // // main.m // Hello // // Created by lishujun on 14-8-28. // Copyright (c) 2014年 lishujun. All rig ...

  3. hadoop 2.x 安装包目录结构分析

    bin:Hadoop最基本的管理脚本和使用脚本所在目录,这些脚本是sbin目录下管理脚本的基础实现,用户可以直接使用这些脚本管理和使用hadoop etc:Hadoop配置文件所在目录,包括core- ...

  4. Cyclic Tour HDUOJ 费用流

    Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others)Total ...

  5. bzoj 1500: [NOI2005]维修数列 splay

    1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 6556  Solved: 1963[Submit][Status ...

  6. Microsoft HoloLens 技术解谜(下)

    读者提问之“HoloLens 的深度传感器有没有可能是基于 TOF?” 先介绍下背景知识,市面上常见的有三种类型的深度传感器: 结构光,这个技术的代表产品是 Kinect 一代,它的传感器芯片用的是 ...

  7. 想好了,我不学iOS和Android,有4个原因

    1. 2w元的工作,用C++也可达到,不必分散精力学不同的技术,而是应该精益求精练同一门语言,但可以做不同的项目 2. PC更强大,手机只是方便而已,我立志要做真正的IT高手,理所当然应该更喜欢PC. ...

  8. Weblogic8.1 的性能优化

    注:在下面做的介绍都是以Weblogic8.1为例的,其它版本的Weblogic可能会有些许不同. 1) 设置JAVA参数: a) 编辑Weblogic Server启动脚本文件: BEA_HOMEu ...

  9. 14.7.1 Resizing the InnoDB System Tablespace InnoDB 系统表空间大小

    14.7.1 Resizing the InnoDB System Tablespace InnoDB 系统表空间大小 这个章节描述如何增加或者减少 InnoDB 系统表空间的大小 增加InnoDB ...

  10. 14.6.5 Configuring InnoDB Change Buffering 配置InnoDB Change Buffering

    14.6.5 Configuring InnoDB Change Buffering 配置InnoDB Change Buffering 当插入,更新,和删除操作在表上执行, 索引列的值(特别是 se ...