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(水平方向) ...
随机推荐
- postgresql遇到的性能问题
问题SQL scwksmlcls.wk_cls_c , scwklrgcls.wk_lrg_cls_nm , scwkmdlcls.wk_mdl_cls_nm , scwksmlcls.wk_sml_ ...
- react Native环境 搭建
react Native的优点:跨平台 低投入高回报 性能高 支持动态更新.一才两用(ios和Android) 开发成本第 代码复用率高.windows环境搭建react Native开发环境1.安装 ...
- HDU_1227_Fast Food_动态规划
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1227 Fast Food Time Limit: 2000/1000 MS (Java/Others) ...
- java内存组成
java内存组成介绍:堆(Heap)和非堆(Non-heap)内存 按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动 ...
- 个人作业Alpha项目测试
这个作业属于哪个课程 软件工程原理 这个作业要求在哪里 作业要求 团队名称 TEAMPANTHER 这个作业的目标 每个同学必须选取非自己所在团队的3个项目进行测试. 在你所测试的项目的Alpha发布 ...
- 牛客多校Round 5
Solved:3 rank:195 F. take 官方题解:小 A 在打开第 i 个箱子后会交换手中的钻石和第 i 个箱子中的钻石 当且仅当第 i个箱子的钻石是前 i 个箱子打开后出现的所有钻石里最 ...
- Python字符的转义
参考原文 廖雪峰Python教程 字符的转义 字符串是以单引号' 或双引号" 括起来的任意文本,比如'abc',"xyz".''或""本身只是一种表示 ...
- Semi-colon expected (eclipse 引入 json文件报错)
最近做的项目用到的前端框架有一个json文件夹,里面全是json文件,所以导入Eclipse的时候会在整个项目上都是红叉,但是其实不影响项目运行的,之前忙着码代码也没时间管他,这个红叉存留了一个月!今 ...
- MySQL练习题及答案(复习)
新建一个叫做 review 的数据库,将测试数据脚本导进去.(可以使用Navicat查询功能) /* Navicat MySQL Data Transfer Source Server : DB So ...
- AC自动机模板浅讲
Description 给你N个单词,然后给定一个字符串,问一共有多少单词在这个字符串中出现过(输入相同的字符串算不同的单词,同一个单词重复出现只计一次). Input 第一行一个整数N,表示给定单词 ...