IOS实战 (1) 之 仿 LOFTER 底部 水平滑动(也有 Android 版本哦)

写在前面的话

博主 一个懒技术, 毕业两年,做过大半年 Android,然后转 IOS, 虽然也做了不少小项目.但是一直 没有太多文档 博客的积累.现在希望 每隔一段时间就把项目用到的一些实用代码片段,与小的例子 与大家分享交流.就这…. over!!

  • 先看看需要实现的效果图
  • 再看看我们高仿的效果图
  • 实现思路(引用了 github iCarousel 库 )
  • 部分代码说明
  • 代码下载链接

Lofter 效果图

效果 类似图片轮播. 当滑动时 两边视图有缩放的动画效果.
这里写图片描述

实现后的效果图

这里写图片描述

实现思路

一.整理功能特点,选择合适的方法去实现
(1)功能1: 每次滑动都会有一个 View 居中显示
(2)功能2:滑动有两边缩放的动画效果
(3)不同的 View 有各自的 点击事件.
经过分析 有两种实现方法.
第一种:是 UICollectionView 和 自定义 Layout
第二种就是 github 中大神 制作的高级零件.iCarousel.项目中为了 稳定性和效果性 使用的第三方的库.
但是自主思考 过程不能缺少.
先来分析一下 UICollectionView 的实现
关键在 自定义的UICollectionViewFlowLayout.API 的一些详解 参考
http://blog.csdn.net/qpwyj/article/details/51338337

动画缩放关键代码

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {

    CGFloat contentOffsetX = self.collectionView.contentOffset.x;
    CGFloat collectionViewCenterX = self.collectionView.frame.size.width * 0.5;

    //1.取出默认的cell的UICollectionViewLayoutAttributes
    NSArray *attrs = [super layoutAttributesForElementsInRect:rect];

    //2.遍历所有的布局属性

    for (UICollectionViewLayoutAttributes *attr in attrs) {
        CGFloat scale = 1 - fabs(attr.center.x - contentOffsetX - collectionViewCenterX) / self.collectionView.bounds.size.width;
        //计算缩放比例.太小比例 不修改
        if (scale< 0.7) {
             attr.transform = CGAffineTransformMakeScale(0.7, 0.7);
        }

    }
    return attrs;
}

滑动停止后 View 居中显示

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {

    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 *attr in array) {
        if(ABS(attr.center.x - centerX) < ABS(adjustOffsetX)){
            adjustOffsetX = attr.center.x - centerX;
        }
    }
    return CGPointMake(proposedContentOffset.x+adjustOffsetX, proposedContentOffset.y);
}

此例子效果图
这里写图片描述

在实战项目中 本博主秉承 能搬砖就搬砖的思路. 开启了 github 的搬砖之旅
用 pod 或者下载代码 将第三方库(iCarousel)引入
不会使用 pods 工具的参考 http://blog.csdn.net/lilinoscar/article/details/46930387

准备工作: 创建新项目. 并有iCarousel库. 在 ViewController 中 导入iCarousel. h 头文件.
在 Xib 中创建 一个 View 把 Class 改为iCarousel. ( 可以代码中 创建). 实现. iCarouselDataSource, iCarouselDelegate.的部分方法

- (NSInteger)numberOfItemsInCarousel:(__unused iCarousel *)carousel
{



    return _dataList.count;
}

- (UIView *)carousel:(__unused iCarousel *)carousel viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view
{
    MyCardView *cardView = nil;

    if (view == nil)
    {
        cardView= [[MyCardView alloc] initWithFrame:CGRectMake(0, 0, ScreenWidth*0.7, ScreenHeight*0.40)];
        cardView.delegate=self;
        view=cardView;
        view.contentMode = UIViewContentModeCenter;

    }
    NSDictionary *dic=_dataList[index];

    [cardView setData:dic];

    return cardView;
}

- (CGFloat)carousel:(iCarousel *)carousel valueForOption:(iCarouselOption)option withDefault:(CGFloat)value
{

    //customize carousel display
    switch (option)
    {
        case iCarouselOptionWrap:
        {
            //normally you would hard-code this to YES or NO
            return YES;
        }
        case iCarouselOptionSpacing:
        {
            //add a bit of spacing between the item views
            return value * 1.1f;
        }
        case iCarouselOptionFadeMax:
        case iCarouselOptionShowBackfaces:
        case iCarouselOptionRadius:
        case iCarouselOptionAngle:
        case iCarouselOptionArc:
        case iCarouselOptionTilt:
        case iCarouselOptionCount:
        case iCarouselOptionFadeMin:
        case iCarouselOptionFadeMinAlpha:
        case iCarouselOptionFadeRange:
        case iCarouselOptionOffsetMultiplier:
        case iCarouselOptionVisibleItems:
        {
            return value;
        }
    }
}

- (CATransform3D)carousel:(iCarousel *)carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform
{
    static CGFloat max_sacle = 1.0f;
    static CGFloat min_scale = 0.8f;
    if (offset <= 1 && offset >= -1){
        float tempScale = offset < 0 ? 1 + offset : 1 - offset;
        float slope = (max_sacle-min_scale) / 1;
        CGFloat scale = min_scale+slope*tempScale;
        transform = CATransform3DScale(transform, scale, scale, 1);
    }else{
        transform = CATransform3DScale(transform, min_scale, min_scale, 1);
    }
    return CATransform3DTranslate(transform, offset * self.myICarousel.itemWidth * 1.2, 0.0, 0.0);

}


-(void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index{



}

-(void)itemClickIndex:(NSInteger)index{


    NSLog(@"被点击的 是 第%ld 卡片中的 第 %ld",(long)_iCarouselindex+1,(long)index+1);


}

其中 (UIView )carousel:(__unused iCarousel )carousel viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view 方法 返回的每个 卡片的 View 可以自定义. Demo 中 随意编写的,读者可以重新编写,提高代码的重用性.

IOS 最终效果图

这里写图片描述

Android 版本 使用的deprecation的类 Gallery.虽然不建议使用了.很老的 API 但是做这个效果是我能想到最简单的一个.如果有 新的实现方法可以跟我讲一下.(没有找到合适的 类库)
核心代码 就是 View 缩放一下.

if (selectNum == position) {
holder.mainLinlayout.setLayoutParams(new Gallery.LayoutParams(gallery.getLayoutParams().height - 100, gallery.getLayoutParams().height));// 如果被选择则放大显示
} else {
holder.mainLinlayout.setLayoutParams(new Gallery.LayoutParams((gallery.getLayoutParams().height - 100) / 10 * 9,
gallery.getLayoutParams().height / 10 * 9));// 否则正常

}

Android 效果图

Android 效果图

关键!!!代码下载

Android
代码下载链接
iOS iCarousel库实现
代码下载链接

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值