浅谈iOS11新特性:新增拖拽交互体验

一、引言

在使用PC进行操作时,你一定遇到过这样的场景,可以将图片直接拖入聊天软件进行发送,可以将文档、音乐、视频文件等文件拖入相应应用程序直接进行使用。这种拖拽操作交互极大的方便了电脑的使用。在iOS11中,你可以在iPhone或iPad上构建这种交互体验!

说在前面的话:

拖拽操作在iPad上是支持跨应用程序的,你可以从一个应用中拖取项目,通过Home键回到主界面并且打开另一个应用程序,然后将被拖拽的项目传递给这个应用程序中。在iPhone上,拖拽操作只支持当前应用程序内,你可以将某个元素从一个界面拖拽到另一个,这种维度的操作可以给设计人员更大的灵活性。

拖拽操作被设计成系统管理,开发者不需要为App申请特殊的用户权限。

二、拖拽源

对于拖拽操作,至少要有两个组件,一个组件作为拖拽源用来提供数据,一个组件作为拖拽目的用来接收数据,当前,同一个组件既可以是拖拽源也可以是拖拽目的。首先我们先来看拖拽源,在UIKit框架中,iOS11默认实现了一些组件可以作为拖拽源, 例如UITextField、UITextView、UITableView和UICollectionView等。文本组件默认支持拖拽操作进行文本的传递,对于列表组件则默认支持元素的拖拽。例如,在UITextField选中的文案中进行拖拽,可以将文字拖拽出来,效果如下图:

任意的UIView组件都可以作为拖拽源,让其成为拖拽源其实也十分简单,只需要3步:

1.创建一个UIDragInteraction行为对象。

2.设置UIDragInteraction对象的代理并实现相应方法。

3.将UIDragInteraction对象添加到指定View上。

最简单的可拖拽组件的创建示例代码如下:

- (void)viewDidLoad {
  [super viewDidLoad];
  [self.view addSubview:self.dragView];
}
//创建View
-(UIView *)dragView{
  if (!_dragView) {
    _dragView = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
    _dragView.backgroundColor = [UIColor redColor];
    [_dragView addInteraction:self.dragInteraction];
  }
  return _dragView;
}
//创建拖拽行为对象
-(UIDragInteraction *)dragInteraction{
  if (!_dragInteraction) {
    _dragInteraction = [[UIDragInteraction alloc]initWithDelegate:self];
    //要设置可用 注意!!!
    [_dragInteraction setEnabled:YES];
  }
  return _dragInteraction;
}

//实现提供数据的代理方法
- (NSArray<UIDragItem *> *)dragInteraction:(UIDragInteraction *)interaction itemsForBeginningSession:(id<UIDragSession>)session{
  //数据提供者
  NSItemProvider * provider = [[NSItemProvider alloc]initWithObject:@"Hello World"];
  UIDragItem * item = [[UIDragItem alloc]initWithItemProvider:provider];
  return @[item];
}

上面的dragInteraction:代理方法用来提供要传递的数据,传递的数据必须遵守相应的承诺协议,后面会给大家介绍,这里只是简单返回了一个字符串数据Hello World,运行工程,你可以试验下,可以直接将我们自定义的视图拖拽进UITextField并在其中显示Hello World。

三、关于UIDragInteraction类

所有可以接收拖拽行为的组件都必须通过这个类实现,这个类中属性意义列举如下:

//初始化方法
- (instancetype)initWithDelegate:(id<UIDragInteractionDelegate>)delegate;
//代理
@property (nonatomic, nullable, readonly, weak) id<UIDragInteractionDelegate> delegate;
//是否支持多种手势都接收响应
@property (nonatomic) BOOL allowsSimultaneousRecognitionDuringLift;
//设置是否有效
@property (nonatomic, getter=isEnabled) BOOL enabled;
//获取默认是否有效 不同的设备这个值将有所区别
@property (class, nonatomic, readonly, getter=isEnabledByDefault) BOOL enabledByDefault;

四、UIDragInteractionDelegate协议

UIDragInteractionDelegate用来处理拖拽源的行为与数据。其中定义了一个必须实现的方法和许多可选实现的方法。解析如下:

/*
这个方法是必须实现的用来返回拖拽源提供的数据
需要注意,这个函数需要返回一个数组,数组中可以有多个数据源
如果返回空数组,则拖拽行为不会开始
*/
- (NSArray<UIDragItem *> *)dragInteraction:(UIDragInteraction *)interaction itemsForBeginningSession:(id<UIDragSession>)session;
/*
这个方法用来自定义拖拽效果的预览视图 关于预览视图,后面会介绍
需要注意,系统默认会提供一个预览视图,不实现这个方法即是使用系统默认的
如果返回nil,则会去除预览动画
*/
- (nullable UITargetedDragPreview *)dragInteraction:(UIDragInteraction *)interaction previewForLiftingItem:(UIDragItem *)item session:(id<UIDragSession>)session;
/*
拖拽动画即将开始时会调用此函数
*/
- (void)dragInteraction:(UIDragInteraction *)interaction willAnimateLiftWithAnimator:(id<UIDragAnimating>)animator session:(id<UIDragSession>)session;
//拖拽行为会话即将开始时调用的方法
- (void)dragInteraction:(UIDragInteraction *)interaction sessionWillBegin:(id<UIDragSession>)session;
//这个方法设置数据的防止是否允许数据的 移动操作,需要注意,这个只有在app内有效,跨app的操作会总是复制数据
- (BOOL)dragInteraction:(UIDragInteraction *)interaction sessionAllowsMoveOperation:(id<UIDragSession>)session;
//设置是否允许跨应用程序进行拖拽 ipad
- (BOOL)dragInteraction:(UIDragInteraction *)interaction sessionIsRestrictedToDraggingApplication:(id<UIDragSession>)session;
//设置预览视图是否显示原始大小
- (BOOL)dragInteraction:(UIDragInteraction *)interaction prefersFullSizePreviewsForSession:(id<UIDragSession>)session;
/*
当拖拽源被移动时调用,可以用如下方法获取其坐标
NSLog(@"%f,%f",[session locationInView:self.view].x,[session locationInView:self.view].y);
*/
- (void)dragInteraction:(UIDragInteraction *)interaction sessionDidMove:(id<UIDragSession>)session;
//拖拽行为将要结束时调用
- (void)dragInteraction:(UIDragInteraction *)interaction session:(id<UIDragSession>)session willEndWithOperation:(UIDropOperation)operation;
//拖拽行为已经结束时调用
- (void)dragInteraction:(UIDragInteraction *)interaction session:(id<UIDragSession>)session didEndWithOperation:(UIDropOperation)operation;
//拖拽源进行了放置操作后调用
- (void)dragInteraction:(UIDragInteraction *)interaction sessionDidTransferItems:(id<UIDragSession>)session;
//设置拖拽动作取消的视图动画 返回nil则消除动画
-(nullable UITargetedDragPreview *)dragInteraction:(UIDragInteraction *)interaction previewForCancellingItem:(UIDragItem *)item withDefault:(UITargetedDragPreview *)defaultPreview;
//拖拽动作即将取消时调用的方法
- (void)dragInteraction:(UIDragInteraction *)interaction item:(UIDragItem *)item willAnimateCancelWithAnimator:(id<UIDragAnimating>)animator;
//设置是否允许向拖拽中的项目添加数据
/*
可以返回数据载体数组 当拖拽过程中 点击可拖拽的组件时会触发
*/
- (NSArray<UIDragItem *> *)dragInteraction:(UIDragInteraction *)interaction itemsForAddingToSession:(id<UIDragSession>)session withTouchAtPoint:(CGPoint)point;
//设置允许进行拖拽中追加数据的拖拽行为会话
- (nullable id<UIDragSession>)dragInteraction:(UIDragInteraction *)interaction sessionForAddingItems:(NSArray<id<UIDragSession>> *)sessions withTouchAtPoint:(CGPoint)point;
//将要向拖拽组件中追加数据时调用
- (void)dragInteraction:(UIDragInteraction *)interaction session:(id<UIDragSession>)session willAddItems:(NSArray<UIDragItem *> *)items forInteraction:(UIDragInteraction *)addingInteraction;

上面列举的协议方法中有关联到其他许多iOS11中新增的类,后面会一一介绍。其实,完成了以上内容的了解,你就已经可以完全随心所欲的定制拖拽源组件了。

五、放置目的地

拖拽源是数据的提供者,放置目的地就是数据的接收者。前面我们也实验过,将自定义的拖拽源拖拽进UITextField后,文本框中会自动填充我们提供的文本数据。同样,对于任何自定义的UIView视图,我们也可以让其成为放置目的地,需要完成如下3步:

1.创建一个UIDropInteraction行为对象。

2.设置UIDropInteraction对象的代理并实现协议方法。

3.将其添加到自定义的视图中。

例如,我们将自定义的UILabel组件用来显示拖拽的文案:

//添加视图
- (void)viewDidLoad {
  [super viewDidLoad];
  //有关拖拽源的代码 前面已经列举过 这里不再重复
  [self.view addSubview:self.dragView];
  [self.view addSubview:self.dropLabel];
}

-(UILabel *)dropLabel{
  if (!_dropLabel) {
    _dropLabel = [[UILabel alloc]initWithFrame:CGRectMake(10, 300, 300, 30)];
    _dropLabel.backgroundColor = [UIColor greenColor];
    _dropLabel.userInteractionEnabled = YES;
    [_dropLabel addInteraction:self.dropInteraction];
  }
  return _dropLabel;
}
//放置目的地行为对象
-(UIDropInteraction*)dropInteraction{
  if (!_dropInteraction) {
    _dropInteraction = [[UIDropInteraction alloc]initWithDelegate:self];
  }
  return _dropInteraction;
}

//这个方法返回是否响应此放置目的地的放置请求
-(BOOL)dropInteraction:(UIDropInteraction *)interaction canHandleSession:(id<UIDropSession>)session{
  return YES;
}
//设置以何种方式响应拖放会话行为
-(UIDropProposal *)dropInteraction:(UIDropInteraction *)interaction sessionDidUpdate:(id<UIDropSession>)session{
  return [[UIDropProposal alloc]initWithDropOperation:UIDropOperationCopy];
}
//已经应用拖放行为后执行的操作
-(void)dropInteraction:(UIDropInteraction *)interaction performDrop:(id<UIDropSession>)session{
  [session loadObjectsOfClass:[NSString class] completion:^(NSArray<__kindof id<NSItemProviderReading>> * _Nonnull objects) {
    self.dropLabel.text = objects.firstObject;
  }];
}

上面的代码将我们自定义的拖拽源提供的Hello World拖放进了UILabel组件中。

六、关于UIDropInteraction类

与UIDragInteraction类类似,这个类的作用是让组件有相应放置操作的能力。其中属性如下:

//初始化方法
- (instancetype)initWithDelegate:(id<UIDropInteractionDelegate>)delegate;
//代理对象
@property (nonatomic, nullable, readonly, weak) id<UIDropInteractionDelegate> delegate;
//是否允许多个交互行为
@property (nonatomic, assign) BOOL allowsSimultaneousDropSessions;

七、UIDropInteractionDelegate协议

UIDropInteractionDelegate协议中所定义的方法全部是可选实现的,其用来处理用户放置交互行为。

//放置行为即将响应时触发的方法 返回值确定是否响应此次行为
- (BOOL)dropInteraction:(UIDropInteraction *)interaction canHandleSession:(id<UIDropSession>)session;
//当上面的协议方法返回YES时会接着调用这个函数
- (void)dropInteraction:(UIDropInteraction *)interaction sessionDidEnter:(id<UIDropSession>)session;
//将要处理数据时回调的方法
/*
当数据源数据添加时,这个方法也会被重新调用
这个函数需要返回一个处理行为方式UIDropProposal对象,这个我们后面再说
*/
- (UIDropProposal *)dropInteraction:(UIDropInteraction *)interaction sessionDidUpdate:(id<UIDropSession>)session;
//放置行为相应结束的时候会调用此方法
- (void)dropInteraction:(UIDropInteraction *)interaction sessionDidExit:(id<UIDropSession>)session;
//这个方法当用户进行放置时会调用,可以从session中获取被传递的数据
- (void)dropInteraction:(UIDropInteraction *)interaction performDrop:(id<UIDropSession>)session;
//放置动画完成后会调用这个方法
- (void)dropInteraction:(UIDropInteraction *)interaction concludeDrop:(id<UIDropSession>)session;
//整个拖放行为结束后会调用
- (void)dropInteraction:(UIDropInteraction *)interaction sessionDidEnd:(id<UIDropSession>)session;
//下面这些方法用来自定义放置动画
//设置放置预览动画
- (nullable UITargetedDragPreview *)dropInteraction:(UIDropInteraction *)interaction previewForDroppingItem:(UIDragItem *)item withDefault:(UITargetedDragPreview *)defaultPreview;
//这个函数每当有一个拖拽数据项放入时都会调用一次 可以进行动画
- (void)dropInteraction:(UIDropInteraction *)interaction item:(UIDragItem *)item willAnimateDropWithAnimator:(id<UIDragAnimating>)animator;

需要注意,UIDropProposal类用来进行处理回执,属性方法解析如下:

//初始化方法
/*
typedef NS_ENUM(NSUInteger, UIDropOperation) {
  //取消这次行为
  UIDropOperationCancel  = 0,
  //拒绝行为
  UIDropOperationForbidden = 1,
  //接收拷贝数据
  UIDropOperationCopy   = 2,
  //接收移动数据
  UIDropOperationMove   = 3,
}
*/
- (instancetype)initWithDropOperation:(UIDropOperation)operation;
//处理方式
@property (nonatomic, readonly) UIDropOperation operation;
//精准定位
@property (nonatomic, getter=isPrecise) BOOL precise;
//设置是否展示完整的预览尺寸
@property (nonatomic) BOOL prefersFullSizePreview;

八、拖拽数据载体UIDragItem类

UIDragItem类用来承载要传递的数据。其通过NSItemProvider类来进行构建,传递的数据类型是有严格规定的,必须遵守一定的协议,系统的NSString,NSAttributeString,NSURL,UIColor和UIImage是默认支持的,你可以直接传递这些数据。

UIDragItem中提供的属性方法:

//初始化方法
- (instancetype)initWithItemProvider:(NSItemProvider *)itemProvider;
//数据提供者实例
@property (nonatomic, readonly) __kindof NSItemProvider *itemProvider;
//用来传递一些额外的关联信息
@property (nonatomic, strong, nullable) id localObject;
//用来自定义每个item添加时的预览动画
@property (nonatomic, copy, nullable) UIDragPreview * _Nullable (^previewProvider)(void);

九、UIDropSession与UIDragSession

在与拖拽交互相关的接口中,这两个是面向协议编程的绝佳范例,首先在UIKit框架中只定义了这两个协议,而并没有相关的实现类,在拖拽行为的相关回调接口中,很多id类型的参数都遵守了这个协议,我们无需知道是哪个类实现的,直接进行使用即可:

UIDropSession:

//继承于UIDragDropSession(提供基础数据), NSProgressReporting(提供数据读取进度)
@protocol UIDropSession <UIDragDropSession, NSProgressReporting>
//原始的dragSesstion会话 如果是跨应用的 则为nil
@property (nonatomic, readonly, nullable) id<UIDragSession> localDragSession;
//设置进度风格
/*
typedef NS_ENUM(NSUInteger, UIDropSessionProgressIndicatorStyle) {
  UIDropSessionProgressIndicatorStyleNone,    // 无
  UIDropSessionProgressIndicatorStyleDefault,  // 默认的
} API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(watchos, tvos);
*/
@property (nonatomic) UIDropSessionProgressIndicatorStyle progressIndicatorStyle;
//进行数据的加载
- (NSProgress *)loadObjectsOfClass:(Class<NSItemProviderReading>)aClass completion:(void(^)(NSArray<__kindof id<NSItemProviderReading>> *objects))completion;
@end

UIDragSession:

API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(watchos, tvos) @protocol UIDragSession <UIDragDropSession>
//设置要传递的额外信息 只有在同个APP内可见
@property (nonatomic, strong, nullable) id localContext;
@end

UIDragDropSession:

//传递的数据数组
@property (nonatomic, readonly) NSArray<UIDragItem *> *items;
//当前操作行为的坐标
- (CGPoint)locationInView:(UIView *)view;
//此次行为是否允许移动操作
@property (nonatomic, readonly) BOOL allowsMoveOperation;
//是否支持应用程序层面的拖拽
@property (nonatomic, readonly, getter=isRestrictedToDraggingApplication) BOOL restrictedToDraggingApplication;
//验证传递的数据是否支持某个数据类型协议
- (BOOL)hasItemsConformingToTypeIdentifiers:(NSArray<NSString *> *)typeIdentifiers;
//验证传递的数据是否可以加载某个类
- (BOOL)canLoadObjectsOfClass:(Class<NSItemProviderReading>)aClass;

十、交互预览类UITargetedDragPreview

UITargetedDragPreview专门用来处理拖放交互过程中的动画与预览视图。方法解析如下:

//创建一个预览对象
/*
view:要创建的预览视图 需要注意,这个视图必须在window上
param:配置参数
target:容器视图,用来展示预览,一般设置为view的父视图
*/
- (instancetype)initWithView:(UIView *)view parameters:(UIDragPreviewParameters *)parameters target:(UIDragPreviewTarget *)target;
//同上
-(instancetype)initWithView:(UIView *)view parameters:(UIDragPreviewParameters *)parameters;
//同上
- (instancetype)initWithView:(UIView *)view;
//动画承载者
@property (nonatomic, readonly) UIDragPreviewTarget* target;
//动画视图
@property (nonatomic, readonly) UIView *view;
//配置参数
@property (nonatomic, readonly, copy) UIDragPreviewParameters *parameters;
//尺寸
@property (nonatomic, readonly) CGSize size;
//返回新的对象
- (UITargetedDragPreview *)retargetedPreviewWithTarget:(UIDragPreviewTarget *)newTarget;

UIDragPreviewTarget主要用来设置动画的起始视图与结束时回归的视图,其中属性方法如下:

/*
初始化方法
container:必须是在window上的view
center:动画起点与终点
transform:进行变换
*/
- (instancetype)initWithContainer:(UIView *)container center:(CGPoint)center transform:(CGAffineTransform)transform;
//同上
- (instancetype)initWithContainer:(UIView *)container center:(CGPoint)center;
//对应属性
@property (nonatomic, readonly) UIView *container;
@property (nonatomic, readonly) CGPoint center;
@property (nonatomic, readonly) CGAffineTransform transform;

UIDragPreviewParameters用来进行拖拽动画的配置,解析如下:

//构造方法并设置路径矩形
- (instancetype)initWithTextLineRects:(NSArray<NSValue /* CGRect */ *> *)textLineRects;
//显示的路径
@property (nonatomic, copy, nullable) UIBezierPath *visiblePath;
//背景色
@property (nonatomic, copy, null_resettable) UIColor *backgroundColor;

我们可以使用任意自定义的视图来展现这个预览动画,如下图所示:

十一、使用拖拽操作进行自定义数据的传递

本篇文章到这里,其实基本的内容都已经说完了,虽然比较详细,也可能难免冗余,如果你耐着性子看到了这里,那么我首先钦佩你的毅力并且感谢你的耐心。其实,拖拽交互如果进行只能对系统的提供的数据类型进行操作则应用就局限太多。试想一下,如果我们可以通过拖拽商品来进行购买,拖拽联系人来进行发送,或者在游戏中,拖拽进行卡片的融合,装备的提炼等等这种交互操作是不是会很畅快。最后,我们就来看看如何让自定义的数据类型支持拖拽操作。

首先你需要关注两个协议,NSItemProviderWriting与NSItemProviderReading。Writing协议用来让数据支持提供给数据源,Reading协议让数据支持从数据源读出,用自定义的Person类为例:

#import <Foundation/Foundation.h>
//遵守协议
@interface Person : NSObject<NSItemProviderWriting,NSItemProviderReading>
//自定义内容
@property(nonatomic,strong)NSString * name;
@property(nonatomic,assign)NSUInteger age;
@end
//.m文件
@implementation Person
//数据归档
- (nullable NSProgress *)loadDataWithTypeIdentifier:(NSString *)typeIdentifier
          forItemProviderCompletionHandler:(void (^)(NSData * _Nullable data, NSError * _Nullable error))completionHandler{
  NSProgress * pro = [NSProgress new];
  NSData * data = [NSKeyedArchiver archivedDataWithRootObject:self];
  completionHandler(data,nil);
  return pro;
}

+(NSItemProviderRepresentationVisibility)itemProviderVisibilityForRepresentationWithTypeIdentifier:(NSString *)typeIdentifier{
  return NSItemProviderRepresentationVisibilityAll;
}

- (NSItemProviderRepresentationVisibility)itemProviderVisibilityForRepresentationWithTypeIdentifier:(NSString *)typeIdentifier{
  return NSItemProviderRepresentationVisibilityAll;
}
//提供一个标识符
+(NSArray<NSString *> *)writableTypeIdentifiersForItemProvider{
  return @[@"object"];
}
-(NSArray<NSString *> *)writableTypeIdentifiersForItemProvider{
  return @[@"object"];
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
  self = [super init];
  if (self) {
    self.name = [coder decodeObjectForKey:@"name"];
    self.age = [coder decodeIntegerForKey:@"age"];
  }
  return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder{
  [aCoder encodeObject:self.name forKey:@"name"];
  [aCoder encodeInteger:self.age forKey:@"age"];
}
//这两个是读协议
+(NSArray<NSString *> *)readableTypeIdentifiersForItemProvider{
  return @[@"object"];
}
//解归档返回
+ (nullable instancetype)objectWithItemProviderData:(NSData *)data
                   typeIdentifier:(NSString *)typeIdentifier
                       error:(NSError **)outError{
  Person * p = [NSKeyedUnarchiver unarchiveObjectWithData:data];
  return p;
}
@end

需要注意,在拖放行为读取数据时的类型要对应,如下:

-(void)dropInteraction:(UIDropInteraction *)interaction performDrop:(id<UIDropSession>)session{
  NSLog(@"%@",session.items.lastObject.localObject);
  [session loadObjectsOfClass:[Person class] completion:^(NSArray<__kindof id<NSItemProviderReading>> * _Nonnull objects) {
    self.dropLabel.text = ((Person*)objects.firstObject).name;
  }];
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android ReboundScrollView仿IOS拖拽回弹效果

    初衷: 其实github上有很多这种ScrollView的项目,但是不得不说功能太多太乱了,我就只是想要一个简单效果的ScrollView,另外监听下滑动距离而已,想想还是自己写了个. 这里先说下思路吧,如果不愿意看的朋友可以直接跳过这一步,看下面的代码: Android 原生的ScrollView是不支持拉出屏幕外,并且也没有回弹效果的,用户友好度却不不太好,不知道为什么不那么设计. 我想做的事情正如上面所述: 1.希望能拉出屏幕外 2.松手后希望控件回弹 我的思路是对ScrollView的子

  • 浅谈iOS11新特性:新增拖拽交互体验

    一.引言 在使用PC进行操作时,你一定遇到过这样的场景,可以将图片直接拖入聊天软件进行发送,可以将文档.音乐.视频文件等文件拖入相应应用程序直接进行使用.这种拖拽操作交互极大的方便了电脑的使用.在iOS11中,你可以在iPhone或iPad上构建这种交互体验! 说在前面的话: 拖拽操作在iPad上是支持跨应用程序的,你可以从一个应用中拖取项目,通过Home键回到主界面并且打开另一个应用程序,然后将被拖拽的项目传递给这个应用程序中.在iPhone上,拖拽操作只支持当前应用程序内,你可以将某个元素从

  • 浅谈ECMAScript6新特性之let、const

    第一次写博客有点紧张,如果说的不对的地方,欢迎大家留言指正.咱们先来说说"ECMAScript"这到底是啥玩意儿?它和javascript的关系又是如何的?首先,在1996年11月的时候,javascript的创造者(网景公司Netscape)和sun公司联合ECMA(欧洲计算机制造商协会)对javascript进行标准化,次年,ECMA发布262号标准文件文件(ECMA-262)的第一版,规定了浏览器脚本语言的标准(在这里提个问题:为什么要标准化?),并将这种语言称为ECMAScri

  • 浅谈Java8新特性Predicate接口

    一.前言 Java 8中引入了Predicate功能接口. Java Predicate表示一个参数的谓词. Predicate是一个布尔值的函数. Java Predicate是一个功能接口,属于java.util.function包. Predicate的功能方法是test(T t). Predicate的其他方法是test.isEqual.and.or.negate和not. not方法在Java 11中被引入. 在本文章,我们将提供Predicate的例子及其所有方法. 二.test(T

  • IOS11新特性与兼容适配

    IOS11发布以来,很多新的特性为开发工作提供了方便,小编在此给大家介绍一下IOS11的新特性以及在兼容适配等做的工作. 1. UIView变化 1.1. 更加方便的RTL边距设置 在之前的系统中我们会使用layoutMargins来获取和设置控件显示内容部分的边缘与控件边缘的距离.在iOS 11中,新增directionalLayoutMargins属性来指定边距.这两个属性的结构定义如下: typedef struct UIEdgeInsets { CGFloat top, left, bo

  • 浅谈python新手中常见的疑惑及解答

    1 lambda函数 函数格式是lambda keys:express   匿名函数lambda是一个表达式函数,接受keys参数,返回表达式的值.所以不用return,也没有函数名,经常用在需要key参数的函数中,比如sorted. 2 元组(),它是以逗号辨别的,而不是小括号.比如一个元素的元组新手经常写成(12),其实他会被解释成单个元素12.正确的写法应该是(12,),在元素后面加上逗号. 3 模块导入.比如 import random print random.choice(range

  • 详解IOS11新特性之larget title的实现

    本文介绍了IOS11新特性之larget title的实现,分享给大家,具体如下: 大标题(larget title) 图层解析 小标题所处.jpg 这就是我们平常所见的Nav的title 大标题所处.jpg 这是IOS11新特性larget title 处于哪里.jpg 他们其实都在navigationBar这个view上,但是大标题先添加在navigationBar上的,看下图便知道了 上拉到顶部.png 只不过是小标题把大标题遮盖住了 //必须要设置navigationBar的prefer

  • 浅谈JDK9的特性之JVM的xlog

    简介 JVM是java程序运行的基础,JVM中各种事件比如:GC,class loading,JPMS,heap,thread等等其实都可以有日志来记录.通过这些日志,我们可以监控JVM中的事件,并可以依次来对java应用程序进行调优. 在JDK9中引入的Xlog日志服务就是为这个目的而创建的. 通过xlog,JDK将JVM中的各种事件统一起来,以统一的形式对外输出.通过tag参数来区分子系统,通过log level来区分事件的紧急性,通过logging output来配置输出的地址. xlog

  • 浅谈PHP 闭包特性在实际应用中的问题

    呃,其实大部分情况下是可以的,而有些方面还是令人非常的困扰,下面慢慢道来. 很多语言的都提供了非常优雅和漂亮的操作数组的方法.在下面的例子中,会使用 PHP5.3 以及其他语言提供的闭包功能,用于展示如何"客观的"操作迭代数组. 译注:原文作者比较火星,我不了解 Groovy 以及 Scala 语言,所以这里我加上 Javascript 的实现. 在开始之前先说明下,本例子仅仅是阐明观点,并没有考虑性能等其他方面的因素. "货比三家" 用个简单的例子开始,有下面个数

  • iOS11新特性之在你的APP中使用LargeTitle

    随着WWDC17以及Apple 2017秋季新品发布会的召开,Apple也在9月20日正式推送了iOS 11的正式版.在iOS 11中,Apple也推出了全新的UI风格. UI风格 在iOS 11中,系统APP使用了这种UI风格.这种风格最明显的变化就是使用了iOS 11的新特性--Large Title和新的SearchController. Demo GitHub: LargerTitleDemo Large Title & Table View 设置Lager Title APP全局使用L

  • 浅谈Android客户端与服务器的数据交互总结

    前言: 本文总结了Android客户端与服务器进行交互时,采用RESTful API +Json的交互方式,针对不同的数据形式以及不同的解析方法,如有不足之处,欢迎指正. 温馨提示:本文适合有一定Android开发经验的人阅读,如有疑问,欢迎留言讨论. 先了解一下相关的基本概念. 1. Android客户端与服务器端通信方式 通信方式主要有HTTP和Socket. HTTP通信:即使用HTTP协议进行通信,工作原理是客户端向服务器端发送一条HTTP请求,服务器收到之后先解析客户端的请求,之后会返

随机推荐