自定义scrollview右侧的滑动条

时间:2023-01-22 14:08:01

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

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

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

  在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. 【转】自定义&lpar;滑动条&rpar;input&lbrack;type&equals;&quot&semi;range&quot&semi;&rsqb;样式

    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&lbrack;type&equals;&quot&semi;range&quot&semi;&rsqb;)

    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. NodeJs 开发微信公众号(四)微信网页授权

    微信的网页授权指的是在微信公众号中访问第三方网页时获取用户地理.个人等信息的权限.对于开发了自己的网页app应用时,获取个人的信息非常重要.上篇博客讲到了注册时可以获取用户的信息,很多人会问为什么还需 ...

  2. ORACLE实现自定义序列号生成

    实际工作中,难免会遇到序列号生成问题,下面就是一个简单的序列号生成函数 (1)创建自定义序列号配置表如下: --自定义序列 create table S_AUTOCODE ( pk1 ) primar ...

  3. 简单谈谈如何利用h5实现音频的播放

    作者:白狼 出处:http://www.manks.top/article/h5_audio本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律 ...

  4. mysql命令行导入sql脚本中文变问号问题

    之前一直用工具连接mysql虽然小问题不断也都无伤大雅,最近做金融云项目,只能通过服务器的内网访问数据库,也就是说只能在linux下通过命令行访问,在导入中文的时候发现都变成问号了,经过查询资料解决, ...

  5. FusionCharts for Flex报错

    1.昨天,我新建了一个Flex项目,并将FusionCharts组件添加进去了,但是Flex应用程序还是报错 具体错误如下: 2.但是,Flex项目已经导入FusionCharts.swc

  6. C&num;操作Excel(读&sol;写)

    http://www.cnblogs.com/litianfei/archive/2008/03/21/1116906.html 写的很详细 一.操作Excel 首先导出Excel (1)示例: // ...

  7. Photoshop理论:另外一种角度看图层混合模式

    源地址:http://www.missyuan.com/thread-687724-1-4.html 1.我将一个色阶看成是一个由亮部和暗部组成的这么一个元素,亮部是我们看的见的,暗部是影响亮部的,有 ...

  8. vue 2&period;0 无法编译ES6语法

    # vue2.0 webpack 无法编译 ES6 语法 之前在使用 vue 1.x 时用 vue-loader@8.0.0 版本可以正常打包vue的代码,包括ES6语法也能正常转为ES5语法,但是当 ...

  9. php获取当前域名

    当前url:http://localhost:805/test/helloworld.php echo 'SERVER_NAME:'.$_SERVER['SERVER_NAME']; //获取当前域名 ...

  10. python———day03

    一.字符串格式化输出: 占位符    %s(字符串) %d(整数) %f(浮点数,约等于小数) name = input("Name:") age = input("Ag ...