自定义scrollview右侧的滑动条
在做这个功能之前我其实是拒绝的,为什么这么说呢,因为我怕麻烦啊!(开玩笑的,怕麻烦就不做程序员了)
很久没有写博客,这次刚好项目中有个有趣的东西,想拿出来分享一下,希望能帮到某些小伙伴。
首先说说需求,是这样的:
在tableview滑动的过程中,右侧的滑动条中间放一个label随着滑动条一起滑动,并且它的centerY与滑动条的centerY相等。当然,在滑到顶部或者尾部的时候label不能超出tableview的范围。
然后label上面显示与之对应的cell的内容。
刚开始想用系统提供的滑动条,scrollIndicator,没啥用啊。就提供了一个方法,没办法完成这种效果,只能自定义一个。下面有几个变量,我先设置一下,height:tableview的高度,allHeight:tableview内容的高度,y:tableview的contentoffset.y,currentHeight:滑动条的高度。
1.猜想,currentHeight/height=height/allHeight,然后去证实这一猜想,结果是有几个像素的偏差,不过并不影响。
2.确定滑动块的位置,要判断画框在画布的上半部分还是下半部分,在上面用top,在下面用bottom(没看明白继续往下看,有完整的代码):
if (y+height/2.0<=allHeight/2.0)
{
myScrollViewIndirect.top = +y*height/allHeight;
if (myScrollViewIndirect.top < )
{
myScrollViewIndirect.top = ;
}
}
else
{
CGFloat y1 = (allHeight-height-y);
myScrollViewIndirect.bottom = +height-y1*height/allHeight;
if (myScrollViewIndirect.bottom>+height)
{
myScrollViewIndirect.bottom = +height;
}
}
3.滑块的位置的高度确定了,相当于已经完成了一半,接下来是确定label的位置,这就简单了,将滑动条的centerY给label的centerY就可以了。不过滑到最顶部,而且继续往下拉,滑动到最底部继续往上拉的时候需要判断一下label的位置。很简单的条件语句,后面有。
4.最核心的功能,label显示其所在位置的cell内容。通过遍历tableview里面cell的位置来判断对应的是哪一个cell,获取其下标,然后在数据源中得到内容。不过由于是遍历,我实在没脸单独把这个算法拿出来,想想以后还是学学高级一点的算法吧。
最后附上代码,不然就要被喷了。
#define SUBCOUNT 0.2
#import "ALDayPictureWallViewController.h"
#import "ALGoalPictureWallViewController.h" @interface ALDayPictureWallViewController ()<UITableViewDelegate,UITableViewDataSource>
{
NSTimer *timer;
CGFloat subCount;
CGFloat y;
//自定义滑动块
UIView *myScrollViewIndirect;
UILabel *myLabel;
NSInteger cellCount;
}
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *dataArray; @end @implementation ALDayPictureWallViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
subCount = SUBCOUNT;
[self createNavi];
[self createUI]; myScrollViewIndirect = [LMFUITools createView:CGRectMake(, , , ) andBackgroundColor:[UIColor grayColor]];
myScrollViewIndirect.layer.cornerRadius = myScrollViewIndirect.width/2.0;
myScrollViewIndirect.right = SCREEN_WIDTH-;
[self.view addSubview:myScrollViewIndirect]; myLabel = [LMFUITools createLabelWithFrame:CGRectMake(, , , ) andBackgroundColor:[UIColor cyanColor] andTextAlignment:NSTextAlignmentCenter andFont:[UIFont systemFontOfSize:] andText:@"" andTextColor:[UIColor blackColor]];
myLabel.right = myScrollViewIndirect.left-;
[self.view addSubview:myLabel]; [self loadData]; } - (void)loadData
{
for (int i=; i<; i++)
{
NSString *str = [NSString stringWithFormat:@"第%i行", i];
[self.dataArray addObject:str];
}
[self.tableView reloadData];
} - (NSMutableArray *)dataArray
{
if (_dataArray == nil)
{
_dataArray = [NSMutableArray array];
}
return _dataArray;
} - (void)createNavi
{
float height = ;
float width = height * / ;
UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(, , , )];
[self.view addSubview:leftView];
UIImageView *image = [LMFUITools createImageView:CGRectMake(, (-height)/, width, height) andBackgroundImage:@"naviBlack_image"];
[leftView addSubview:image];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(goBackView:)];
[leftView addGestureRecognizer:tap]; UILabel *titleLable = [LMFUITools createLabelWithFrame:CGRectMake(, , SCREEN_WIDTH/2.0, ) andBackgroundColor:nil andTextAlignment:NSTextAlignmentCenter andFont:[UIFont systemFontOfSize:] andText:@"照片墙" andTextColor:[UIColor blackColor]];
titleLable.centerX = SCREEN_WIDTH * 0.5;
[self.view addSubview:titleLable]; //平铺
UIView *rightView = [[UIView alloc] initWithFrame:CGRectMake(, , , )];
rightView.right = SCREEN_WIDTH;
rightView.top = ;
[self.view addSubview:rightView]; UIImageView *rightImage = [LMFUITools createImageView:CGRectMake(, , , ) andBackgroundImage:@""];
[rightView addSubview:rightImage];
UILabel *label = [LMFUITools createLabelWithFrame:CGRectMake(, , , ) andBackgroundColor:nil andTextAlignment:NSTextAlignmentLeft andFont:[UIFont systemFontOfSize:] andText:@"平铺" andTextColor:[UIColor colorWithHexString:@"#999999"]];
label.left = rightImage.right;
[rightView addSubview:label]; UITapGestureRecognizer *goalPictureTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(startTimer)];
[rightView addGestureRecognizer:goalPictureTap];
} - (void)startTimer
{
if (timer == nil)
{
timer = [NSTimer scheduledTimerWithTimeInterval:0.002 target:self selector:@selector(startScrollTableView) userInfo:nil repeats:YES];
self.tableView.userInteractionEnabled = NO;
[timer fire];
}
else
{
[timer setFireDate:[NSDate distantFuture]];
timer = nil;
[timer invalidate];
self.tableView.userInteractionEnabled = YES;
}
} - (void)createUI
{
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(, , SCREEN_WIDTH, SCREEN_HEIGHT-) style:UITableViewStylePlain];
self.tableView.backgroundColor = [UIColor colorWithHexString:@"#f5f5f5"];
// self.tableView.showsVerticalScrollIndicator = NO;
// self.tableView.showsHorizontalScrollIndicator = NO;
// self.tableView.separatorInset = UIEdgeInsetsZero;
// self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.view addSubview:self.tableView];
[self.tableView setContentOffset:CGPointMake(, )];
} #pragma mark --tableview delegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return ;
} - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.dataArray count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return ;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UITableViewCell"];
}
if ([self.dataArray count])
{
cell.textLabel.text = [self.dataArray objectAtIndex:indexPath.row];
} cell.selectionStyle = ;
return cell;
} - (void)goalPicture:(UITapGestureRecognizer *)gesture
{
ALGoalPictureWallViewController *goalPictureView = [[ALGoalPictureWallViewController alloc] init];
self.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:goalPictureView animated:YES];
} #pragma mark --开始滑动
- (void)startScrollTableView
{
y+=subCount;
NSInteger count = ;
CGFloat height = count*44.0;
if (y>height-self.tableView.height)
{
subCount = -SUBCOUNT;
}
else if (y<)
{
subCount = SUBCOUNT;
}
[self.tableView setContentOffset:CGPointMake(, y)];
} - (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog(@"contentOffset.y %f", scrollView.contentOffset.y);
y = scrollView.contentOffset.y; //需要tableview的contentoffset.y,tableview的高度,tableview画布的高度
CGFloat height = scrollView.height;
CGFloat allHeight = scrollView.contentSize.height; //计算自定义滑块的高度
myScrollViewIndirect.height = height*height/allHeight;
//控件的高度不能设为负数,它会自动转化为正数,阿西吧
float currentHeight = myScrollViewIndirect.height;
//计算滑块
//如果tableview的中心在画框的上部,通过top确定滑块的位置 if (y<)
{
currentHeight += y;
}
if (y+height>allHeight)
{
CGFloat h = fabs(y+height-allHeight);
currentHeight -= h;
} if (currentHeight<)
{
myScrollViewIndirect.height = ;
}
else
{
myScrollViewIndirect.height = currentHeight;
} if (y+height/2.0<=allHeight/2.0)
{
myScrollViewIndirect.top = +y*height/allHeight;
if (myScrollViewIndirect.top < )
{
myScrollViewIndirect.top = ;
}
}
else
{
CGFloat y1 = (allHeight-height-y);
myScrollViewIndirect.bottom = +height-y1*height/allHeight;
if (myScrollViewIndirect.bottom>+height)
{
myScrollViewIndirect.bottom = +height;
}
}
myLabel.height = ;
myLabel.centerY = myScrollViewIndirect.centerY;
if (myLabel.top < )
{
myLabel.top = ;
}
if (myLabel.bottom>+height)
{
myLabel.bottom = +height;
}
CGFloat centerY = myLabel.centerY+y-;
for (NSInteger i=; i<[self.dataArray count]; i++)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:];
CGRect rectInTableView = [self.tableView rectForRowAtIndexPath:indexPath];
// CGRect rect = [self.tableView convertRect:rectInTableView toView:[self.tableView superview]];
if (rectInTableView.origin.y<=centerY && centerY<=rectInTableView.origin.y+rectInTableView.size.height)
{
NSLog(@"cell.y=%f cellHeight=%f", rectInTableView.origin.y, rectInTableView.size.height);
myLabel.text = [self.dataArray objectAtIndex:i];
return;
}
if (rectInTableView.origin.y > centerY)
{
NSLog(@"cell.y=%f cellHeight=%f", rectInTableView.origin.y, rectInTableView.size.height);
return;
}
}
} - (void)goBackView:(UITapGestureRecognizer *)gesture
{
[self.navigationController popViewControllerAnimated:YES];
} - (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.navigationBar.hidden = YES;
} - (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[timer setFireDate:[NSDate distantFuture]];
timer = nil;
[timer invalidate];
self.navigationController.navigationBar.hidden = NO;
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} @end
自定义scrollview右侧的滑动条的更多相关文章
- Android 自定义ScrollView 支持惯性滑动,惯性回弹效果。支持上拉加载更多
先讲下原理: ScrollView的子View 主要分为3部分:head头部,滚动内容,fooder底部 我们实现惯性滑动,以及回弹,都是靠超过head或者fooder 就重新滚动到 ,内容的顶部或 ...
- Android 自定义ScrollView ListView 体验各种纵向滑动的需求
分类: [android 进阶之路]2014-08-31 12:59 6190人阅读 评论(10) 收藏 举报 Android自定义ScrollView纵向拖动 转载请标明出处:http: ...
- Android自定义Seekbar滑动条,Pop提示跟随滑动按钮一起滑动
由于项目需要做出此效果,自定义写了一个. 效果图 思路: 原始的seekbar只有滑动条并没有下方的提示文字,所以我们必须要继承Seekbar重写这个控件. 代码: 在values文件夹下新建attr ...
- 【转】自定义(滑动条)input[type="range"]样式
1.如何使用滑动条? 用法很简单,如下所示: <input type="range" value="0"> 各浏览器原始样式如下: Chrome: ...
- Android 自定义ScrollView的滑动监听事件
项目结构: 1.LazyScrollView类(自定义ScrollView) package android.zhh.com.myapplicationscrollview; /** * Create ...
- ListView自定义滑动条
/** * 修改默认滑动条 */ private void SetSliderIcon() { try { Field f = AbsListView.class.getDeclaredField(& ...
- HTML5新特性——自定义滑动条(input[type="range"])
HTML 4.01 与 HTML5之间的差异 以下 input 的 type属性值是 HTML5 中新增的: color.date.datetime.datetime-local.month.week ...
- Android ScrollView监听滑动到顶部和底部的两种方式(你可能不知道的细节)
Android ScrollView监听滑动到顶部和底部,虽然网上很多资料都有说,但是不全,而且有些细节没说清楚 使用场景: 1. 做一些复杂动画的时候,需要动态判断当前的ScrollView是否滚动 ...
- android 自定义scrollview 仿QQ空间效果 下拉伸缩顶部图片,上拉回弹 上拉滚动顶部title 颜色渐变
首先要知道 自定义scrollview 仿QQ效果 下拉伸缩放大顶部图片 的原理是监听ontouch事件,在MotionEvent.ACTION_MOVE事件时候,使用不同倍数的系数,重置布局位置[ ...
随机推荐
- 非常强大的table根据表头排序,点击表头名称,对其内容排序
js代码: /** * 通过表头对表列进行排序 * * @param sTableID * 要处理的表ID<table id=''> * @param iCol * 字段列id eg: 0 ...
- iOS GCD 编程小结
一.简单介绍 1.GCD简介? 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器” 纯C语言,提供了非常多强大的函数 2.GCD优势 GCD是苹果公司为多核的并行运算提出的 ...
- .NET开发者必备的工具箱
本文作者Spencer是一名专注于ASP.NET和C#的程序员,他列举了平时工作.在家所使用的大部分开发工具,其中大部分工具都是集中于开发,当然也有一些其它用途的,比如图片处理.文件压缩等. 如果你是 ...
- 从JAVA看C#中volatile和synchronized关键字的作用
最近一直在想C#中 volatile关键字到底是用来干什么的?查了很多.NET的文章都是说用volatile修饰的变量可以让多线程同时修改,这是什么鬼... 然后查到了下面这篇JAVA中关于volat ...
- 将webservice封装成dll
生成dll文件的步骤如下:1.发布完成后,在浏览器中打开WebService文件,如:http://localhost/WebSer/WebService1.asmx,可以看到WebService1. ...
- JS倒计时功能,给定时间返回规定格式倒计时时间
重写了一下,增强了通用性,重写时发现月份和年份计算很复杂,因为月份天数不一样,年份又涉及平年闰年; 本人数学实在不佳无法写出算法,哪位大大日后写出来了分享给小弟一份,谢谢~. <!doctype ...
- php常用array函数
http://www.w3school.com.cn/php/php_ref_array.asp 1.array_change_key_case() 把数组中所有键更改为小写或大写2.array_ch ...
- exp_tools
#pwntools # github https://github.com/Gallopsled/pwntools 在线帮助文档 https://docs.pwntools.com/en/stable ...
- [译]Dynamics AX 2012 R2 BI系列-规划分析的注意事项
https://msdn.microsoft.com/en-us/library/gg731898.aspx 在开始实施AX的分析特性前,有很多事情要考虑.本文描述了你必须考虑的事情,和在 ...
- 将形如:Oct 8, 2016 5:29:44 PM串转换成正常时间在真机上遇到的坑
将形如:Oct 8, 2016 5:29:44 PM串转换成正常时间在真机上遇到的坑 /** * 根据传入字符串 * * @param str 传入的日期字符串 形如:Oct 8, 2016 5:29 ...