简体   繁体   English

UITableView以一定的速度滚动?

[英]UITableView scroll smooth with certain speed?

I'm building a custom slot machine with a column that exists of a uitableview. 我正在构建一个自定义老虎机,其中包含一个uitableview列。

When the user pulls a lever the tableview should scroll to a certain position with an index. 当用户拉动杠杆时,工作台视图应滚动到具有索引的特定位置。 I used the method: 我用的方法是:

- scrollToRowAtIndexPath:atScrollPosition:animated:

But this method will make the table scroll with a constant duration. 但是这种方法会使表格以恒定的持续时间滚动。 So you will not really recognize a long or short spin. 所以你不会真正认识到长期或短期的旋转。

I'm looking for a way to: A) Slow down the scroll animation. 我正在寻找一种方法:A)减慢滚动动画。 Or, B) Change the duration for the scroll animation to a self defined value. 或者,B)将滚动动画的持续时间更改为自定义值。

The normal scroll animation (with the finger) does show this effect. 正常的滚动动画(用手指)确实显示了这种效果。 Maybe it is a stupid idea, but is it an idea to invoke a touchesBegan and touchesDidEnd method on my tableView? 也许这是一个愚蠢的想法,但是在我的tableView上调用touchesBegan和touchesDidEnd方法是一个想法吗?

Thanks already 谢谢

May need to look in that direction? 可能需要朝那个方向看?

 [UIView animateWithDuration: 1.0
                  animations: ^{
                      [tableViewExercises scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:previousSelectedExerciseCell inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
                  }completion: ^(BOOL finished){
                  }
    ];

Work only with animated:NO. 仅使用动画:NO。

Because a UITableView inherits from UIScrollView you might also use setContentOffset:animated: This way you can make your tableview "scroll" a certain amount of pixels of your choosing to any side you like. 因为UITableView继承自UIScrollView,所以你也可以使用setContentOffset:animated:这样你就可以让你的tableview将你选择的一定数量的像素“滚动”到你喜欢的任何一面。

This can be done the same with the scrollToRowAtIndexPath:atScrollPosition:animated: 这可以与scrollToRowAtIndexPath相同:atScrollPosition:animated:

I made a prototype just to show you how it works. 我做了一个原型只是为了告诉你它是如何工作的。

Because this is done with timers and stuff you can set how long the autoScroll will last and how fast (and how far if you're using the contentoffset) the animation will go. 因为这是通过计时器和东西来完成的,你可以设置autoScroll将持续多长时间以及动画将会有多快(以及你使用contentoffset的距离)。

This is the .h file: 这是.h文件:

#import <UIKit/UIKit.h>

@interface AutomaticTableViewScrollViewController : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
    UITableView *slotMachine;
    NSMutableArray *listOfItems;
    NSTimer *tableTimer;
}

@property (nonatomic,retain) UITableView *slotmachine;
@property (nonatomic,retain) NSMutableArray *listOfItems;
@property (nonatomic,retain) NSTimer *tableTimer;

-(void)automaticScroll;
-(void)stopscroll;

@end

This is the .m file: 这是.m文件:

#import "AutomaticTableViewScrollViewController.h"

@implementation AutomaticTableViewScrollViewController

@synthesize slotmachine;
@synthesize listOfItems;
@synthesize tableTimer;

-(void)loadView
{
    [super loadView];

    slotmachine = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
    slotmachine.delegate = self;
    slotmachine.dataSource = self;
    [self.view addSubview:slotmachine];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{    
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    // Set up the cell...
    if (indexPath.row % 2 == 0) 
    {
        cell.textLabel.text = @"blalala";
    }

    return cell;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 99999;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    //you might want to do this action in ur buttonTargetMethod
    //start timers
    tableTimer = [NSTimer scheduledTimerWithTimeInterval:0.2 //this value arranges the speed of the autoScroll
                                                   target:self
                                                 selector:@selector(automaticScroll)
                                                 userInfo:nil
                                                  repeats:YES];

    [NSTimer scheduledTimerWithTimeInterval:5 //this arranges the duration of the scroll
                                     target:self
                                   selector:@selector(stopscroll)
                                   userInfo:nil
                                    repeats:NO]; 
}

-(void)automaticScroll
{
    [slotmachine setContentOffset:CGPointMake(slotmachine.contentOffset.x, slotmachine.contentOffset.y + 50) animated:YES]; //the 50 stands for the amount of movement every tick the timer will make
}

-(void)stopscroll
{
    //stop tabletimer again
    [tableTimer invalidate];
}

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    return YES;
}

@end

If you have any question feel free to leave a comment and I will elaborate. 如果您有任何问题可以自由发表评论,我会详细说明。

If you can require iOS 5, you could use the UIScrollViewDelegate method scrollViewWillEndDragging:withVelocity:targetContentOffset: . 如果你可以要求iOS 5,你可以使用UIScrollViewDelegate方法scrollViewWillEndDragging:withVelocity:targetContentOffset: . This allows you to see, how fast the user was moving the finger, where the deceleration animation would end with the default speed, and it allows you to override the animation speed, so that it ends at a different point. 这使您可以查看用户移动手指的速度,减速动画以默认速度结束的位置,并允许您覆盖动画速度,以便在不同的点结束。

I searched a lot for this answer but ultimately had to come up with one of my own. 我搜索了很多这个答案,但最终还是得出了我自己的答案。 You can call the method scrollAutomatically with the starting row number like: 您可以使用起始行号调用方法scrollAutomatically,如:

[self scrollAutomatically:0];

So this is what the function looked like. 所以这就是函数的样子。 I was dealing with a table which always had 3000 rows and I intended to scroll to the bottom. 我正在处理一个总共有3000行的表,我打算滚动到底部。

- (void) scrollAutomatically:(int) i
{
    __block int j = i;
    [UIView animateWithDuration: 0//Change this to something more for slower scrolls
                     animations: ^{
                         [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:j inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:NO];
                     }
                     completion: ^(BOOL finished){
                         j = j + 10;//Changing this number affects speed.
                         if(j<=2999)//here you could provide the index of destination row
                             [self scrollAutomatically:j];
                         else
                         {
                             //I had some code here that popped up a UIAlertView.
                         }
                     }];
}

Now coming to the speed of the scroll. 现在来到滚动的速度。

FOR REALLY FAST SCROLLS: 真正的快速滚动:

If I set value by which I increment the row index (j) on each call of the function to 10, ie if I write j = j+10; 如果我设置值,我将函数的每次调用的行索引(j)增加到10,即如果我写j = j+10; then my 3000 rows took about 9 seconds to scroll. 然后我的3000行花了大约9秒来滚动。 (3000 * mean FPS that I could muster). (3000 *意味着我可以集合的FPS)。 If I set it to j = j+20; 如果我把它设置为j = j+20; then the 3000 rows took about 4.5 seconds. 然后3000行花了大约4.5秒。 So you get the idea. 所以你明白了。 To make it scroll slower reduce the increment value. 要使其滚动较慢,请减小增量值。

FOR SLOW, READABLE SCROLLS: 对于慢,可读的滚动:

[UIView animateWithDuration: 1.5//this will directly set your speed. n rows scrolled every 1.5 seconds.

NOTE: If you change frames of CALayers or Views (eg. a customView you may have added to the contentView of your tableViewCell), then those animations will start to bother you here. 注意:如果您更改CALayers或Views的框架(例如,您可能已添加到tableViewCell的contentView中的customView),那么这些动画将开始打扰您。 For a large animation duration, they will be very visible and you may see strange cell beahviour. 对于大型动画持续时间,它们将非常明显,您可能会看到奇怪的细胞行为。

In that case wherever you change your frames etc. look at something like: 在这种情况下,无论你改变你的帧等等,看看像这样的东西:

[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
[myView.myCALayer.frame = (CGRect){ { 10, 10 }, { 100, 100 } ];
[CATransaction commit];

Find the above solution here . 此处找到上述解决方案。

You may also have to set the actions dictionary for the layer to return nulls for all actions. 您可能还必须为图层设置操作字典,以便为所有操作返回空值。

NSMutableDictionary *newActions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[NSNull null], @"sublayers", nil];
superlayer.actions = newActions;

This seems to be too late but for people facing the same problem I hope this answer will be helpful. 这似乎为时已晚,但对于面临同样问题的人,我希望这个答案会有所帮助。 Also please feel free to guide me in case I have made some obvious (or not so much) blunder. 如果我犯了一些明显(或没有那么多)的错误,请随时指导我。

Edit: Oops, I see the exact thing above my answer :( Anyways, this is a bit more detailed and I am only a beginner :) 编辑:哎呀,我看到我的答案上面的确切事情:(不管怎样,这是一个更详细,我只是一个初学者:)

制作app-slot-machines的常用方法是用UIPickerView,也许你应该检查一下..

How about setup a timer and then call the scroll when timer fires: 如何设置计时器,然后在计时器触发时调用滚动:

start_index = 0;
dest_index = 20;
timer = [NSTimer scheduledTimerWithTimeInterval:(0.1) target:self selector:@selector(rolling) userInfo:nil repeats:YES];                


- (void)rolling {
start_index++;
if (start_index < dest_index) {
    NSIndexPath *Index = [NSIndexPath indexPathForRow:start_index inSection:0];
    [self.tableView scrollToRowAtIndexPath:Index atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
} else {
    [timer invalidate];
}
}

I've been using the Sparrow framework's tweening features to do similar animations. 我一直在使用Sparrow框架的补间功能来做类似的动画。

The link above has an example of how to set it up. 上面的链接有一个如何设置它的例子。 You can animate any numeric property of any Objective C object, and you can use transitions like "easy in", "ease out", "ease in elastic", etc., or just good old linear animations. 您可以为任何Objective C对象的任何数字属性设置动画,并且可以使用“easy in”,“ease out”,“easy in elastic”等转换,或者只是使用旧的线性动画。

The property contentSize is a CGPoint though, so you would need actually animate a different property on one of your classes and then implement an actual method for the property setter function so that it updates the contentOffset. 属性contentSize虽然是CGPoint,但是您需要在其中一个类上实际设置不同属性的动画,然后为属性setter函数实现一个实际方法,以便更新contentOffset。

- (void) setTableScrollPosition:(CGFloat)position
{
    CGPoint newOffset = CGPointMake(0.0, position);
    scrollView.contentOffset = newOffset;
}

You can't (to my knowledge, I have been looking everywhere for a way to do this) make a speed that isn't constant for 你不能(据我所知,我一直在寻找一种方法来做到这一点)制造一个不恒定的速度

- scrollToRowAtIndexPath:atScrollPosition:animated:

So I would suggest... that if you really need it, make your own out of some animation or something, or do something alot easier that would save you some time, use UIPickerView 所以我建议......如果你真的需要它,可以用一些动画或其他东西制作你自己的东西,或做一些比较容易的东西可以节省你一些时间,使用UIPickerView

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM