UITableView scroll smooth with certain speed?
I'm building a custom slot machine with a column that exists of a 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) S开发者_开发技巧low down the scroll animation. Or, B) Change the duration for the scroll animation to a self defined value.
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?
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.
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.
This can be done the same with the 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.
This is the .h file:
#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:
#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:
.
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.
the common way to make apps-slot-machines is with UIPickerView maybe you should check this..
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.
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.
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.
- (void) setTableScrollPosition:(CGFloat)position
{
CGPoint newOffset = CGPointMake(0.0, position);
scrollView.contentOffset = newOffset;
}
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:
[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.
- (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,
i.e. if I write j = j+10;
then my 3000 rows took about 9 seconds to scroll. (3000 * mean FPS that I could muster).
If I set it to j = j+20;
then the 3000 rows took about 4.5 seconds. 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. 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 :)
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
精彩评论