ios 仿android gallery控件
ios 上没有发现与android gallery类似的控件,因为在项目上须要使用到.採用UICollectionView实现
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhhbmdwaW5nODcx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
ViewController.m
#import "ViewController.h"
#import "ImageCell.h"
#import "LineLayout.h" @interface ViewController () <UICollectionViewDataSource, UICollectionViewDelegate>
@property (nonatomic, strong) NSMutableArray *images;
@property (nonatomic, weak) UICollectionView *collectionView;
@end @implementation ViewController static NSString *const ID = @"image"; - (NSMutableArray *)images
{
if (!_images) {
self.images = [[NSMutableArray alloc] init]; for (int i = 1; i<=20; i++) {
[self.images addObject:[NSString stringWithFormat:@"%d", i]];
}
}
return _images;
} - (void)viewDidLoad {
[super viewDidLoad]; CGFloat w = self.view.frame.size.width;
CGRect rect = CGRectMake(0, 100, w, 200);
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:rect collectionViewLayout:[[LineLayout alloc] init]];
collectionView.dataSource = self;
collectionView.delegate = self;
[collectionView registerNib:[UINib nibWithNibName:@"ImageCell" bundle:nil] forCellWithReuseIdentifier:ID];
[self.view addSubview:collectionView];
self.collectionView = collectionView;
// collectionViewLayout :
// UICollectionViewLayout
// UICollectionViewFlowLayout
} - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([self.collectionView.collectionViewLayout isKindOfClass:[LineLayout class]]) {
[self.collectionView setCollectionViewLayout:[[UICollectionViewFlowLayout alloc] init] animated:YES];
} else {
[self.collectionView setCollectionViewLayout:[[LineLayout alloc] init] animated:YES];
}
} #pragma mark - <UICollectionViewDataSource>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.images.count;
} - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
ImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath];
cell.image = self.images[indexPath.item];
return cell;
} - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
// 删除模型数据
[self.images removeObjectAtIndex:indexPath.item]; // 删UI(刷新UI)
[collectionView deleteItemsAtIndexPaths:@[indexPath]];
} @end
LineLayout.m
#import "LineLayout.h" static const CGFloat ItemWH = 100; @implementation LineLayout - (instancetype)init
{
if (self = [super init]) {
}
return self;
} /**
* 仅仅要显示的边界发生改变就又一次布局:
内部会又一次调用prepareLayout和layoutAttributesForElementsInRect方法获得全部cell的布局属性
*/
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
} /**
* 用来设置collectionView停止滚动那一刻的位置
*
* @param proposedContentOffset 原本collectionView停止滚动那一刻的位置
* @param velocity 滚动速度
*/
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
// 1.计算出scrollView最后会停留的范围
CGRect lastRect;
lastRect.origin = proposedContentOffset;
lastRect.size = self.collectionView.frame.size; // 计算屏幕最中间的x
CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5; // 2.取出这个范围内的全部属性
NSArray *array = [self layoutAttributesForElementsInRect:lastRect]; // 3.遍历全部属性
CGFloat adjustOffsetX = MAXFLOAT;
for (UICollectionViewLayoutAttributes *attrs in array) {
if (ABS(attrs.center.x - centerX) < ABS(adjustOffsetX)) {
adjustOffsetX = attrs.center.x - centerX;
}
} return CGPointMake(proposedContentOffset.x + adjustOffsetX, proposedContentOffset.y);
} /**
* 一些初始化工作最好在这里实现
*/
- (void)prepareLayout
{
[super prepareLayout]; // 每个cell的尺寸
self.itemSize = CGSizeMake(ItemWH, ItemWH);
CGFloat inset = (self.collectionView.frame.size.width - HMItemWH) * 0.5;
self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);
// 设置水平滚动
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.minimumLineSpacing = ItemWH * 0.7; // 每个cell(item)都有自己的UICollectionViewLayoutAttributes
// 每个indexPath都有自己的UICollectionViewLayoutAttributes
} /** 有效距离:当item的中间x距离屏幕的中间x在HMActiveDistance以内,才会開始放大, 其他情况都是缩小 */
static CGFloat const ActiveDistance = 150;
/** 缩放因素: 值越大, item就会越大 */
static CGFloat const ScaleFactor = 0.6; - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
// 0.计算可见的矩形框
CGRect visiableRect;
visiableRect.size = self.collectionView.frame.size;
visiableRect.origin = self.collectionView.contentOffset; // 1.取得默认的cell的UICollectionViewLayoutAttributes
NSArray *array = [super layoutAttributesForElementsInRect:rect];
// 计算屏幕最中间的x
CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width * 0.5; // 2.遍历全部的布局属性
for (UICollectionViewLayoutAttributes *attrs in array) {
// 假设不在屏幕上,直接跳过
if (!CGRectIntersectsRect(visiableRect, attrs.frame)) continue; // 每个item的中点x
CGFloat itemCenterX = attrs.center.x; // 差距越小, 缩放比例越大
// 依据跟屏幕最中间的距离计算缩放比例
CGFloat scale = 1 + ScaleFactor * (1 - (ABS(itemCenterX - centerX) / ActiveDistance));
attrs.transform = CGAffineTransformMakeScale(scale, scale);
} return array;
} @end
ImageCell.m
#import "ImageCell.h" @interface ImageCell()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end @implementation ImageCell - (void)awakeFromNib {
self.imageView.layer.borderWidth = 3;
self.imageView.layer.borderColor = [UIColor whiteColor].CGColor;
self.imageView.layer.cornerRadius = 3;
self.imageView.clipsToBounds = YES;
} - (void)setImage:(NSString *)image
{
_image = [image copy]; self.imageView.image = [UIImage imageNamed:image];
} @end
ios 仿android gallery控件的更多相关文章
- Android仿iPhone 滚轮控件 实现
Android_开发 实用滚轮效果选择数字http://blog.csdn.net/zhangtengyuan23/article/details/8653771 Android仿iPhone滚轮控件 ...
- Android 开源控件与常用开发框架开发工具类
Android的加载动画AVLoadingIndicatorView 项目地址: https://github.com/81813780/AVLoadingIndicatorView 首先,在 bui ...
- 矩阵, 矩阵 , Android基础控件之ImageView
天下文章大家抄,以下所有内容,有来自copy,有来自查询,亦有自己的总结(目的是总结出自己的东西),所以说原创,不合适,说是转载也不恰当,所以我称之为笔记,可惜没有此分类选项,姑且不要脸一点,选择为原 ...
- android 基本控件使用
http://tech.it168.com/a2012/0321/1327/000001327704.shtml Android_ListView_用代码控制ListView的位置 有三种方法 mli ...
- IOS版App的控件元素定位
前言 Android版App的控件元素可以通过Android studio自带的工具uiautomatorviewer来协助定位! IOS版App的控件元素可以通过Appium来实现(未实现),或ap ...
- android 基础控件(EditView、SeekBar等)的属性及使用方法
android提供了大量的UI控件,本文将介绍TextView.ImageView.Button.EditView.ProgressBar.SeekBar.ScrollView.WebView ...
- Android基本控件之Menus
在我们的手机中有很多样式的菜单,比如:我们的短信界面,每条短信,我们长按都会出现一个菜单,还有很多的种类.那么现在,我们就来详细的讨论一下安卓中的菜单 Android的控件中就有这么一个,叫做Menu ...
- Android:控件布局(相对布局)RelativeLayout
RelativeLayout是相对布局控件:以控件之间相对位置或相对父容器位置进行排列. 相对布局常用属性: 子类控件相对子类控件:值是另外一个控件的id android:layout_above-- ...
- Android:控件布局(线性布局)LinearLayout
LinearLayout是线性布局控件:要么横向排布,要么竖向排布 决定性属性:必须有的! android:orientation:vertical (垂直方向) .horizontal(水平方向) ...
随机推荐
- dubbo之日志适配及访问日志
日志适配 自 2.2.1 开始,dubbo 开始内置 log4j.slf4j.jcl.jdk 这些日志框架的适配 1,也可以通过以下方式显示配置日志输出策略: 命令行 java -Ddubbo.app ...
- HDU_2112_最短路
题目链接:http://acm.hdu.edu.cn/status.php?user=l1526789512&pid=2112&status=5 HDU Today Time Limi ...
- Linux文件排序和FASTA文件操作
文件排序 seq: 产生一系列的数字; man seq查看其具体使用.我们这使用seq产生下游分析所用到的输入文件. # 产生从1到10的数,步长为1 $ seq 1 10 1 2 3 4 5 6 7 ...
- netstat查看服务器连接数端口并发数
简介 Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Member ...
- nz-card头部右侧添加东西
<nz-card [nzBordered]="true" nzTitle="卡片标题" [nzExtra]="extraTemplate1&qu ...
- Linux(Centos7)下搭建SVN服务器(新手上路)
以前都是别人直接给地址在svn上,下载或者上传东西,如今要自己建一个版本库用来存放东西.1.安装svnyum install -y subversion 2.查看svn安装位置还有哪些文件rpm -q ...
- 3D赛瓦号——整装待发!
随着岁末将至,twaver开发团队依旧马不停蹄,3d产品功能持续更新,新特效和功能目不暇接.现在,我们就利用一些新功能,制作一个全新“赛瓦号”飞船,大家看一下仿真程度是否有质的不同? 网页3d技术正在 ...
- 右键快捷打开Git Bash here失败
右键快捷打开Git Bash here失败,提示: Error: Could not fork child process: Resource temporarily unavailable (-1) ...
- jQuey中的return false作用是什么?
jQuey中的return false作用是什么?在众多的语句中都有return false的使用,当然对于熟悉它的开发者来说,当然是知根知底,知道此语句的作用,当然也就知道在什么时候使用此语句,不过 ...
- HTML5网页如何调用浏览器APP的微信分享功能?
if (/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Al ...