在做这个功能之前我其实是拒绝的,为什么这么说呢,因为我怕麻烦啊!(开玩笑的,怕麻烦就不做程序员了)

  很久没有写博客,这次刚好项目中有个有趣的东西,想拿出来分享一下,希望能帮到某些小伙伴。

  首先说说需求,是这样的:

  在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右侧的滑动条的更多相关文章

  1. Android 自定义ScrollView 支持惯性滑动,惯性回弹效果。支持上拉加载更多

    先讲下原理: ScrollView的子View 主要分为3部分:head头部,滚动内容,fooder底部 我们实现惯性滑动,以及回弹,都是靠超过head或者fooder 就重新滚动到  ,内容的顶部或 ...

  2. Android 自定义ScrollView ListView 体验各种纵向滑动的需求

      分类: [android 进阶之路]2014-08-31 12:59 6190人阅读 评论(10) 收藏 举报 Android自定义ScrollView纵向拖动     转载请标明出处:http: ...

  3. Android自定义Seekbar滑动条,Pop提示跟随滑动按钮一起滑动

    由于项目需要做出此效果,自定义写了一个. 效果图 思路: 原始的seekbar只有滑动条并没有下方的提示文字,所以我们必须要继承Seekbar重写这个控件. 代码: 在values文件夹下新建attr ...

  4. 【转】自定义(滑动条)input[type="range"]样式

    1.如何使用滑动条? 用法很简单,如下所示: <input type="range" value="0"> 各浏览器原始样式如下: Chrome:  ...

  5. Android 自定义ScrollView的滑动监听事件

    项目结构: 1.LazyScrollView类(自定义ScrollView) package android.zhh.com.myapplicationscrollview; /** * Create ...

  6. ListView自定义滑动条

    /** * 修改默认滑动条 */ private void SetSliderIcon() { try { Field f = AbsListView.class.getDeclaredField(& ...

  7. HTML5新特性——自定义滑动条(input[type="range"])

    HTML 4.01 与 HTML5之间的差异 以下 input 的 type属性值是 HTML5 中新增的: color.date.datetime.datetime-local.month.week ...

  8. Android ScrollView监听滑动到顶部和底部的两种方式(你可能不知道的细节)

    Android ScrollView监听滑动到顶部和底部,虽然网上很多资料都有说,但是不全,而且有些细节没说清楚 使用场景: 1. 做一些复杂动画的时候,需要动态判断当前的ScrollView是否滚动 ...

  9. android 自定义scrollview 仿QQ空间效果 下拉伸缩顶部图片,上拉回弹 上拉滚动顶部title 颜色渐变

    首先要知道  自定义scrollview 仿QQ效果 下拉伸缩放大顶部图片 的原理是监听ontouch事件,在MotionEvent.ACTION_MOVE事件时候,使用不同倍数的系数,重置布局位置[ ...

随机推荐

  1. 微信聊天记录查看器(程序+源码) - iOS版

    本文版权归cxun所有,如有转载请注明出处与本文链接,谢谢!原文地址:http://www.cnblogs.com/cxun/p/4338643.html Updates [2016.10.14]感谢 ...

  2. html5,加密元素

    <form action="">    账号:<input type="text" name="user">     ...

  3. NIO SelectionKey中定义的4种事件

    SelectionKey.OP_ACCEPT —— 接收连接继续事件,表示服务器监听到了客户连接,服务器可以接收这个连接了 SelectionKey.OP_CONNECT —— 连接就绪事件,表示客户 ...

  4. Configure Visual Studio 2013 for debugging .NET framework

    https://referencesource.microsoft.com/ In order to configure Visual Studio 2013 do the following in ...

  5. netty 解决TCP粘包与拆包问题(二)

    TCP以流的方式进行数据传输,上层应用协议为了对消息的区分,采用了以下几种方法. 1.消息固定长度 2.第一篇讲的回车换行符形式 3.以特殊字符作为消息结束符的形式 4.通过消息头中定义长度字段来标识 ...

  6. java学习点

    (1) spring mvc (2) java 多线程 (3) 链表 (4) mq (5) db2 (6)meaven (7) Mybitis

  7. Rest Post示例(java服务端、python客户端)

    前提:服务端是现成的,java.springMVC.resttemplate.jboss等:突然有个需要,要在windows上开发一个客户端,作用是定期向服务端上传文件.想了想,如果客户端写一个jav ...

  8. java中常见的几种异常

    算术异常类:ArithmeticExecption空指针异常类:NullPointerException类型强制转换异常:ClassCastException数组负下标异常:NegativeArray ...

  9. ping命令脚本实现显示网络状态、学生姓名、学号

    #!/bin/bash a=. ####定义一个固定变量 h=(wanghao xieyunshen 刘桃) ####定义数组 ..} ####for循环,后面的in是条件即从多少循环到多少 do # ...

  10. mysql connection refused

    mysql数据库认证的时候和别的服务器不一样,即使mysqld数据库服务器没有启动,使用mysql这种客户端程序去连接,也要先输入密码,从而使人有一种错觉,以会服务器已经正常启动了.是不是密码或是主机 ...