一:在ViewController中實(shí)例化MLPickerScrollView完成代理<MLPickerScrollViewDataSource份招,MLPickerScrollViewDelegate>
////? 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.數(shù)據(jù)源
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個(gè)的寬度
_pickerScollView.itemHeight = kItemH;
_pickerScollView.firstItemX = (_pickerScollView.frame.size.width - _pickerScollView.itemWidth) * 0.5;
_pickerScollView.dataSource = self;
_pickerScollView.delegate = self;
[self.view addSubview:_pickerScollView];
// 3.刷新數(shù)據(jù)
[_pickerScollView reloadData];
// 4.滾動(dòng)到對(duì)應(yīng)折扣
self.discount = 2;//(NSInteger)arc4random()%10;
/*if (self.discount) {
NSInteger number = 0;
for (int i = 0; i < data.count; i++) {
MLDemoModel *model = [data objectAtIndex:i];
if (model.dicountIndex == self.discount) {
number = i;
}
}
*/
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;//標(biāo)記數(shù)據(jù)模型上的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(@" 點(diǎn)擊后代理回調(diào):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
#import@class MLPickerItem,MLPickerScrollView;@protocol MLPickerScrollViewDelegate/**? *? 選中(代理方法-可選) * *? @param menuScollView MLPickerScrollView *? @param index? ? ? ? 下標(biāo) */@optional- (void)pickerScrollView:(MLPickerScrollView *)menuScrollViewdidSelecteItemAtIndex:(NSInteger)index;/** *? 改變中心位置的Item樣式 * *? @param item MLPickerItem */- (void)itemForIndexChange:(MLPickerItem *)item;/** *? 改變-非-中心位置的Item樣式 * *? @param item MLPickerItem */- (void)itemForIndexBack:(MLPickerItem *)item;@end@protocol MLPickerScrollViewDataSource/** *? 個(gè)數(shù) * *? @param pickerScrollView MLPickerScrollView * *? @return 需要展示的item個(gè)數(shù) */- (NSInteger)numberOfItemAtPickerScrollView:(MLPickerScrollView *)pickerScrollView;/** *? 用來創(chuàng)建MLPickerItem * *? @param pickerScrollView MLPickerScrollView *? @param index? ? ? ? 位置下標(biāo) * *? @return MLPickerItem */- (MLPickerItem *)pickerScrollView:(MLPickerScrollView *)pickerScrollView? ? ? ? ? ? ? ? ? itemAtIndex:(NSInteger)index;@end@interface MLPickerScrollView : UIView/** 選中下標(biāo) */@property (nonatomic, assign)NSInteger seletedIndex;/** menu寬 */@property (nonatomic, assign)CGFloat itemWidth;/** menu高 */@property (nonatomic, assign)CGFloat itemHeight;/** 第一個(gè)item X值 */@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(@"? ---? 刷新數(shù)據(jù)后重新布局? ---? ");
// 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的坐標(biāo)
}
// startX的坐標(biāo)(所有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));
//計(jì)算滾動(dòng)區(qū)間
[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);
/*
self.scrollView.contentOffset.width: 869.400000
self.scrollView.contentOffset.height: 110.000000
self.scrollView.contentOffset.x: 0.000000
*/
}
#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];
}//刷新界面的時(shí)候獲取items的個(gè)數(shù)
for (NSInteger i = 0; i < count; i++) {//獲取到items的個(gè)數(shù)后再獲取到每個(gè)items的實(shí)例對(duì)象
MLPickerItem *item = nil;
if ([self.dataSource respondsToSelector:@selector(pickerScrollView:itemAtIndex:)]) {
item = [self.dataSource pickerScrollView:self itemAtIndex:i];
}
//把每個(gè)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;//選中回調(diào)index
}
// layout
[self layoutItems];
}
- (void)scollToSelectdIndex:(NSInteger)index
{
[self selectItemAtIndex:index];
}
#pragma mark - Helper
/* 根據(jù)scrollView的contentoffset來 是哪個(gè)item處于中心點(diǎn)區(qū)域巷挥, 然后傳出去通知外面 */
- (void)setItemAtContentOffset:(CGPoint)offset
{
NSInteger centerIndex = roundf(offset.x / self.itemWidth);//返回最接近_X的整數(shù)
NSLog(@" setItemAtContentOffset: %ld? 移動(dòng)距離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];
}];
//先移動(dòng)再讓中間的變大
}
//滑動(dòng)停止的時(shí)候調(diào)用這個(gè)方法
/*
contentSize:scrollview可顯示的區(qū)域
屬性類型:
struct CGSize {
CGFloat width;
CGFloat height;
};
typedef struct CGSize CGSize;
contentOffset:scrollview當(dāng)前顯示區(qū)域頂點(diǎn)相對(duì)于frame頂點(diǎn)的偏移量
屬性類型:
struct CGPoint {
CGFloat x;
CGFloat y;
};
typedef struct CGPoint CGPoint;
contentInset:scrollview的contentview的頂點(diǎn)相對(duì)于scrollview的位置
屬性類型:
typedef struct UIEdgeInsets {
CGFloat top, left, bottom, right;
} UIEdgeInsets;
*/
- (void)setCenterContentOffset:(UIScrollView *)scrollView
{
CGFloat offsetX = scrollView.contentOffset.x;//移動(dòng)的x距離
NSLog(@" scrollView offsetX : %f",offsetX);
if (offsetX < 0) {
offsetX = self.itemWidth * 0.5;//offsetX 為負(fù)的時(shí)候就滑到第一個(gè)位置
}else if (offsetX > (self.items.count - 1) * self.itemWidth) {
offsetX = (self.items.count - 1) * self.itemWidth;
}
NSInteger value = roundf(offsetX / self.itemWidth);//滑到第幾個(gè)
NSLog(@" value : %ld? offsetX : %f",value,offsetX);
[UIView animateWithDuration:kAnimationTime animations:^{
[scrollView setContentOffset:CGPointMake(self.itemWidth * value, scrollView.contentOffset.y)];//滑動(dòng)到哪個(gè)就移動(dòng)到哪個(gè)
} completion:^(BOOL finished) {
[self setItemAtContentOffset:scrollView.contentOffset];//然后使中間的最大
}];
}
#pragma mark - delegate
- (void)selectItemAtIndex:(NSInteger)index
{
NSLog(@"點(diǎn)擊選中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];
}
}
/** 手指離開屏幕后ScrollView還會(huì)繼續(xù)滾動(dòng)一段時(shí)間直到停止 時(shí)執(zhí)行
*? 如果需要scrollview在停止滑動(dòng)后一定要執(zhí)行某段代碼的話應(yīng)該搭配scrollViewDidEndDragging函數(shù)使用
*/
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
NSLog(@"? --? scrollViewDidEndDecelerating? --? ");
[self setCenterContentOffset:scrollView];
}
/** UIScrollView真正停止滑動(dòng)捌浩,應(yīng)該怎么判斷: 當(dāng)decelerate = true時(shí),才會(huì)調(diào)UIScrollView的delegate */
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (!decelerate) {
NSLog(@"? --? scrollViewDidEndDragging? --? ");
[self setCenterContentOffset:scrollView];
}
}
@end
三:自定義點(diǎn)擊view放button用于點(diǎn)擊選擇按鈕圖片文字父類MLPickerItem,子類重寫MLDemoItem
#import@interface MLPickerItem : UIView
@property (nonatomic, assign)NSInteger index;
@property (nonatomic, assign)CGSize originalSize;
@property (nonatomic, assign)BOOL selected;
/**
*? 選中回調(diào)
*/
@property (nonatomic, copy) void(^PickerItemSelectBlock)(NSInteger index);
/**
*? 子類重寫實(shí)現(xiàn)
*/
- (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);
}
}
// 留給子類調(diào)用
- (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];
}
/**
*? 改變item成紅色. frame變大
*/
- (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);
}
/**
*? 改變item成灰色,frame變小
*/
- (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
四:點(diǎn)擊MLDemoItem自定義模型MLDemoModel
#import@interface MLDemoModel : NSObject
@property (nonatomic, copy) NSString *dicountTitle;
@property (nonatomic, assign) NSInteger dicountIndex;
@property (nonatomic, copy) NSString *dicountImageName;
@end
@implementation MLDemoModel
@end
五:自定義圖片在上文字在下button:JXButton
#import@interface 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