iOS开发——定制圆形头像与照相机图库的使用
如今的App都很流行圆形的头像,比方QQ右上角的头像,今日头条的头像等等。这已经成为App设计的趋势了。今天我们就来简单实现一下这个功能,我还会把从手机拍照中或者图库中取出作为头像的照片存储到应用程序沙盒中。
下次进入应用的时候还会显示该头像。
演示样例代码上传至:https://github.com/chenyufeng1991/AvatarPhoto
。
(1)该demo使用storyboard进行实现。首先拖入一个ImageView用来显示头像和一个button。
并拖拽到代码中进行绑定。图片绑定IBOutlet,button绑定IBAction。storyboard的设计效果例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">。
(2)如今要设置矩形的ImageView为圆形,同一时候能够设置该控件的边框颜色和宽度。
实现代码例如以下:
- (void)setCirclePhoto{
//avatarImage是图片控件;
[self.avatarImage.layer setCornerRadius:CGRectGetHeight([self.avatarImage bounds]) / 2];
self.avatarImage.layer.masksToBounds = true; //能够依据需求设置边框宽度、颜色
self.avatarImage.layer.borderWidth = 1;
self.avatarImage.layer.borderColor = [[UIColor blackColor] CGColor];
//设置图片;
self.avatarImage.layer.contents = (id)[[UIImage imageNamed:@"avatar.png"] CGImage]; }
(3)如今执行程序。能够发现ImageView已经设置为圆形了。
以下将会从手机中读取照片,这里的方法是假设你的设备(真机)支持拍照,那么默认会打开照相机,进行拍照;假设你的设备不支持拍照(模拟器),那么就会默认打开图库。实现方式例如以下:selectPhoto是button的点击事件。
- (IBAction)selectPhoto:(id)sender { if ([self.imagePickerPopover isPopoverVisible]) {
[self.imagePickerPopover dismissPopoverAnimated:YES];
self.imagePickerPopover = nil;
return;
} UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.editing = YES; //假设设备支持相机。就使用拍照技术
//否则让用户从照片库中选择照片
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
else{
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
} imagePicker.delegate = self; //同意编辑图片
imagePicker.allowsEditing = YES; //创建UIPopoverController对象前先检查当前设备是不是ipad
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
self.imagePickerPopover = [[UIPopoverController alloc] initWithContentViewController:imagePicker];
self.imagePickerPopover.delegate = self;
[self.imagePickerPopover presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
else
{
[self presentViewController:imagePicker animated:YES completion:nil];
}
} -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
//通过info字典获取选择的照片
UIImage *image = [info valueForKey:UIImagePickerControllerEditedImage]; //以itemKey为键,将照片存入ImageStore对象中
[[MyImageStore sharedStore] setImage:image forKey:@"CYFStore"]; //将照片放入UIImageView对象
self.avatarImage.image = image; //推断UIPopoverController对象是否存在
if (self.imagePickerPopover) {
[self.imagePickerPopover dismissPopoverAnimated:YES];
self.imagePickerPopover = nil;
}
else
{
//关闭以模态形式显示的UIImagePickerController
[self dismissViewControllerAnimated:YES completion:nil];
}
}
(4)执行以上程序,就已经能够从照相机或者图库中取出照片放到圆形ImageView中了。我解释一下上面的一行代码。
[[MyImageStore sharedStore] setImage:image forKey:@"CYFStore"];
这行代码是把该照片存储到应用沙盒中,也使用键值对的方式来存储。
下次程序启动后,直接会读取该图片。
等下我会来实现这个MyImageStore类。
同一时候。也要声明一个属性:
@property (strong, nonatomic) UIPopoverController *imagePickerPopover;
UIPopoverController对象用来打开照相机。
(5)以下将要来实现把图片存储到沙盒(文件存储)中(代码较多。可直接參考源码)
+(instancetype)sharedStore
{
static MyImageStore *instance = nil; //确保多线程中仅仅创建一次对象,线程安全的单例
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] initPrivate];
}); return instance;
} -(instancetype)initPrivate
{
self = [super init];
if (self) {
_dictionary = [[NSMutableDictionary alloc] init]; //注冊为低内存通知的观察者
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(clearCaches:)
name:UIApplicationDidReceiveMemoryWarningNotification
object:nil];
}
return self;
} -(void)setImage:(UIImage *)image forKey:(NSString *)key
{
[self.dictionary setObject:image forKey:key]; //获取保存图片的全路径
NSString *path = [self imagePathForKey:key]; //从图片提取JPEG格式的数据,第二个參数为图片压缩參数
NSData *data = UIImageJPEGRepresentation(image, 0.5);
//以PNG格式提取图片数据
//NSData *data = UIImagePNGRepresentation(image); //将图片数据写入文件
[data writeToFile:path atomically:YES];
} -(UIImage *)imageForKey:(NSString *)key
{
//return [self.dictionary objectForKey:key];
UIImage *image = [self.dictionary objectForKey:key];
if (!image) {
NSString *path = [self imagePathForKey:key]; image = [UIImage imageWithContentsOfFile:path];
if (image) {
[self.dictionary setObject:image forKey:key];
}
else
{
NSLog(@"Error: unable to find %@", [self imagePathForKey:key]);
}
}
return image;
} -(NSString *)imagePathForKey:(NSString *)key
{
NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [documentDirectories firstObject];
return [documentDirectory stringByAppendingPathComponent:key];
} -(void)clearCaches:(NSNotification *)n
{
NSLog(@"Flushing %ld images out of the cache", (unsigned long)[self.dictionary count]);
[self.dictionary removeAllObjects];
}
(6)执行程序,实现效果例如以下:
。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">。
总结,当选择完图片之后,就会存储到文件里,当下次程序又一次启动,就会从文件里自己主动读出该图片进行显示。在实际开发中。图片可能是从网络获取的。而且选择完图片后也会传到server,当然你也能够在本地做一个缓存。提高效率。
该模块能够进行扩展,也能够直接拿到项目中使用。
博客更新:
假设我不想让图片在取完之后进行截取编辑,能够设置:
imagePicker.allowsEditing = false;
同一时候把:
//通过info字典获取选择的照片
UIImage *image = [info valueForKey:UIImagePickerControllerEditedImage];
改动为:
//通过info字典获取选择的照片
UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
上面都没有涉及把一张图片存储到手机的图库中,下面方法能够把拍照后的Image保存到用户手机中:当中第三个參数能够写一个回调方法,也就是把照片存储到图库后的方法回调。
//把一张照片保存到图库中,此时不管是这张照片是照相机拍的还是本身从图库中取出的,都会保存到图库中;
UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);
假设我们要把一张图片进行保存或者使用网络传输。使用NSData较为合适,并进行压缩:
//压缩图片,假设图片要上传到server或者网络,则须要运行该步骤(压缩),第二个參数是压缩比例,转化为NSData类型。
NSData *fileData = UIImageJPEGRepresentation(image, 1.0);
应用优化与更新:
事实上在让用户选择图片的时候,应该也要用户选择是打开照相机还是图库。
以下的代码优化是弹出选择框(UIAlertController),主要就是设置sourceType属性。现把点击button的事件处理改动例如以下:代码更新已经提交至:https://github.com/chenyufeng1991/AvatarPhoto。
- (IBAction)selectPhoto:(id)sender { if ([self.imagePickerPopover isPopoverVisible]) {
[self.imagePickerPopover dismissPopoverAnimated:YES];
self.imagePickerPopover = nil;
return;
} UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.editing = YES;
imagePicker.delegate = self; /*
假设这里allowsEditing设置为false。则以下的UIImage *image = [info valueForKey:UIImagePickerControllerEditedImage];
应该改为: UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
也就是改为原图像。而不是编辑后的图像。 */ //同意编辑图片
imagePicker.allowsEditing = YES;
/*
这里以弹出选择框的形式让用户选择是打开照相机还是图库
*/ //初始化提示框。
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"请选择打开方式" message:nil preferredStyle: UIAlertControllerStyleActionSheet]; [alert addAction:[UIAlertAction actionWithTitle:@"照相机" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;//设置为照相机打开; //创建UIPopoverController对象前先检查当前设备是不是ipad
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
self.imagePickerPopover = [[UIPopoverController alloc] initWithContentViewController:imagePicker];
self.imagePickerPopover.delegate = self;
[self.imagePickerPopover presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
else{
[self presentViewController:imagePicker animated:YES completion:nil]; }
}]]; [alert addAction:[UIAlertAction actionWithTitle:@"相冊" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;//设置为图库打开。 //创建UIPopoverController对象前先检查当前设备是不是ipad
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
self.imagePickerPopover = [[UIPopoverController alloc] initWithContentViewController:imagePicker];
self.imagePickerPopover.delegate = self;
[self.imagePickerPopover presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
else{
[self presentViewController:imagePicker animated:YES completion:nil];
}
}]]; [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
//取消;
}]]; //弹出提示框;
[self presentViewController:alert animated:true completion:nil];
}
实现效果例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
github主页:https://github.com/chenyufeng1991
。
欢迎大家訪问!
iOS开发——定制圆形头像与照相机图库的使用的更多相关文章
- iOS开发-定制多样式二维码
iOS开发-定制多样式二维码 二维码/条形码是按照某种特定的几何图形按一定规律在平台(一维/二维方向上)分布的黑白相间的图形纪录符号信息.使用若干个与二进制对应的几何形体来表示文字数值信息. 最常 ...
- Android自定义控件实例,圆形头像(图库 + 裁剪+设置),上传头像显示为圆形,附源码
Android项目开发中经常会遇见需要实现圆角或者圆形的图片功能,如果仅仅使用系统自带的ImageView控件显然无法实现此功能,所以通过系列文章的形式由简到繁全方位的介绍一下此功能的实现,巩固一下自 ...
- iOS实现头像选取(照相或者图片库)、大小等比缩放、生成圆形头像
//弹出actionsheet.选择获取头像的方式 //从相册获取图片 -(void)takePictureClick:(UIButton *)sender { // /*注:使用,需要实现以下协议: ...
- Android开发之制作圆形头像自定义View,直接引用工具类,加快开发速度。带有源代码学习
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 QQ986945193 博客园主页:http://www.cnblogs.com/mcxiaobing ...
- 【iOS开发-80】Quartz2D绘图简介:直线/圆形/椭圆/方形以及上下文栈管理CGContextSaveGState/CGContextRestoreGState
本文转载至 http://blog.csdn.net/weisubao/article/details/41282457 - (void)drawRect:(CGRect)rect { //获得当前上 ...
- 【iOS开发-80】Quartz2D画图简单介绍:直线/圆形/椭圆/方形以及上下文栈管理CGContextSaveGState/CGContextRestoreGState
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2Vpc3ViYW8=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA ...
- iOS 画圆形头像
demo下载地址:http://pan.baidu.com/s/1mgBf6YG _logoImageView.image = [self getEllipseImageWithImage:[UIIm ...
- iOS:iOS开发非常全的三方库、插件等等
iOS开发非常全的三方库.插件等等 github排名:https://github.com/trending, github搜索:https://github.com/search. 此文章转自git ...
- iOS开发之资料收集
github排名:https://github.com/trending, github搜索:https://github.com/search. 此文章转自github:https://github ...
随机推荐
- go函数初级
一.简介 在go语言中,函数的功能是非常强大的,以至于被认为拥有函数式编程语言的多种特性. 二.介绍 1.一个程序中包含了很多的函数:函数式基本的代码块 2.函数编写的顺序是无关紧要的:鉴于可读性的需 ...
- SqlMap常用参数(一)
sqlmap可谓是利用sql注入的神器了,sqlmap的参数很多,接下介绍几种常见的参数. 一.注入access数据库常用的参数 sqlmap.py -u "url" //判断参 ...
- Elasticsearch之更新(全部更新和局部更新)
前面的基础, Elasticsearch之curl创建索引库 Elasticsearch之curl创建索引 Elasticsearch之curl创建索引库和索引时注意事项 Elasticsearch之 ...
- Android使用charles抓包
1.下载并安状软件,官网在此: 2.前题条件,电脑和手机必须在同一网段 3.在Charles界面选择菜单 proxy->proxy settings 勾选"Enable transpa ...
- Leetcode0092 & 0206--Reverse Linked List 链表逆转
[转载请注明]http://www.cnblogs.com/igoslly/p/8670038.html 链表逆序在链表题目中还是较为常见的,这里将Leetcode中的两道题放在一起,分别是 0092 ...
- Ubuntu中在终端进入root权限但是总提示密码错误的解决方案
先解除root锁定,为root用户重新设置密码 打开终端输入:sudo passwd(注意是passwd不是password) Password: <--- 输入你当前用户的密码 Enter n ...
- VMWare虚拟机Centos 6.9中的 linux 配置静态ip地址上外网
1.查看网络 # ifconfig 发现网络还没有配置,ping不通 2.修改网卡配置文件 # vim /etc/sysconfig/network-scripts/ifcfg-eth0 添加如下配置 ...
- 安卓桌布显示的dip和px
安卓程序设计界面显示设置图像大小,在layout.xml里面有dip和px选项,dip为 什么 暂时还不知道,或许是设计桌布的设定像素比率,px为像素值: 比如我的手机是 Lenovo K920,屏幕 ...
- SLAM: 图像角点检测的Fast算法(OpenCV文档)
官方链接:http://docs.opencv.org/trunk/doc/py_tutorials/py_feature2d/py_fast/py_fast.html#fast-algorithm- ...
- 实验8 标准模板库STL
一.实验目的与要求: 了解标准模板库STL中的容器.迭代器.函数对象和算法等基本概念. 掌握STL,并能应用STL解决实际问题. 二.实验过程: 完成实验8标准模板库STL中练习题,见:http:// ...