1、UITextView
2、UITextField
3、UIWebView
UIKit framework提供了几个类和协议方便我们在自己的应用程序中实现剪贴板的功能。
1、UIPasteboard:我们可以向其中写入数据,也可以读取数据
2、UIMenuController:显示一个快捷菜单,用来展示复制、剪贴、粘贴等选择的项。
3、UIResponder中的 canPerformAction:withSender:用于控制哪些命令显示在快捷菜单中。
4、当快捷菜单上的命令点击的时候,UIResponderStandardEditActions将会被调用。
下面这些项能被放置到剪贴板中
1、UIPasteboardTypeListString — 字符串数组, 包含kUTTypeUTF8PlainText
2、UIPasteboardTypeListURL — URL数组,包含kUTTypeURL
3、UIPasteboardTypeListImage — 图形数组, 包含kUTTypePNG 和kUTTypeJPEG
4、UIPasteboardTypeListColor — 颜色数组
剪贴板的类型分为两种:
系统级:使用UIPasteboardNameGeneral和UIPasteboardNameFind,系统级应用程序关闭,或者卸载的数据不会丢失。
应用程序级:通过设置,可以让数据在应用程序关闭之后仍然保存在剪贴板中,但是应用程序卸载之后数据就会失去。我们可用通过pasteboardWithName:create:来创建。
例子如下:
有时候我们可能需要复制UILabel上的文本,或者UIImageView的图片,而UILabel和UIImageView默认是不响应Touch事件的,也无法复制,那么我们就需要自己实现一个可复制的UILabel。新添加一个类继承自UILabel:
@interface UICopyLabel : UILabel
@end
#import "UICopyLabel.h"
@implementation UICopyLabel
@end
为了能接收到事件(能成为第一响应者),我们需要覆盖一个方法:
-(BOOL)canBecomeFirstResponder
{
return YES
}
还需要针对复制的 *** 作覆盖两个方法:
// 可以响应的方法
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
return (action == @selector(copy:))
}
//针对于响应方法的实现
-(void)copy:(id)sender
{
UIPasteboard *pboard = [UIPasteboard generalPasteboard]
pboard.string = self.text
}
有了以上三个方法,我们就能处理copy了,当然,在能接收到事件的情况下:
//UILabel默认是不接收事件的,我们需要自己添加touch事件
-(void)attachTapHandler
{
self.userInteractionEnabled = YES //用户交互的总开关
UITapGestureRecognizer *touch = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]
touch.numberOfTapsRequired = 2
[self addGestureRecognizer:touch]
[touch release]
}
//绑定事件
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame]
if (self)
{
[self attachTapHandler]
}
return self
}
//同上
-(void)awakeFromNib
{
[super awakeFromNib]
[self attachTapHandler]
}
我们已经可以接收到事件了!由于我在上方将tap数设为2,所以需要双击才能捕获,接下来,我们需要处理这个tap,以便让菜单栏d出来:
-(void)handleTap:(UIGestureRecognizer*) recognizer
{
[self becomeFirstResponder]
UIMenuItem *copyLink = [[[UIMenuItemalloc] initWithTitle:@"复制"
action:@selector(copy:)]autorelease]
[[UIMenuControllersharedMenuController] setMenuItems:[NSArrayarrayWithObjects:copyLink, nil]]
[[UIMenuControllersharedMenuController] setTargetRect:self.frameinView:self.superview]
[[UIMenuControllersharedMenuController] setMenuVisible:YESanimated: YES]
}
这样一来,一个可复制的UILabel就诞生了!它能处理接收点击、d出菜单栏、处理copy,这是一个很普通的可复制控件。
接下来我们做一个可复制的UIImageView,创建一个新的viewController,放两个imageView,默认显示不同的图:
然后把上面的代码直接拷过来,改三个地方:
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
return (action == @selector(copy:) || action == @selector(paste:))
}
-(void)copy:(id)sender
{
UIPasteboard *pboard = [UIPasteboard generalPasteboard]
pboard.image = self.image
}
-(void)paste:(id)sender
{
UIPasteboard *pboard = [UIPasteboard generalPasteboard]
self.image = pboard.image
}
UIPasteboard有系统级别和应用级别两种类型,所以不仅可以在应用程序内通信,还能在应用程序间通信,比如我复制一个url,然后打开safari,粘贴到地址栏去,而我们可以在应用程序间通信、共享数据。
在PasteBoardWrite里面点“写入”后把textField中的文本写入粘贴板,然后切换到PasteBoardRead的时候显示出来。如果我们的粘贴板只想给“自己人”用的话,就不能用系统的通用粘贴板,需要我们自己创建一个:
//需要提供一个唯一的名字,一般使用倒写的域名:com.mycompany.myapp.pboard
//后面的参数表示,如果不存在,是否创建一个
UIPasteboard *pb = [UIPasteboard pasteboardWithName:@"testBoard" create:YES]
使用这个粘贴板,我们可以把文本存进去,然后在另一个app里面读出来,一些常用的类型已经被设置为属性了:
除此之外,如果是能够转换成plist的数据类型(NSString, NSArray, NSDictionary, NSDate, NSNumber 和 NSURL),我们可以调用setValue:forPasteboardType:方法去存储数据,其他类型只能调用setData:forPasteboardType:方法(plist数据类型也可使用),类似于这样:
//存储数据
NSDictionary *dict = [NSDictionary dictionaryWithObject:textField.text forKey:@"content"]
NSData *dictData = [NSKeyedArchiver archivedDataWithRootObject:dict]
[pb setData:dictData forPasteboardType:@"myType"]
//获取就类似于这样:
UIPasteboard *pb = [UIPasteboard pasteboardWithName:@"testBoard" create:YES]
NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithData:[pb dataForPasteboardType:@"myType"]]
caption.text = [dict objectForKey:@"content"]
上面提到了一个PasteboardType,这是一个统一类型标识符(Uniform Type Identifier UTI),能帮助app获取自己能处理的数据。比如你只能处理文本的粘贴,那给你一个UIImage显然是无用的。你可以使用公用的UTI,也可以使用任意字符,苹果建议使用倒写的域名加上类型名:com.myCompany.myApp.myType。
问题:YYLabel继承于UIView不支持项目本身的自定义表情,UILabel能正常显示自定义表情,pass
思路:手动获取label的显示字符个数,自己处理展示逻辑+点击逻辑
手动获取label的显示字符个数
1.用UITextView的链接,有点瑕疵。
具体为:点击一下会出现灰色背景色,长按会出现一个菜单,还有剪切复制菜单。
txtView.isSelectable = false // 同时禁用了可选和超链接跳转
canPerformAction return false // 不显示菜单栏了,但是仍然可选
添加长按手势以屏蔽默认的手势 // 不能屏蔽
添加自定义手势,并禁用掉其他手势 // do work
2.用CoreText的点击
瑕疵:
展开文案没有完全居右
收起的点击区域不太准确
带表情的多行文本展示了2行
3.保底方案
另起一行展开/收起,不追加在内容后面。
遇到问题:展开收起-tabview闪动
禁用掉预估高度,然后手动计算cell高度即可
1、let line: CTLineRef = CFArrayGetValueAtIndex(lines, 0)
这会产生错误“’ConstUnsafePointer<()&'不能转换为'CTLineRef''. Cast似乎没有改变这个错误
let line: CTLineRef = lines[0]
产生错误“’CFArrayRef’没有名为’subscript’的成员”
改用unsafeBitCast即可
Swift 类型UnsafeRawPointer转化报错
2、ios获取UILabel每行显示的文字
https://www.jianshu.com/p/65a07b6013c7
3、iOS 富文本添加点击事件
https://www.jianshu.com/p/480db0cc7380
4、iOS中CoreText框架探究
https://www.jianshu.com/p/9987e6194b2e
5、展开收起-tabview闪动
禁用掉预估高度,然后手动计算cell高度即可
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)