| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 |
- //
- // PGPickerColumnView.m
- // PGPickerView
- //
- // Created by piggybear on 2017/7/26.
- // Copyright © 2017年 piggybear. All rights reserved.
- //
- #import "PGPickerColumnView.h"
- #import "PGPickerColumnCell.h"
- #import "PGPickerTableView.h"
- @interface PGPickerColumnView()<UITableViewDelegate, UITableViewDataSource>
- @property (nonatomic) CGFloat rowHeight;
- @property (nonatomic, weak) UIView *upView;
- @property (nonatomic, weak) UIView *centerView;
- @property (nonatomic, weak) UIView *downView;
- @property (nonatomic, weak) PGPickerTableView *upTableView;
- @property (nonatomic, weak) PGPickerTableView *centerTableView;
- @property (nonatomic, weak) PGPickerTableView *downTableView;
- @property (nonatomic, assign) CGFloat offset;
- @property (nonatomic, assign) NSInteger offsetCount;
- @property (nonatomic) CGFloat upLinePosY;
- @property (nonatomic, assign) CGFloat upLineHeight;
- @property (nonatomic, assign) CGFloat downLineHeight;
- @property (nonatomic, assign) CGFloat showCount;
- @property (nonatomic, assign) BOOL isSubViewLayouted;
- @property (nonatomic, assign) CGFloat circumference;
- @property (nonatomic, assign) CGFloat radius;
- @property(nonatomic, assign) BOOL copyCycleScroll;
- @property (nonatomic, assign) NSInteger copyOffsetCount;
- @property(nonatomic, assign) BOOL isSelectedRow;
- @end
- @implementation PGPickerColumnView
- #define kWidth self.frame.size.width
- #define kHeight self.frame.size.height
- static NSString *const cellReuseIdentifier = @"PGPickerColumnCell";
- - (instancetype)initWithFrame:(CGRect)frame rowHeight:(CGFloat)rowHeight upLineHeight:(CGFloat)upLineHeight downLineHeight:(CGFloat)downLineHeight isCycleScroll:(BOOL)isCycleScroll datas:(NSArray *)datas {
- if (self = [super initWithFrame:frame]) {
- self.isCycleScroll = isCycleScroll;
- self.copyCycleScroll = isCycleScroll;
- self.rowHeight = rowHeight;
- self.upLineHeight = upLineHeight;
- self.downLineHeight = downLineHeight;
- self.backgroundColor = [UIColor clearColor];
- self.upLinePosY = (self.bounds.size.height - self.rowHeight) / 2 - self.upLineHeight;
- NSInteger index = self.upLinePosY / self.rowHeight;
- self.offsetCount = index + 1;
- self.offset = self.offsetCount * self.rowHeight - self.upLinePosY;
- if (self.offset == self.rowHeight) {
- self.offset = 0;
- self.offsetCount -= 1;
- }
- self.showCount = (frame.size.height / self.rowHeight - 1) / 2;
- self.circumference = self.rowHeight * self.showCount * 2 - 25;
- self.radius = self.circumference / M_PI * 2;
- self.copyOffsetCount = self.offsetCount;
-
- [self setupCycleScrollWithDatas:datas];
- [self setupView];
- }
- return self;
- }
- - (void)layoutSubviews {
- [super layoutSubviews];
- if (self.isSubViewLayouted) {
- return;
- }
- self.isSubViewLayouted = true;
- }
- - (void)setupCycleScrollWithDatas:(NSArray *)datas {
- if (self.frame.size.height >= self.rowHeight * datas.count) {
- self.isCycleScroll = false;
- }else {
- self.isCycleScroll = self.copyCycleScroll;
- }
- if (self.isCycleScroll) {
- self.offsetCount = 0;
- }else {
- self.offsetCount = self.copyOffsetCount;
- }
- }
- - (void)setupView {
- CGFloat upViewHeight = kHeight / 2 - self.rowHeight / 2 - self.upLineHeight;
- CGFloat centerViewPosY = upViewHeight + self.upLineHeight;
- CGFloat downViewPosY = centerViewPosY + self.rowHeight + self.downLineHeight;
-
- UIView *upView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, kWidth, upViewHeight)];
- upView.backgroundColor = [UIColor clearColor];
- upView.clipsToBounds = true;
- [self addSubview:upView];
- self.upView = upView;
-
- UIView *downView = [[UIView alloc]initWithFrame:CGRectMake(0, downViewPosY, kWidth, kHeight - downViewPosY)];
- downView.backgroundColor = [UIColor clearColor];
- downView.clipsToBounds = true;
- [self addSubview:downView];
- self.downView = downView;
-
- UIView *centerView = [[UIView alloc]initWithFrame:CGRectMake(0, centerViewPosY, kWidth, self.rowHeight)];
- centerView.backgroundColor = [UIColor clearColor];
- centerView.clipsToBounds = true;
- [self addSubview:centerView];
- self.centerView = centerView;
- [self setupTableView];
- }
- - (void)setupTableView {
- {
- CGRect frame = self.bounds;
- frame.origin.y = -self.offset;
- frame.size.height += self.offset;
- PGPickerTableView *tableView = [[PGPickerTableView alloc]initWithFrame:frame style:UITableViewStylePlain];
- [tableView registerClass:[PGPickerColumnCell class] forCellReuseIdentifier:cellReuseIdentifier];
- tableView.delegate = self;
- tableView.dataSource = self;
- tableView.showsVerticalScrollIndicator = false;
- tableView.showsHorizontalScrollIndicator = false;
- [self.upView addSubview:tableView];
- self.upTableView = tableView;
- }
- {
- CGRect frame = [self convertRect:self.upTableView.frame toView:self.centerView];
- PGPickerTableView *tableView = [[PGPickerTableView alloc]initWithFrame:frame style:UITableViewStylePlain];
- [tableView registerClass:[PGPickerColumnCell class] forCellReuseIdentifier:cellReuseIdentifier];
- tableView.delegate = self;
- tableView.dataSource = self;
- tableView.showsVerticalScrollIndicator = false;
- tableView.showsHorizontalScrollIndicator = false;
- [self.centerView addSubview:tableView];
- self.centerTableView = tableView;
- [self bringSubviewToFront:tableView];
- }
-
- {
- CGRect frame = [self convertRect:self.upTableView.frame toView:self.downView];
- PGPickerTableView *tableView = [[PGPickerTableView alloc]initWithFrame:frame style:UITableViewStylePlain];
- [tableView registerClass:[PGPickerColumnCell class] forCellReuseIdentifier:cellReuseIdentifier];
- tableView.delegate = self;
- tableView.dataSource = self;
- tableView.showsVerticalScrollIndicator = false;
- tableView.showsHorizontalScrollIndicator = false;
- [self.downView addSubview:tableView];
- self.downTableView = tableView;
- }
- }
- - (NSInteger)setupSelectedRow {
- NSInteger row = self.centerTableView.contentOffset.y / self.rowHeight + 0.5;
- if (self.isCycleScroll) {
- CGFloat posY = self.centerTableView.contentOffset.y + self.copyOffsetCount * self.rowHeight + self.rowHeight / 2;
- NSInteger count = posY / (self.datas.count * self.rowHeight);
- CGFloat newPosY = (self.centerTableView.contentOffset.y + self.copyOffsetCount * self.rowHeight) - (self.datas.count * self.rowHeight) * count;
- if (newPosY < 0) {
- newPosY = 0;
- }
- row = newPosY / self.rowHeight + 0.5;
- }
- return row;
- }
- - (void)setupTableViewScroll:(UITableView *)tableView animated:(BOOL)animated {
- CGPoint offsetPoint = CGPointMake(tableView.contentOffset.x, tableView.contentOffset.y + self.rowHeight / 2);
- NSIndexPath *indexPath = [tableView indexPathForRowAtPoint: offsetPoint];
- [tableView scrollToRowAtIndexPath: indexPath atScrollPosition: UITableViewScrollPositionTop animated:animated];
- }
- - (void)selectRow:(NSInteger)row animated:(BOOL)animated {
- NSInteger newRow = row;
- if (self.isCycleScroll) {
- newRow = row - self.copyOffsetCount;
- }
- if (animated) {
- NSIndexPath *indexPath = [NSIndexPath indexPathForRow:newRow inSection:0];
- [self.centerTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:true];
- self.selectedRow = row;
- self.isSelectedRow = true;
- }else {
- self.centerTableView.contentOffset = CGPointMake(0, newRow * self.rowHeight);
- [self scrollViewDidEndDecelerating: self.centerTableView];
- }
- }
- #pragma mark - UIScrollViewDelegate
- - (void)scrollViewDidScroll:(UITableView *)tableView {
- CGPoint offset = tableView.contentOffset;
- NSInteger rowHeight = self.rowHeight;
- NSInteger posY = offset.y;
- NSInteger value = posY % rowHeight;
- CGFloat itemAngle = value * ((rowHeight / self.radius) / rowHeight);
-
- if (self.isCycleScroll) {
- if (posY < self.rowHeight * self.datas.count * 2) {
- posY = posY + self.rowHeight * self.datas.count;
- }
- if (posY > self.rowHeight * self.datas.count * 3) {
- posY = posY - self.rowHeight * self.datas.count;
- }
- }
-
- if (self.centerTableView == tableView) {
- self.upTableView.contentOffset = CGPointMake(0, posY);
- self.downTableView.contentOffset = CGPointMake(0, posY);
- return;
- }
-
- if (tableView == self.downTableView) {
- self.centerTableView.contentOffset = CGPointMake(0, posY);
- if (!self.isHiddenWheels) {
- [tableView.visibleCells enumerateObjectsUsingBlock:^(__kindof PGPickerColumnCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
- NSUInteger index = idx - self.showCount;
- NSInteger length = index * rowHeight;
- CGFloat angle = length / self.radius - itemAngle;
- CGFloat scale = cos(angle / 2);
- [obj transformWith:angle scale:scale];
- }];
- }
- return;
- }
-
- if (tableView == self.upTableView) {
- self.centerTableView.contentOffset = CGPointMake(0, posY);
- if (!self.isHiddenWheels) {
- [tableView.visibleCells enumerateObjectsUsingBlock:^(__kindof PGPickerColumnCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
- NSUInteger index = self.showCount - idx;
- NSInteger length = index * rowHeight;
- CGFloat angle = length / self.radius + itemAngle;
- CGFloat scale = cos(angle / 2);
- [obj transformWith:angle scale: scale];
- }];
- }
- }
- }
- - (void)scrollViewDidEndDragging:(UITableView *)scrollView willDecelerate:(BOOL)decelerate{
- if (decelerate) return;
- [self scrollViewDidEndDecelerating:scrollView];
- }
- - (void)scrollViewDidEndDecelerating:(UITableView *)tableView {
- [self setupTableViewScroll:tableView animated:true];
- self.selectedRow = [self setupSelectedRow];
- }
- - (void)scrollViewDidEndScrollingAnimation:(UITableView *)tableView {
- if (!self.isSelectedRow) {
- [self setupTableViewScroll:tableView animated:false];
- NSUInteger row = [self setupSelectedRow];
- self.selectedRow = row;
- }
- if (self.isSelectedRow) {
- self.isSelectedRow = false;
- }
-
- }
- #pragma mark - row logic
- - (NSUInteger)numberOfRowsInTableView {
- return self.datas.count + self.offsetCount * 2;
- }
- #pragma mark - UITableViewDataSource
- - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
- if (self.isCycleScroll) {
- return 10;
- }
- return 1;
- }
- - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
- return [self numberOfRowsInTableView];
- }
- - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
- tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
- PGPickerColumnCell *cell = [tableView dequeueReusableCellWithIdentifier:cellReuseIdentifier];
- NSInteger row = indexPath.row - self.offsetCount;
-
- if (indexPath.row < self.offsetCount || row >= self.datas.count) {
- cell.label.attributedText = [[NSAttributedString alloc] initWithString: @""];
- cell.contentView.backgroundColor = [UIColor clearColor];
- }else {
- cell.label.attributedText = self.datas[row];
- cell.contentView.backgroundColor = self.viewBackgroundColors[row];
-
- if (!self.isHiddenWheels) {
- if (tableView == self.downTableView) {
- NSUInteger index = row - self.selectedRow;
- NSInteger length = index * self.rowHeight;
- CGFloat angle = length / self.radius;
- CGFloat scale = cos(angle / 2);
- [cell transformWith:angle scale:scale];
- }else if (tableView == self.upTableView) {
- NSUInteger index = self.selectedRow - row;
- NSInteger length = index * self.rowHeight;
- CGFloat angle = length / self.radius;
- CGFloat scale = cos(angle / 2);
- [cell transformWith:angle scale:scale];
- }
- }
- }
- if (tableView == self.centerTableView) {
- cell.label.textColor = self.textColorOfSelectedRow;
- cell.label.font = self.textFontOfSelectedRow;
- }else {
- cell.label.textColor = [self textColorOfOtherRow:row];
- cell.label.font = [self textFontOfOtherRow:row];
- }
- return cell;
- }
- #pragma mark - UITableViewDelegate
- - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
- NSInteger row = indexPath.row;
- if (row < self.offsetCount || row >= self.datas.count + self.offsetCount) {
- return;
- }
- UITableViewScrollPosition position = UITableViewScrollPositionTop;
- if (self.isCycleScroll) {
- position = UITableViewScrollPositionMiddle;
- }
- row = indexPath.row - self.offsetCount;
- [tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row - self.offsetCount inSection: indexPath.section] animated:true scrollPosition:position];
- self.selectedRow = indexPath.row - self.offsetCount;
- }
- - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
- if ([self numberOfRowsInTableView] - 1 == indexPath.row && !self.isCycleScroll) {
- CGFloat tmp = self.offsetCount * self.rowHeight - self.upLinePosY;
- if (self.rowHeight > 44) {
- return fabs(tmp - self.rowHeight);
- }
- }
- return self.rowHeight;
- }
- - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
- return self.rowHeight;
- }
- #pragma mark - Setter
- - (void)setSelectedRow:(NSUInteger)selectedRow {
- _selectedRow = selectedRow;
- if (self.datas.count > selectedRow) {
- NSAttributedString *attriString = self.datas[selectedRow];
- self.textOfSelectedRow = attriString.string;
- }
- if (self.delegate && [self.delegate respondsToSelector:@selector(pickerColumnView:didSelectRow:)]) {
- [self.delegate pickerColumnView:self didSelectRow:selectedRow];
- }
- if (self.delegate && [self.delegate respondsToSelector:@selector(pickerColumnView:title:didSelectRow:)]) {
- [self.delegate pickerColumnView:self title:self.textOfSelectedRow didSelectRow:selectedRow];
- }
- }
- - (void)setDatas:(NSArray *)datas {
- _datas = datas;
- [self setupCycleScrollWithDatas:datas];
- [self safeReloadData];
- }
- #pragma mark - other
- - (UIFont *)textFontOfOtherRow:(NSInteger)row {
- if (self.delegate && [self.delegate respondsToSelector:@selector(pickerColumnView:textFontOfOtherRow:InComponent:)]) {
- return [self.delegate pickerColumnView:self textFontOfOtherRow:row InComponent:self.component];
- }
- return self.textFontOfOtherRow;
- }
- - (UIColor *)textColorOfOtherRow:(NSInteger)row {
- if (self.delegate && [self.delegate respondsToSelector:@selector(pickerColumnView:textColorOfOtherRow:InComponent:)]) {
- return [self.delegate pickerColumnView:self textColorOfOtherRow:row InComponent:self.component];
- }
- return self.textColorOfOtherRow;
- }
- - (void)safeReloadData {
- [self.centerTableView reloadData];
- [self.upTableView reloadData];
- [self.downTableView reloadData];
-
- NSInteger index = [self setupSelectedRow];
- NSAttributedString *attriString = [[NSAttributedString alloc]initWithString:@""];
- if (self.datas.count > index) {
- attriString = self.datas[index];
- self.textOfSelectedRow = attriString.string;
- }
- }
- @end
|