自定义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事件时候,使用不同倍数的系数,重置布局位置[ ...
随机推荐
- 微信聊天记录查看器(程序+源码) - iOS版
本文版权归cxun所有,如有转载请注明出处与本文链接,谢谢!原文地址:http://www.cnblogs.com/cxun/p/4338643.html Updates [2016.10.14]感谢 ...
- html5,加密元素
<form action=""> 账号:<input type="text" name="user"> ...
- NIO SelectionKey中定义的4种事件
SelectionKey.OP_ACCEPT —— 接收连接继续事件,表示服务器监听到了客户连接,服务器可以接收这个连接了 SelectionKey.OP_CONNECT —— 连接就绪事件,表示客户 ...
- Configure Visual Studio 2013 for debugging .NET framework
https://referencesource.microsoft.com/ In order to configure Visual Studio 2013 do the following in ...
- netty 解决TCP粘包与拆包问题(二)
TCP以流的方式进行数据传输,上层应用协议为了对消息的区分,采用了以下几种方法. 1.消息固定长度 2.第一篇讲的回车换行符形式 3.以特殊字符作为消息结束符的形式 4.通过消息头中定义长度字段来标识 ...
- java学习点
(1) spring mvc (2) java 多线程 (3) 链表 (4) mq (5) db2 (6)meaven (7) Mybitis
- Rest Post示例(java服务端、python客户端)
前提:服务端是现成的,java.springMVC.resttemplate.jboss等:突然有个需要,要在windows上开发一个客户端,作用是定期向服务端上传文件.想了想,如果客户端写一个jav ...
- java中常见的几种异常
算术异常类:ArithmeticExecption空指针异常类:NullPointerException类型强制转换异常:ClassCastException数组负下标异常:NegativeArray ...
- ping命令脚本实现显示网络状态、学生姓名、学号
#!/bin/bash a=. ####定义一个固定变量 h=(wanghao xieyunshen 刘桃) ####定义数组 ..} ####for循环,后面的in是条件即从多少循环到多少 do # ...
- mysql connection refused
mysql数据库认证的时候和别的服务器不一样,即使mysqld数据库服务器没有启动,使用mysql这种客户端程序去连接,也要先输入密码,从而使人有一种错觉,以会服务器已经正常启动了.是不是密码或是主机 ...