分享功能目前几乎已成为很多app的标配了,其中微信,微博等app的图片分享界面设计的很棒,不仅能够展示缩略图,还可以预览删除。最近我在做一款社交分享app,其中就要实现图文分享功能,于是试着自行实现仿微信分享风格的功能。

核心思想

主要是使用UICollectionView来动态加载分享图片内容,配合预览页面,实现动态添加和预览删除图片效果。

实现效果

核心代码如下:

分享界面:

//
// PostTableViewController.h
// NineShare
//
// Created by 张昌伟 on 15/1/26.
// Copyright (c) 2015年 9Studio. All rights reserved.
// #import <UIKit/UIKit.h>
#import "UMSocial.h"
#import "YSYPreviewViewController.h" @interface PostTableViewController : UITableViewController<UITextViewDelegate,UICollectionViewDataSource,UICollectionViewDelegate,UIActionSheetDelegate,UIImagePickerControllerDelegate,UMSocialUIDelegate,UINavigationControllerDelegate> @property (weak, nonatomic) IBOutlet UICollectionView *photosCollectionView;
@property (weak, nonatomic) IBOutlet UISwitch *WeiboSwitch;
@property (weak, nonatomic) IBOutlet UISwitch *RenrenSwitch;
- (IBAction)DoubanSwitched:(id)sender;
- (IBAction)RenrenSwitched:(id)sender;
- (IBAction)WeiboSwitched:(id)sender; +(void) deleteSelectedImage:(NSInteger) index;
+(void) deleteSelectedImageWithImage:(UIImage*)image;
@end

实现文件

//
// PostTableViewController.m
// NineShare
//
// Created by 张昌伟 on 15/1/26.
// Copyright (c) 2015年 9Studio. All rights reserved.
// #import "PostTableViewController.h"
#import "NineShareService.h"
static NSMutableArray *currentImages;
@interface PostTableViewController ()
@property (weak, nonatomic) IBOutlet UITextView *shareContent;
- (IBAction)postStatus:(id)sender;
- (IBAction)cancelPost:(id)sender;
-(void) loadSNSStatus;
@property (weak, nonatomic) IBOutlet UISwitch *DoubanSwitch;
@property (weak, nonatomic) IBOutlet UITextView *backgroundTextView;
@property NSMutableArray *snsArray;
//@property NSMutableArray *photos;
@property NineShareService *dataContext;
@property NSMutableDictionary *tempDict; -(void) openCamera;
-(void) openLibary; @end @implementation PostTableViewController - (void)viewDidLoad {
[super viewDidLoad];
if(currentImages ==nil)
{
currentImages=[[NSMutableArray alloc] init];
}
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO; // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
_dataContext=[NineShareService getInstance];
[self loadSNSStatus];
}
-(void)viewWillAppear:(BOOL)animated{
[_photosCollectionView reloadData];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} -(void) loadSNSStatus{
_snsArray=[NSMutableArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sns" ofType:@"plist"]];
if(_snsArray.count>0)
{
[_WeiboSwitch setOn:[_snsArray[0] boolValue] animated:YES];
[_RenrenSwitch setOn:[_snsArray[1] boolValue] animated:YES];
[_DoubanSwitch setOn:[_snsArray[2] boolValue] animated:YES];
}
}
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
if(![text isEqualToString:@""])
{
[_backgroundTextView setHidden:YES];
}
if([text isEqualToString:@""]&&range.length==1&&range.location==0){
[_backgroundTextView setHidden:NO];
}
if ([text isEqualToString:@"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
-(void)textViewDidBeginEditing:(UITextView *)textView
{
CGRect frame = textView.frame;
int offset = frame.origin.y + 32 - (self.view.frame.size.height - 216.0);//键盘高度216 NSTimeInterval animationDuration = 0.30f;
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration]; //将视图的Y坐标向上移动offset个单位,以使下面腾出地方用于软键盘的显示
if(offset > 0)
self.view.frame = CGRectMake(0.0f, -offset, self.view.frame.size.width, self.view.frame.size.height); [UIView commitAnimations];
} -(void)textViewDidEndEditing:(UITextView *)textView{
self.view.frame =CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
if(indexPath.row==currentImages.count)
{
UIActionSheet *action=[[UIActionSheet alloc] initWithTitle:@"选取照片" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"从摄像头选取", @"从图片库选择",nil];
[action showInView:self.view];
}
else
{
[YSYPreviewViewController setPreviewImage:currentImages[indexPath.row]];
[self.navigationController pushViewController:[[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"PreviewVC"] animated:YES];
}
} -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return currentImages.count==0?1:currentImages.count+1;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"collectionCell" forIndexPath:indexPath];
UIImageView *imageView=[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
if(currentImages.count==0||indexPath.row==currentImages.count)
{
imageView.image=[UIImage imageNamed:@"Add"];
}
else{ while ([cell.contentView.subviews lastObject] != nil) {
[(UIView*)[cell.contentView.subviews lastObject] removeFromSuperview];
}
imageView.image=currentImages[indexPath.row];
} imageView.contentMode=UIViewContentModeScaleAspectFill;
[cell.contentView addSubview:imageView];
return cell;
} -(void)saveSNSToFile{
NSString *destPath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
if (![[NSFileManager defaultManager] fileExistsAtPath:destPath]) {
NSString *path=[[NSBundle mainBundle] pathForResource:@"sns" ofType:@"plist"];
[[NSFileManager defaultManager] copyItemAtPath:path toPath:destPath error:nil];
} if(_snsArray==nil)
_snsArray=[[NSMutableArray alloc] init];
[_snsArray removeAllObjects];
[_snsArray addObject:_WeiboSwitch.isOn?@"YES":@"NO"];
[_snsArray addObject:_RenrenSwitch.isOn?@"YES":@"NO"];
[_snsArray addObject:_DoubanSwitch.isOn?@"YES":@"NO"];
if(_snsArray.count>0)
{
[_snsArray writeToFile:destPath atomically:YES];
}
} - (IBAction)postStatus:(id)sender {
if(_WeiboSwitch.isOn)
[[UMSocialDataService defaultDataService] postSNSWithTypes:@[UMShareToSina] content:_shareContent.text.length>0?_shareContent.text: @"9Share for ios test message" image:currentImages.count==0?nil:currentImages[0] location:nil urlResource:nil presentedController:self completion:^(UMSocialResponseEntity *response){
if (response.responseCode == UMSResponseCodeSuccess) {
NSLog(@"分享成功!");
if(!(_RenrenSwitch.isOn||_DoubanSwitch.isOn))
{
[self saveSNSToFile];
[self dismissViewControllerAnimated:YES completion:nil];
}
}
}];
if(_RenrenSwitch.isOn)
[[UMSocialDataService defaultDataService] postSNSWithTypes:@[UMShareToRenren] content:_shareContent.text.length>0?_shareContent.text: @"9Share for ios test message" image:currentImages.count==0?nil:currentImages[0] location:nil urlResource:nil presentedController:self completion:^(UMSocialResponseEntity *response){
if (response.responseCode == UMSResponseCodeSuccess) {
NSLog(@"分享成功!");
if(!_DoubanSwitch.isOn)
{
[self saveSNSToFile];
[self dismissViewControllerAnimated:YES completion:nil];
}
}
}];
if(_DoubanSwitch.isOn)
[[UMSocialDataService defaultDataService] postSNSWithTypes:@[UMShareToDouban] content:_shareContent.text.length>0?_shareContent.text: @"9Share for ios test message" image:currentImages.count==0?nil:currentImages[0] location:nil urlResource:nil presentedController:self completion:^(UMSocialResponseEntity *response){
if (response.responseCode == UMSResponseCodeSuccess) {
NSLog(@"分享成功!");
[self saveSNSToFile];
[self dismissViewControllerAnimated:YES completion:nil];
}
}]; } -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
[picker dismissViewControllerAnimated:YES completion:nil];
UIImage *image=[info objectForKey:UIImagePickerControllerOriginalImage];
NSData *tempData=UIImageJPEGRepresentation(image, 0.5f);
image=[UIImage imageWithData:tempData];
if(currentImages ==nil)
{
currentImages=[[NSMutableArray alloc] init];
}
[currentImages addObject:image];
[_photosCollectionView reloadData];
// [self saveImage:image withName:@""]
} -(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
[picker dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)cancelPost:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
} -(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{ switch (buttonIndex) {
case 0:
[self openCamera];
break;
case 1:
[self openLibary];
break;
default:
break;
}
}
-(void)openCamera{
//UIImagePickerControllerSourceType *type=UIImagePickerControllerSourceTypeCamera;
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
UIImagePickerController *picker=[[UIImagePickerController alloc] init];
picker.delegate=self;
picker.sourceType=UIImagePickerControllerSourceTypeCamera;
picker.allowsEditing=YES;
[self presentViewController:picker animated:YES completion:nil]; }
}
-(void)openLibary{
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary])
{
UIImagePickerController *picker=[[UIImagePickerController alloc] init];
picker.delegate=self;
picker.sourceType=UIImagePickerControllerSourceTypePhotoLibrary;
picker.allowsEditing=YES;
[self presentViewController:picker animated:YES completion:nil]; } }
-(void) saveImage:(UIImage *)image withName:(NSString *)name
{
NSData *imageData=UIImageJPEGRepresentation(image, 0.5);
NSString *path=[NSTemporaryDirectory() stringByAppendingPathComponent:name];
[imageData writeToFile:path atomically:YES]; }
- (IBAction)DoubanSwitched:(id)sender {
if(_DoubanSwitch.isOn){
if(![UMSocialAccountManager isOauthAndTokenNotExpired:UMShareToDouban])
{
//进入授权页面
[UMSocialSnsPlatformManager getSocialPlatformWithName:UMShareToDouban].loginClickHandler(self,[UMSocialControllerService defaultControllerService],YES,^(UMSocialResponseEntity *response){
if (response.responseCode == UMSResponseCodeSuccess) {
//获取微博用户名、uid、token等
UMSocialAccountEntity *snsAccount = [[UMSocialAccountManager socialAccountDictionary] valueForKey:UMShareToDouban];
NSLog(@"username is %@, uid is %@, token is %@",snsAccount.userName,snsAccount.usid,snsAccount.accessToken);
//进入你的分享内容编辑页面
UMSocialAccountEntity *doubanAccount = [[UMSocialAccountEntity alloc] initWithPlatformName:UMShareToDouban];
doubanAccount.usid = snsAccount.usid;
doubanAccount.accessToken = snsAccount.accessToken;
// weiboAccount.openId = @"tencent weibo openId"; //腾讯微博账户必需设置openId
//同步用户信息
[UMSocialAccountManager postSnsAccount:doubanAccount completion:^(UMSocialResponseEntity *response){
if (response.responseCode == UMSResponseCodeSuccess) {
//在本地缓存设置得到的账户信息
[UMSocialAccountManager setSnsAccount:doubanAccount];
//进入你自定义的分享内容编辑页面或者使用我们的内容编辑页面
}}];
}
else {
[_DoubanSwitch setOn:NO animated:YES];
}
});
}
}
} - (IBAction)RenrenSwitched:(id)sender {
if(_DoubanSwitch.isOn)
{
if(![UMSocialAccountManager isOauthAndTokenNotExpired:UMShareToRenren])
{
//进入授权页面
[UMSocialSnsPlatformManager getSocialPlatformWithName:UMShareToRenren].loginClickHandler(self,[UMSocialControllerService defaultControllerService],YES,^(UMSocialResponseEntity *response){
if (response.responseCode == UMSResponseCodeSuccess) {
//获取微博用户名、uid、token等
UMSocialAccountEntity *snsAccount = [[UMSocialAccountManager socialAccountDictionary] valueForKey:UMShareToRenren];
NSLog(@"username is %@, uid is %@, token is %@",snsAccount.userName,snsAccount.usid,snsAccount.accessToken);
//进入你的分享内容编辑页面
UMSocialAccountEntity *renrenAccount = [[UMSocialAccountEntity alloc] initWithPlatformName:UMShareToRenren];
renrenAccount.usid = snsAccount.usid;
renrenAccount.accessToken = snsAccount.accessToken;
// weiboAccount.openId = @"tencent weibo openId"; //腾讯微博账户必需设置openId
//同步用户信息
[UMSocialAccountManager postSnsAccount:renrenAccount completion:^(UMSocialResponseEntity *response){
if (response.responseCode == UMSResponseCodeSuccess) {
//在本地缓存设置得到的账户信息
[UMSocialAccountManager setSnsAccount:renrenAccount];
//进入你自定义的分享内容编辑页面或者使用我们的内容编辑页面
}}];
}
else{
[_RenrenSwitch setOn:NO animated:YES];
}
});
} }
} - (IBAction)WeiboSwitched:(id)sender {
if(_WeiboSwitch.isOn)
{
if(![UMSocialAccountManager isOauthAndTokenNotExpired:UMShareToSina])
{
[UMSocialSnsPlatformManager getSocialPlatformWithName:UMShareToSina].loginClickHandler(self,[UMSocialControllerService defaultControllerService],YES,^(UMSocialResponseEntity *response){
if(response.responseCode==UMSResponseCodeSuccess){
UMSocialAccountEntity *snsAccount=[[UMSocialAccountManager socialAccountDictionary] valueForKey:UMShareToSina];
UMSocialAccountEntity *sinaAccount=[[UMSocialAccountEntity alloc] initWithPlatformName:UMShareToSina];
//缓存到本地
sinaAccount.usid = snsAccount.usid;
sinaAccount.accessToken = snsAccount.accessToken;
// weiboAccount.openId = @"tencent weibo openId"; //腾讯微博账户必需设置openId
//同步用户信息
[UMSocialAccountManager postSnsAccount:sinaAccount completion:^(UMSocialResponseEntity *response){
if (response.responseCode == UMSResponseCodeSuccess) {
//在本地缓存设置得到的账户信息
[UMSocialAccountManager setSnsAccount:sinaAccount];
//进入你自定义的分享内容编辑页面或者使用我们的内容编辑页面
}}]; }
else
{
[_WeiboSwitch setOn:NO animated:YES];
}
});
}
}
} +(void)deleteSelectedImage:(NSInteger)index
{
if(currentImages!=nil)
[currentImages removeObjectAtIndex:index];
}
+(void)deleteSelectedImageWithImage:(UIImage *)image{
if(currentImages!=nil)
[currentImages removeObject:image]; }
@end

预览界面:

//
// YSYPreviewViewController.h
// NineShare
//
// Created by ZhangChangwei on 15/2/1.
// Copyright (c) 2015年 9Studio. All rights reserved.
// #import <UIKit/UIKit.h>
#import "PostTableViewController.h" @interface YSYPreviewViewController : UIViewController<UIActionSheetDelegate>
+(void) setPreviewImage:(UIImage *)image;
@end
//
// YSYPreviewViewController.m
// NineShare
//
// Created by ZhangChangwei on 15/2/1.
// Copyright (c) 2015年 9Studio. All rights reserved.
// #import "YSYPreviewViewController.h"
static UIImage *currentImage;
@interface YSYPreviewViewController ()
- (IBAction)deleteSelectedImage:(id)sender;
@property (weak, nonatomic) IBOutlet UIImageView *previewImageView; @end @implementation YSYPreviewViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_previewImageView.image=currentImage;
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} /*
#pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/ - (IBAction)deleteSelectedImage:(id)sender {
UIActionSheet *action=[[UIActionSheet alloc] initWithTitle:@"要删除这张照片吗?" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"删除" otherButtonTitles: nil];
[action showInView:self.view];
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
if(buttonIndex==actionSheet.cancelButtonIndex)
{
return;
}
else
{
[PostTableViewController deleteSelectedImageWithImage:currentImage];
[self.navigationController popToRootViewControllerAnimated:YES];
}
} +(void)setPreviewImage:(UIImage *)image{
currentImage=image;
}
@end

到这里就可以实现完整的带预览删除的图文分享功能了^_^

iOS开发-仿微信图片分享界面实现的更多相关文章

  1. iOS开发之微信平台分享

    在工程开始之前应该先准备在微信开放平台申请的appid,从微信平台下载sdk文件.下面开始步骤讲述 1.先将SDK导入工程目录 2.在info.plist文件设置相关信息,包括appid标识.白名单 ...

  2. Android开发之使用GridView+仿微信图片上传功能(附源代码)

    前言:如果转载文章请声明转载自:https://i.cnblogs.com/EditPosts.aspx?postid=7419021  .另外针对有些网站转载本人的文章结果源码链接不对的问题,本人在 ...

  3. iOS开发之微信聊天页面实现

    在上篇博客(iOS开发之微信聊天工具栏的封装)中对微信聊天页面下方的工具栏进行了封装,本篇博客中就使用之前封装的工具栏来进行聊天页面的编写.在聊天页面中主要用到了TableView的知识,还有如何在俩 ...

  4. iOS开发之微信聊天工具栏的封装

    之前山寨了一个新浪微博(iOS开发之山寨版新浪微博小结),这几天就山寨个微信吧.之前已经把微信的视图结构简单的拖了一下(IOS开发之微信山寨版),今天就开始给微信加上具体的实现功能,那么就先从微信的聊 ...

  5. Android仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等

    仿照微信,朋友圈分享图片功能 .可以进行图片的多张选择,拍照添加图片,以及进行图片的预览,预览时可以进行缩放,并且可以删除选中状态的图片 .很不错的源码,大家有需要可以下载看看 . 微信 微信 微信 ...

  6. iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码

    iOS精选源码 iOS高仿微信完整项目源码 Khala: Swift 编写的iOS/macOS 路由框架 微信左滑删除效果的实现与TableViewCell的常用样式介绍 实现阴影圆角并存,渐变色背景 ...

  7. [deviceone开发]-仿微信应用(一):框架搭建

    一.简介 这个示例是一步一步跟我学DeviceOne开发 - 仿微信应用系列文档对应的文档.详细介绍了ListView,IndexListView,add方法等常用功能,推荐初学者学习. 二.效果图 ...

  8. [转]Android 超高仿微信图片选择器 图片该这么加载

    快速加载本地图片缩略图的方法: 原文地址:Android 超高仿微信图片选择器 图片该这么加载 其示例代码下载: 仿微信图片选择器 ImageLoader

  9. Android 高级UI设计笔记06:仿微信图片选择器(转载)

    仿微信图片选择器: 一.项目整体分析: 1. Android加载图片的3个目标: (1)尽可能的去避免内存溢出. a. 根据图片的显示大小去压缩图片 b. 使用缓存对我们图片进行管理(LruCache ...

随机推荐

  1. 2018.11.08 NOIP模拟 水管(简单构造)

    传送门 仔细读题会发现只要所有点点权之和等于0一定有解. 如何构造? 直接当做树来构造就行了,非树边都赋值成0就行. 代码

  2. 负载均衡下 tomcat session 共享

    概述 在分布式部署的情况下,每台tomcat 都会有自己的session ,这样如果 用户A 在tomcat1 下登录,在tomcat2 下并没有session信息.如果 tomcat1宕机,tomc ...

  3. react父转子

    父组件使用子组件,子组件绑定父组件数据 ,子组件用props使用父组件数据 import React, { Component } from 'react'; import logo from './ ...

  4. boost--function

    1.简介 function是一个模板类,它就像一个包装了函数指针或函数对象的容器(只有一个元素).可以把它想象成一个泛化的函数指针,而且他非常适合代替函数指针,存储用于回调的函数.如下定义了一个能够容 ...

  5. IntelliJ IDEA 2017版 编译器使用学习笔记(九)(图文详尽版);IDE使用的有趣的插件;IDE代码统计器;Mybatis插件

    一.代码统计器,按照名字搜索即可,在file===setting------plugin 使用右键项目:点击自动统计 二.json转实体类 三.自动找寻bug插件 四.Remind me工具 五.检测 ...

  6. Java编程从头开始---老妪能解

    思想导向: 今天想要分享的是最基础的东西就是如何写一个简单的代码,很多人都是小白,需要的其实并不是很高端的理论,框架和思维模式啊,设计方法啊,这些对于一个新人来说实在是好高骛远,说的那么高端,结果要学 ...

  7. idea intellij对Spring进行单元测试

    1.加入Junit4及SpringJUnit4支持 <!-- junit --> <dependency> <groupId>junit</groupId&g ...

  8. 安卓修改开机logo

    这里我们是在ubuntu下进行操作我是用root用户登陆的,首先安装netpbm库 执行:apt-get install netpbm 对于Android系统最开始表现logo是在内核当中,所以首先我 ...

  9. L1范式和L2范式

    正则化(Regularization) 机器学习中几乎都可以看到损失函数后面会添加一个额外项,常用的额外项一般有两种,一般英文称作ℓ1ℓ1-norm和ℓ2ℓ2-norm,中文称作L1正则化和L2正则化 ...

  10. Linux(CentOS)下的apache服务器配置与管理

    原文链接:http://blog.csdn.net/ylqmf/article/details/5291680 一.WEB服务器与Apache1.web服务器与网址 2.Apache的历史 3.补充h ...