一:在ViewController中執行個體化MLPickerScrollView完成代理 ViewController.m// OYRPickerDemo Created by 歐陽榮 on 17/3/30.// Copyright © 2017年 HengTaiXin. All rights reserved.//#import "ViewController.h"#import "MLPickerScrollView.h"#import "MLDemoItem.h"#import "MLDemoModel.h"#define kItemH 110#define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)#define SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)#define MLColor(r, g, b, a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:(a)]#define kRGB236 MLColor(236, 73, 73, 1.0)@interface ViewController (){
MLPickerScrollView *_pickerScollView;
NSMutableArray *data;
UIButton *sureButton;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self setUpUI];
// [self setUpSureButton];
}
#pragma mark - UI
- (void)setUpUI
{
// 1.資料源
data = [NSMutableArray array];
NSArray *titleArray = @[@"比杆賽",@"最近洞賽",@"推杆賽",@"比洞賽",@"三人鬥地主",@"四人拉斯"];
NSArray *titleImageArray = @[@"img_stroke-play",@"img_putting",@"img_nearpin",@"img_match",@"img_three-landlords",@"img_four-lars"];
for (int i = 0; i < titleArray.count; i++) {
MLDemoModel *model = [[MLDemoModel alloc] init];
model.dicountTitle = [titleArray objectAtIndex:i];
model.dicountImageName = [titleImageArray objectAtIndex:i];
[data addObject:model];
}
// 2.初始化
_pickerScollView = [[MLPickerScrollView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT - 350, SCREEN_WIDTH, kItemH)];
//_pickerScollView.backgroundColor = [UIColor lightGrayColor];
_pickerScollView.itemWidth = _pickerScollView.frame.size.width / 5; //剛好顯示5個的寬度
_pickerScollView.itemHeight = kItemH;
_pickerScollView.firstItemX = (_pickerScollView.frame.size.width - _pickerScollView.itemWidth) * 0.5;
_pickerScollView.dataSource = self;
_pickerScollView.delegate = self;
[self.view addSubview:_pickerScollView];
// 3.重新整理資料
[_pickerScollView reloadData];
// 4.滾動到對應折扣
self.discount = 2;//(NSInteger)arc4random()%10;
NSInteger number = _discount;
_pickerScollView.seletedIndex = number;
[_pickerScollView scollToSelectdIndex:number];
}
- (void)setUpSureButton
{
sureButton = [UIButton buttonWithType:UIButtonTypeCustom];
sureButton.frame = CGRectMake(15, SCREEN_HEIGHT - 200, SCREEN_WIDTH - 30, 44);
sureButton.backgroundColor = kRGB236;
sureButton.layer.cornerRadius = 22;
sureButton.layer.masksToBounds = YES;
[sureButton setTitle:@"确定" forState:UIControlStateNormal];
[sureButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[sureButton addTarget:self action:@selector(clickSure) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:sureButton];
}
#pragma mark - Action
- (void)clickSure
{
NSLog(@"确定--選擇折扣Index為%ld",(long)_pickerScollView.seletedIndex);
NSString *title;
for (int i = 0; i < data.count; i++) {
MLDemoModel *model = [data objectAtIndex:i];
if (model.dicountIndex == _pickerScollView.seletedIndex) {
title = model.dicountTitle;
}
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:nil delegate:self cancelButtonTitle:@"确定" otherButtonTitles:@"取消", nil];
[alert show];
}
#pragma mark - dataSource
- (NSInteger)numberOfItemAtPickerScrollView:(MLPickerScrollView *)pickerScrollView
{
return data.count;
}
- (MLPickerItem *)pickerScrollView:(MLPickerScrollView *)pickerScrollView itemAtIndex:(NSInteger)index
{
// creat
MLDemoItem *item = [[MLDemoItem alloc] initWithFrame:CGRectMake(0, 0, pickerScrollView.itemWidth, pickerScrollView.itemHeight)];
// assignment
MLDemoModel *model = [data objectAtIndex:index];
model.dicountIndex = index;//标記資料模型上的index 取出來指派也行
item.title = model.dicountTitle;
item.imageName = model.dicountImageName;
[item setGrayTitle];
// tap
item.PickerItemSelectBlock = ^(NSInteger d){
[_pickerScollView scollToSelectdIndex:d];
};
return item;
}
- (void)pickerScrollView:(MLPickerScrollView *)menuScrollView
didSelecteItemAtIndex:(NSInteger)index{
NSLog(@" 點選後代理回調:didSelecteItemAtIndex :%ld",index);
}
#pragma mark - delegate
- (void)itemForIndexChange:(MLPickerItem *)item
{
[item changeSizeOfItem];
}
- (void)itemForIndexBack:(MLPickerItem *)item
{
[item backSizeOfItem];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
二:封裝好選擇器MLPickerScrollView
#[email protected] MLPickerItem,MLPickerScrollView;@protocol [email protected] (void)pickerScrollView:(MLPickerScrollView *)menuScrollViewdidSelecteItemAtIndex:(NSInteger)index;- (void)itemForIndexChange:(MLPickerItem *)item;- (void)itemForIndexBack:(MLPickerItem *)item;@[email protected] MLPickerScrollViewDataSource- (NSInteger)numberOfItemAtPickerScrollView:(MLPickerScrollView *)pickerScrollView;- (MLPickerItem *)pickerScrollView:(MLPickerScrollView *)pickerScrollView itemAtIndex:(NSInteger)index;@[email protected] MLPickerScrollView : [email protected] (nonatomic, assign)NSInteger seletedIndex;@property (nonatomic, assign)CGFloat itemWidth;@property (nonatomic, assign)CGFloat itemHeight;@property (nonatomic, assign)CGFloat firstItemX;@property (nonatomic, weak)iddelegate;@property (nonatomic, weak)iddataSource;
- (void)reloadData;
- (void)scollToSelectdIndex:(NSInteger)index;
@end#define kAnimationTime .2#import "MLPickerScrollView.h"#import "MLPickerItem.h"@interface MLPickerScrollView ()@property (nonatomic,strong)UIScrollView *scrollView;
@property (nonatomic,strong)NSMutableArray *items;
@end
@implementation MLPickerScrollView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setUp];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self setUp];
}
return self;
}
#pragma mark - UI
- (void)setUp
{
self.items = [NSMutableArray array];
self.scrollView = [[UIScrollView alloc] initWithFrame:
CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))];
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.showsVerticalScrollIndicator = NO;
self.scrollView.delegate = self;
self.scrollView.decelerationRate = 0.5;
self.scrollView.backgroundColor = [UIColor clearColor];
self.firstItemX = 0;
[self addSubview:self.scrollView];
}
#pragma mark - layout Items
- (void)layoutSubviews
{
NSLog(@" --- layoutSubviews --- ");
[super layoutSubviews];
if (!self.items) {
return;
}
[self layoutItems];
}
- (void)layoutItems
{
NSLog(@" --- 重新整理資料後重新布局 --- ");
// layout
self.scrollView.frame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds));
// item起始X值
CGFloat startX = self.firstItemX;
NSLog(@" CGRectGetHeight(self.bounds) : %f self.itemHeight : %f",CGRectGetHeight(self.bounds),self.itemHeight);
for (int i = 0; i < self.items.count; i++) {
MLPickerItem *item = [self.items objectAtIndex:i];
item.frame = CGRectMake(startX, CGRectGetHeight(self.bounds)-self.itemHeight, self.itemWidth, self.itemHeight);
startX += self.itemWidth;//記錄x的坐标
}
// startX的坐标(所有itemWidth的和) + scrollview.width + firstItemX (0) - itemWidth * 0.5
self.scrollView.contentSize = CGSizeMake(MAX(startX+CGRectGetWidth(self.bounds)-self.firstItemX-self.itemWidth *.5, startX), CGRectGetHeight(self.bounds));
//計算滾動區間
[self setItemAtContentOffset:self.scrollView.contentOffset];
NSLog(@" self.scrollView.contentOffset.width: %f self.scrollView.contentOffset.height: %f self.scrollView.contentOffset.x: %f",self.scrollView.contentSize.width,self.scrollView.contentSize.height,self.scrollView.contentOffset.x);
}
#pragma mark - public Method(GetData)
- (void)reloadData
{
// remove
for (MLPickerItem *item in self.items) {
[item removeFromSuperview];
}
[self.items removeAllObjects];
// create
NSInteger count = 0;
if ([self.dataSource respondsToSelector:@selector(numberOfItemAtPickerScrollView:)]) {
count = [self.dataSource numberOfItemAtPickerScrollView:self];
}//重新整理界面的時候擷取items的個數
for (NSInteger i = 0; i < count; i++) {//擷取到items的個數後再擷取到每個items的執行個體對象
MLPickerItem *item = nil;
if ([self.dataSource respondsToSelector:@selector(pickerScrollView:itemAtIndex:)]) {
item = [self.dataSource pickerScrollView:self itemAtIndex:i];
}
//把每個item添加到scrollview
NSAssert(item, @"[self.dataSource pickerScrollView: itemAtIndex:index] can not nil");
item.originalSize = CGSizeMake(self.itemWidth, self.itemHeight);
[self.items addObject:item];
[self.scrollView addSubview:item];
item.index = i;//選中回調index
}
// layout
[self layoutItems];
}
- (void)scollToSelectdIndex:(NSInteger)index
{
[self selectItemAtIndex:index];
}
#pragma mark - Helper
- (void)setItemAtContentOffset:(CGPoint)offset
{
NSInteger centerIndex = roundf(offset.x / self.itemWidth);//傳回最接近_X的整數
NSLog(@" setItemAtContentOffset: %ld 移動距離offset——x: %f",(long)centerIndex,offset.x);
for (int i = 0; i < self.items.count; i++) {
MLPickerItem * item = [self.items objectAtIndex:i];
[self itemInCenterBack:item];
if (centerIndex == i) {
[self itemInCenterChange:item];
_seletedIndex = centerIndex;
}
}
}
- (void)scollToItemViewAtIndex:(NSInteger)index animated:(BOOL)animated
{
CGPoint point = CGPointMake(index * _itemWidth,self.scrollView.contentOffset.y);
NSLog(@" --- scollToItemViewAtIndex --- index: %ld point: %f",index,point.x);
[UIView animateWithDuration:kAnimationTime animations:^{
[self.scrollView setContentOffset:point];
} completion:^(BOOL finished) {
[self setItemAtContentOffset:point];
}];
//先移動再讓中間的變大
}
//滑動停止的時候調用這個方法
- (void)setCenterContentOffset:(UIScrollView *)scrollView
{
CGFloat offsetX = scrollView.contentOffset.x;//移動的x距離
NSLog(@" scrollView offsetX : %f",offsetX);
if (offsetX < 0) {
offsetX = self.itemWidth * 0.5;//offsetX 為負的時候就滑到第一個位置
}else if (offsetX > (self.items.count - 1) * self.itemWidth) {
offsetX = (self.items.count - 1) * self.itemWidth;
}
NSInteger value = roundf(offsetX / self.itemWidth);//滑到第幾個
NSLog(@" value : %ld offsetX : %f",value,offsetX);
[UIView animateWithDuration:kAnimationTime animations:^{
[scrollView setContentOffset:CGPointMake(self.itemWidth * value, scrollView.contentOffset.y)];//滑動到哪個就移動到哪個
} completion:^(BOOL finished) {
[self setItemAtContentOffset:scrollView.contentOffset];//然後使中間的最大
}];
}
#pragma mark - delegate
- (void)selectItemAtIndex:(NSInteger)index
{
NSLog(@"點選選中index : %ld",index);
_seletedIndex = index;
[self scollToItemViewAtIndex:_seletedIndex animated:YES];
if (self.delegate && [self.delegate respondsToSelector:@selector(pickerScrollView:didSelecteItemAtIndex:)]) {
[self.delegate pickerScrollView:self didSelecteItemAtIndex:_seletedIndex];
}
}
- (void)itemInCenterChange:(MLPickerItem*)item
{
if ([self.delegate respondsToSelector:@selector(itemForIndexChange:)]) {
[self.delegate itemForIndexChange:item];
}
}
- (void)itemInCenterBack:(MLPickerItem*)item
{
if ([self.delegate respondsToSelector:@selector(itemForIndexBack:)]) {
[self.delegate itemForIndexBack:item];
}
}
#pragma mark - scrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//NSLog(@" -- scrollViewDidScroll -- ");
for (int i = 0; i < self.items.count; i++) {
MLPickerItem * item = [self.items objectAtIndex:i];
[self itemInCenterBack:item];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
NSLog(@" -- scrollViewDidEndDecelerating -- ");
[self setCenterContentOffset:scrollView];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (!decelerate) {
NSLog(@" -- scrollViewDidEndDragging -- ");
[self setCenterContentOffset:scrollView];
}
}
@end
三:自定義點選view放button用于點選選擇按鈕圖檔文字父類MLPickerItem,子類重寫MLDemoItem
#[email protected] MLPickerItem : UIView
@property (nonatomic, assign)NSInteger index;
@property (nonatomic, assign)CGSize originalSize;
@property (nonatomic, assign)BOOL selected;
@property (nonatomic, copy) void(^PickerItemSelectBlock)(NSInteger index);
- (void)changeSizeOfItem;
- (void)backSizeOfItem;
@end#import "MLPickerItem.h"
@implementation MLPickerItem
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self addTapGesture];
}
return self;
}
- (void)addTapGesture
{
self.backgroundColor = [UIColor clearColor];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
[self addGestureRecognizer:tap];
}
- (void)tap
{
if (self.PickerItemSelectBlock) {
self.PickerItemSelectBlock(self.index);
}
}
// 留給子類調用
- (void)changeSizeOfItem{}
- (void)backSizeOfItem{}
@end#import "MLPickerItem.h"
@interface MLDemoItem : MLPickerItem
@property (nonatomic, strong)UIButton *discount;
@property (nonatomic, copy)NSString *title;
@property (nonatomic, copy)NSString *imageName;
- (void)setRedTitle;
- (void)setGrayTitle;
@end#define kITEM_WH 60
#define MLColor(r, g, b, a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:(a)]
#define kRGB220 MLColor(151, 151, 151, 1.0)
#define kRGB236 MLColor(51, 51, 51, 1.0)
#import "MLDemoItem.h"
#import "JXButton.h"
@implementation MLDemoItem
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setUI];
}
return self;
}
- (void)setUI
{
//self.backgroundColor = [UIColor greenColor];
_discount = [JXButton buttonWithType:UIButtonTypeCustom];
_discount.enabled = NO;
_discount.titleLabel.font = [UIFont systemFontOfSize:12];
//_discount.layer.borderWidth = 1.0f;
//_discount.layer.cornerRadius = kITEM_WH * 0.5;
//_discount.layer.masksToBounds = YES;
//_discount.backgroundColor = [UIColor redColor];
CGFloat itemW = kITEM_WH;
CGFloat itemH = kITEM_WH;
CGFloat itemX = (self.frame.size.width - itemW)*0.5;
CGFloat itemY = (self.frame.size.height - itemH) *0.5;
_discount.frame = CGRectMake(itemX, itemY, itemW, itemH);
[self addSubview:_discount];
}
- (void)setTitle:(NSString *)title
{
_title = title;
[_discount setTitle:title forState:UIControlStateNormal];
[_discount.titleLabel sizeToFit];
}
-(void)setImageName:(NSString *)imageName{
_imageName = imageName;
[_discount setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
}
- (void)setRedTitle
{
//_discount.layer.borderColor = kRGB236.CGColor;
[_discount setTitleColor:kRGB236 forState:UIControlStateNormal];
}
- (void)setGrayTitle
{
//_discount.layer.borderColor = kRGB220.CGColor;
[_discount setTitleColor:kRGB220 forState:UIControlStateNormal];
}
- (void)changeSizeOfItem
{
[self setRedTitle];
CGFloat itemW = kITEM_WH + kITEM_WH*0.5;
CGFloat itemH = kITEM_WH + kITEM_WH*0.5;
CGFloat itemX = (self.frame.size.width - itemW)*0.5;
CGFloat itemY = (self.frame.size.height - itemH) *0.5;
//_discount.layer.borderWidth = 1.0f;
//_discount.layer.cornerRadius = itemW * 0.5;
//_discount.layer.masksToBounds = YES;
_discount.frame = CGRectMake(itemX, itemY, itemW, itemH);
}
- (void)backSizeOfItem
{
[self setGrayTitle];
//_discount.layer.borderWidth = 1.0f;
//_discount.layer.cornerRadius = kITEM_WH * 0.5;
//_discount.layer.masksToBounds = YES;
CGFloat itemW = kITEM_WH;
CGFloat itemH = kITEM_WH;
CGFloat itemX = (self.frame.size.width - itemW)*0.5;
CGFloat itemY = (self.frame.size.height - itemH) *0.5;
_discount.frame = CGRectMake(itemX, itemY, itemW, itemH);
}
@end
四:點選MLDemoItem自定義模型MLDemoModel
#[email protected] MLDemoModel : NSObject
@property (nonatomic, copy) NSString *dicountTitle;
@property (nonatomic, assign) NSInteger dicountIndex;
@property (nonatomic, copy) NSString *dicountImageName;
@[email protected] MLDemoModel
@end
五:自定義圖檔在上文字在下button:JXButton
#[email protected] JXButton : UIButton
@end#import "JXButton.h"
@implementation JXButton
-(id)initWithCoder:(NSCoder *)aDecoder{
if (self=[super initWithCoder:aDecoder]) {
[self commonInit];
}
return self;
}
-(id)initWithFrame:(CGRect)frame{
if (self=[super initWithFrame:frame]) {
[self commonInit];
}
return self;
}
-(void)commonInit{
self.titleLabel.textAlignment = NSTextAlignmentCenter;
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
self.titleLabel.font = [UIFont systemFontOfSize:14];
}
-(CGRect)titleRectForContentRect:(CGRect)contentRect{
CGFloat titleX = 0;
CGFloat titleY = contentRect.size.height *0.75;
CGFloat titleW = contentRect.size.width;
CGFloat titleH = contentRect.size.height - titleY;
return CGRectMake(titleX - 10, titleY, titleW + 20, titleH);
}
-(CGRect)imageRectForContentRect:(CGRect)contentRect{
CGFloat imageW = CGRectGetWidth(contentRect);
CGFloat imageH = contentRect.size.height * 0.7;
return CGRectMake(0, 0, imageW, imageH);
}
@end