iOS开发-仿微信图片分享界面实现

分享功能目前几乎已成为很多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:[email protected]"YES":@"NO"];
    [_snsArray addObject:[email protected]"YES":@"NO"];
    [_snsArray addObject:[email protected]"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

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

时间: 2024-11-03 21:39:57

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

iOS高仿微信完整源码,网易爱玩APP源码等

iOS精选源码 iOS一种弹出视图效果带动画 一个快速便捷.无侵入.可扩展的动画弹框库 高仿Elk - 旅行货币转换器 iOS内分享的界面.功能一体化解决方案 使用Olami sdk实现一个语音查询股票的iOS程序 iOS高仿微信完整项目源码 分段绘制折线指示图, 点击效果 最新环信推送封装 v3.0[附代码] 仿照网易爱玩APP APP启动视频 iOS优质博客 iOS 一行代码搞定 KVO 前言发现好久没有研究.学习iOS优秀开源代码,现在大部分时间都在写业务代码, 学习其他语言及一些杂七杂八

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

在上篇博客(iOS开发之微信聊天工具栏的封装)中对微信聊天页面下方的工具栏进行了封装,本篇博客中就使用之前封装的工具栏来进行聊天页面的编写.在聊天页面中主要用到了TableView的知识,还有如何在俩天中显示我们发送的表情,具体请参考之前的博客:IOS开发之显示微博表情,在这儿就不做赘述啦.在聊天页面用到了三对,六种Cell,不过cell的复杂度要比之前的新浪微博(IOS开发之新浪围脖)简单的多.废话少说吧,还是先来几张效果图,在给出实现代码吧. 聊天界面的效果图如下:在下面的聊天界面中中用到了

iOS开发之微信聊天工具栏的封装(走过路过不要错过哦)

之前山寨了一个新浪微博(iOS开发之山寨版新浪微博小结),这几天就山寨个微信吧.之前已经把微信的视图结构简单的拖了一下(IOS开发之微信山寨版),今天就开始给微信加上具体的实现功能,那么就先从微信的聊天界面开始吧.提到封装是少不了写代码的,在封装组件的时候,为了组件的可移植性,我们就不能用storyboard来拖拽了.为了屏幕的适配,适应不同屏幕的手机,所以在封装组件的时候是少不了为我们的组件来添加约束.今天博客中的所有代码都是脱离storyboard的,这些代码在别的工程中也是可以使用的.好,

iOS开发UI篇—以微博界面为例使用纯代码自定义cell程序编码全过程(一)

iOS开发UI篇-以微博界面为例使用纯代码自定义cell程序编码全过程(一) 一.storyboard的处理 直接让控制器继承uitableview controller,然后在storyboard中把继承自uiviewcontroller的控制器干掉,重新拖一个tableview controller,和主控制器进行连线. 项目结构和plist文件 二.程序逻辑业务的处理 第一步,把配图和plist中拿到项目中,加载plist数据(非png的图片放到spooding files中) 第二步,字

iOS开发——仿淘宝添加到购物车的动画效果实现

这篇博文实在不知道该起什么名字才能概况我的意思...挫语文水平 类似于淘宝一样,我们在写一些购物.订餐之类的app的时候,在用户选择购买或者加入购物车时可以添加一个商品飞到购物车中的动画效果,如下图所示: 实现这个效果还是不算难的,但涉及的问题比较多,还是挺有学习价值的.主要面对的问题有以下几点 1.cell中有button,如何获得该button,即如何知道用户点击的是哪一个button. 2.坐标系的转换,这里频繁使用坐标系转换,主要原因是这里需要涉及三个视图--cell.tableView

iOS开发之友盟分享的使用

iOS开发之友盟分享的使用 1. 准备工作 (1) 注册友盟账号, 获取Appkey (2) 根据需要下载分享库(注意: 最好64位) 2. 基本分享 (1) 库文件拖进工程中 umeng_ios_social_sdk_4.2 (2) 添加必要二进制库 若你的工程设置了all_load,需要添加手机QQ SDK需要的系统framework: Security.framework, libiconv.dylib, SystemConfiguration.framework, CoreGraphic

Android高仿微信图片选择上传工具

源码托管地址:https://github.com/SleepyzzZ/photo-selector 话不多说,先上效果图(高仿微信图片选择器): 图片选择界面: 图片预览界面: 批量上传图片: 实现的功能介绍: 1.图片异步加载,使用Glide开源库实现加载; 2.图片的预览界面,支持左右滑动,双击放大浏览; 3.图片批量上传,使用OkHttp来实现与Servlet服务器的通信; 使用方法(Android Studio): 新建工程,File->New->Import Module导入pho

Android 高级UI设计笔记06:仿微信图片选择器

仿微信图片选择器: 一.项目整体分析: 1. Android加载图片的3个目标: (1)尽可能的去避免内存溢出. a. 根据图片的显示大小去压缩图片 b. 使用缓存对我们图片进行管理(LruCache) (2)用户操作UI控件必须充分的流畅. a. getView里面尽可能不去做耗时的操作(异步加载 + 回调显示) (3)用户预期显示的图片尽可能的快(图片的加载策略的选择,一般选择是LIFO). a. LIFO 2. 定义一个Imageloader完成上面1中的3个目标: Imageloader

android之使用GridView+仿微信图片上传功能(附源代码)

由于工作要求最近在使用GridView完成图片的批量上传功能,我的例子当中包含仿微信图片上传.拍照.本地选择.相片裁剪等功能,如果有需要的朋友可以看一下,希望我的实际经验能对您有所帮助. 直接上图,下面的图片就是点击"加号"后弹出的对话框,通过对话框可以根据自己需求进行相片选择. 项目结构: 下面直接上代码. 整体的布局文件activity_main.xml 1 <LinearLayout xmlns:android="http://schemas.android.co