在新的项目中,需要实现分享功能,比较后接入友盟分享。友盟分享的使用文档以及常见问题都非常的详细,接入也较为简单。只是分享面板与我们的App风格不太相符,所以自定义了一个分享面板。
项目地址在这里
实现的过程
1. ShareView
- .h文件中,主要属性及初始化方法
// 点击按钮block回调
@property (nonatomic,copy) void(^btnClick)(NSInteger);
// 头部提示文字
@property (nonatomic,copy) NSString *proStr;
// 设置弹窗背景蒙板灰度(0~1)
@property (nonatomic,assign) CGFloat duration;
/**
* 初始化
*
* @param titleArray 标题数组
* @param imageArray 图片数组(如果不需要的话传空数组(@[])进来)
* @param proTitle 最顶部的标题 不需要的话传@""
*
* @return ShareView
*/
- (instancetype)initWithShareHeadOprationWith:(NSArray *)titleArray andImageArry:(NSArray *)imageArray andProTitle:(NSString *)proTitle;
- 初始化时,为视图添加手势,设置背景蒙板灰度,加载自定义视图
- (instancetype)initWithShareHeadOprationWith:(NSArray *)titleArray andImageArry:(NSArray *)imageArray andProTitle:(NSString *)proTitle {
self = [super init];
if (self) {
_shareBtnTitleArray = titleArray;
_shareBtnImageArray = imageArray;
_protext = proTitle;
self.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight);
// 背景,带灰度
self.backgroundColor = WINDOW_COLOR;
// 可点击
self.userInteractionEnabled = YES;
// 点击背景,收起底部分享面板,移除本视图
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tappedCancel)];
[self addGestureRecognizer:tapGesture];
// 加载分享面板
[self loadUIConfig];
}
return self;
}
- 加载视图,依次添加分享的按钮,视图显示时,主要分享面板从底部弹出
/**
加载自定义视图,按钮的tag依次为(200 + i)
*/
- (void)loadUIConfig {
[self addSubview:self.bgView];
[self.bgView addSubview:self.topSheetView];
[self.bgView addSubview:self.cancelBtn];
self.proLbl.text = _protext;
// 按钮
for (NSInteger i = 0; i < self.shareBtnTitleArray.count; i++) {
CGFloat x = self.bgView.bounds.size.width / 3 * ( i % 3);
CGFloat y = LABEL_HEIGHT + (i / 3) * LINE_HEIGHT;
CGFloat w = self.bgView.bounds.size.width / 3;
CGFloat h = 70;
CGRect frame = CGRectMake(x, y, w, h);
ImageWithLabel *item = [ImageWithLabel imageLabelWithFrame:frame Image:[UIImage imageNamed:self.shareBtnImageArray[i]] LabelText:self.shareBtnTitleArray[i]];
item.labelOffsetY = 6;
item.tag = 200 + i;
UITapGestureRecognizer *tapGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(itemClick:)];
[item addGestureRecognizer:tapGes];
[self.topSheetView addSubview:item];
[self.buttons addObject:item];
}
// 弹出
[UIView animateWithDuration:ANIMATE_DURATION animations:^{
self.bgView.frame = CGRectMake(0, ScreenHeight - CGRectGetHeight(self.bgView.frame), ScreenWidth, CGRectGetHeight(self.bgView.frame));
}];
// icon 动画
[self iconAnimation];
}
- 背景面板(这是一排三个的设计,个人认为更好看一些,由于本次分享平台较少,并没有限制高度或者做多高之后可以滚动。。。)
- (UIView *)bgView {
if (_bgView == nil) {
_bgView = [[UIView alloc] init];
// 根据图标个数,计算行数,计算 backgroundView 的高度
NSInteger index;
if (_shareBtnTitleArray.count % 3 == 0) {
index = _shareBtnTitleArray.count / 3;
} else {
index = _shareBtnTitleArray.count / 3 + 1;
}
_bgView.frame = CGRectMake(0, ScreenHeight, ScreenWidth, BUTTON_HEIGHT + (_protext.length == 0 ? 0 : 45) + LINE_HEIGHT * index);
}
return _bgView;
}
- 点击背景面板或者取消按钮
/**
点击取消
*/
- (void)tappedCancel {
[UIView animateWithDuration:ANIMATE_DURATION animations:^{
[self.bgView setFrame:CGRectMake(0, ScreenHeight, ScreenWidth, 0)];
self.alpha = 0;
} completion:^(BOOL finished) {
if (finished) {
[self removeFromSuperview];
}
}];
}
- 这是一个借用了 Facebook 开源框架写的图标弹出动画,有点像今日头条的分享面板(😳)。代码简洁效果炫酷,你值得拥有(😬)。
/**
做一个 icon 依次粗线的弹簧动画
*/
- (void)iconAnimation {
CGFloat duration = 0;
for (UIView *icon in self.buttons) {
CGRect frame = icon.frame;
CGRect toFrame = icon.frame;
frame.origin.y += frame.size.height;
icon.frame = frame;
POPSpringAnimation *animation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame];
animation.toValue = [NSValue valueWithCGRect:toFrame];
animation.beginTime = CACurrentMediaTime() + duration;
animation.springBounciness = 10.0f;
[icon pop_addAnimation:animation forKey:kPOPViewFrame];
duration += 0.07;
}
}
2. 创建与配置
- 判断设备中是否安装了要分享的平台对应的App(微博平台不用判断):
BOOL hadInstalledWeixin = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"weixin://"]];
BOOL hadInstalledQQ = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"mqq://"]];
将安装的了App对应的图标和标题放入数组;
实现 Button 点击的 Block 回调(例),回调的方法里根据不同的 type 设置不同的分享内容:
case 0: {
// 微信
[self shareTextToPlatformType:UMSocialPlatformType_WechatSession shareType:type model:model];
}
- 将分享面板展示:
[[UIApplication sharedApplication].keyWindow addSubview:shareView];
3. 区分不同的平台,设置分享内容
- 创建分享消息对象(U-Share SDK类):
UMSocialMessageObject *messageObject = [UMSocialMessageObject messageObject];
//设置文本
messageObject.text = @"";
- 分享多媒体对象,例分享网页(U-Share SDK方法):
UMShareWebpageObject *webPageObject = [UMShareWebpageObject shareObjectWithTitle:model.title descr:model.detail thumImage:model.thumImage];
webPageObject.webpageUrl = model.url;
messageObject.shareObject = webPageObject;
- 调用分享接口(U-Share SDK方法)
[[UMSocialManager defaultManager] shareToPlatform:platformType messageObject:messageObject currentViewController:self completion:^(id data, NSError *error) {
if (error) {
Log(@"************Share fail with error %@*********",error);
[SVProgressHUD showErrorWithStatus:@"分享失败"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
});
}else{
Log(@"response data is %@",data);
[SVProgressHUD showSuccessWithStatus:@"分享成功"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
});
}
}];
4. 外部调用
ShareModel *model = [ShareModel shareAppModel];
// 分享
[CommonUtils shareBoardBySelfDefinedWithType:ShareTypeApp model:model];
实现的效果
遇到的问题
- 最开始配置好各个分享平台的 URL Scheme 之后,分享功能仍然无法正常使用,经检查是因为 iOS 9 的白名单问题。加入后解决。
- 由于是自定义的分享面板,在调用时需要判断当前设备中是否安装了相应的平台的应用,如 QQ、Wechat等。如果当前设备中没有安装某个应用而面板中带有该平台的分享图标,在 App 审核时可能不会被通过。友盟自带的分享面板已经做过这层判断。