iOS 抖音个人主页布局开发(简单)

思路:用UICollectionView为父容器,用于显示个人详细信息、多行多列Tab切换。

①抖音个人主页包含用户信息和用户发布、喜欢的视频列表,以CollectionView为父容器即可全部实现。UICollectionView包含两个Section,第一个Section包含一个Header和一个Footer,Header 用于显示用户头像、昵称等详细信息,Footer则用于切换“作品”与“喜欢”两个tab,第二个section则用于显示短视频动图列表。

UICollectionView指定元素固定原理

通过重写UICollectionViewFlowLayout中的layoutAttributesForElementsInRect方法可以让UICollectionView显示诸如瀑布流、水平流动布局等各种样式的布局。其原理就是layoutAttributesForElementsInRect方法本身返回的是UICollectionView中每个元素的属性,属性中就包含元素的frame信息,通过修改frame值即可改变每个元素显示的位置,这里的元素类型分为Header、Footer、Cell,判断元素类型可将不同元素进行区分

抖音个人主页在向上滑动时,第一个section滑动到导航栏底部时便固定位置不再上移。实现这个效果就需要将第一个section中的元素提取出来单独处理frame值。之前也介绍了,第一个section包含一个Header和一个Footer,Header用于显示用户详细信息,Footer则用于显示切换"作品"和"喜欢"的Tab栏,因此只需判断是否是第一个section的Header和Footer并修改frame值即可实现固定效果,具体代码如下:

#import <UIKit/UIKit.h>

@interface HoverViewFlowLayout : UICollectionViewFlowLayout

@property (nonatomic, assign) CGFloat      topHeight;

- (instancetype)initWithTopHeight:(CGFloat)height;

@end
#import "HoverViewFlowLayout.h"

@implementation HoverViewFlowLayout

- (instancetype)initWithTopHeight:(CGFloat)height{
    self = [super init];
    if (self){
        self.topHeight = height;
    }
    return self;
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{
    NSMutableArray<UICollectionViewLayoutAttributes *> *superArray = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
    for (UICollectionViewLayoutAttributes *attributes in [superArray mutableCopy]) {
        if ([attributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) {
            [superArray removeObject:attributes];
        }
    }
    
    [superArray addObject:[super layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]];
  
    for (UICollectionViewLayoutAttributes *attributes in superArray) {
        
        if(attributes.indexPath.section == 0) {
            
            if ([attributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]){
                CGRect rect = attributes.frame;
                if(self.collectionView.contentOffset.y + self.topHeight - rect.size.height > rect.origin.y) {
                    rect.origin.y =  self.collectionView.contentOffset.y + self.topHeight - rect.size.height;
                    attributes.frame = rect;
                }
                attributes.zIndex = 5;
            }
        }
        
    }
    return [superArray copy];
}

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBound {
    return YES;
}

@end

③UICollectionView指定元素下拉缩放原理

UIScrollView的bounce属性设置为YES后,UIScrollView及其子类都会有在滑动到顶部和底部时出现弹簧拉伸效果,UICollectionView、UITableView都继承自UIScrollView,所以也有bounce属性。实现抖音个人主页的拉伸效果的代码片段如下:

//UIScrollViewDelegate Delegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat offsetY = scrollView.contentOffset.y;
    if (offsetY < 0) {
        [_userInfoHeader overScrollAction:offsetY];
    }else {
        [_userInfoHeader scrollToTopAction:offsetY];
        [self updateNavigationTitle:offsetY];
    }
}
- (void)updateNavigationTitle:(CGFloat)offsetY {
    if (kUserInfoHeaderHeight - HK_NAVBAR_HEIGHT*2 > offsetY) {
        [self setNavBarTextColor:ColorClear];
    }
    if (kUserInfoHeaderHeight - HK_NAVBAR_HEIGHT*2 < offsetY && offsetY < kUserInfoHeaderHeight - HK_NAVBAR_HEIGHT) {
        CGFloat alphaRatio =  1.0f - (kUserInfoHeaderHeight - HK_NAVBAR_HEIGHT - offsetY)/[self navagationBarHeight];
        [self setNavBarTextColor:[UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:alphaRatio]];
    }
    if (offsetY > kUserInfoHeaderHeight - [self navagationBarHeight]) {
        [self setNavBarTextColor:ColorWhite];
    }
}

///////////////////////////////////////////////
#pragma update position when over scroll

- (void)overScrollAction:(CGFloat) offsetY {
    CGFloat scaleRatio = fabs(offsetY)/370.0f;
    CGFloat overScaleHeight = (370.0f * scaleRatio)/2;
    _topBackground.transform = CGAffineTransformConcat(CGAffineTransformMakeScale(scaleRatio + 1.0f, scaleRatio + 1.0f), CGAffineTransformMakeTranslation(0, -overScaleHeight));
}

- (void)scrollToTopAction:(CGFloat) offsetY {
    CGFloat alphaRatio = offsetY/(370.0f - 44 - StatusBarHeight);
    _containerView.alpha = 1.0f - alphaRatio;
}

效果图:

             

代码地址:

https://gitee.com/Steven_Hu/DouyinUserHomePage

参考:

https://sshiqiao.github.io/document/douyin-objectc.html#2.2

 

 

 

 

 

 

 

 

 

 

 

posted @ 2018-12-11 19:50  淡然微笑_Steven  阅读(3895)  评论(0编辑  收藏  举报