How to Put a static UIButton Overlaying a UITableView - ios

Basically, I wanna create a static UIButton on top whether or not the table view is scrolled. However, I tried to add the UIButton as the subview of the UIView and make it on the top by using "bringSubviewToFront" method. However, the UIButton still moves when I scroll the UITableView. Therefore, how can I make a static UIButton overlaying the UITableView?
Here is my code:
#import "DiscoverTimelineTableViewController.h"
#interface DiscoverTimelineTableViewController ()
#property (strong, nonatomic) UIView* myview;
#end
#implementation DiscoverTimelineTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self displayMakePlanButton];
NSLog(#"%f", self.view.layer.zPosition);
NSLog(#"%f", self.tableView.layer.zPosition);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 100.0f;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text = #"Sleepy";
return cell;
}
#pragma mark - Add the make plan button
- (void) displayMakePlanButton
{
CGFloat buttonWidth = self.view.frame.size.width;
CGFloat buttonHeight = 104.0f;
CGFloat navBarHeight = self.navigationController.navigationBar.frame.size.height;
CGFloat statBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
UIButton *makePlanButton = [UIButton buttonWithType: UIButtonTypeCustom];
[makePlanButton setFrame:CGRectMake(0, self.view.frame.size.height - buttonHeight - navBarHeight - statBarHeight, buttonWidth, buttonHeight)];
[makePlanButton setBackgroundColor:[UIColor colorWithRed:0.286 green:0.678 blue:0.231 alpha:1]];
[makePlanButton setTitle:#"MAKE PLAN" forState:UIControlStateNormal];
[self.view addSubview:makePlanButton];
//makePlanButton.layer.zPosition = 1;
[self.view bringSubviewToFront:makePlanButton];
NSLog(#"%f", makePlanButton.layer.zPosition);
}
#end

You're using a table view controller, so self.view is the table view. A table view is a scroll view, so the view scrolls along with everything else.
You should use a regular view controller with a table as a subview instead.
Alternatively, you could try resetting the view's frame in the scrollViewDidScroll: scroll view delegate method, but I think the view would still jitter a bit.
Finally, you could add the button directly to the UIWindow, but that's likely to bring up a whole host of other problems with rotations, animations, and transitions.

Related

UIbutton should not scroll with view [duplicate]

Basically, I wanna create a static UIButton on top whether or not the table view is scrolled. However, I tried to add the UIButton as the subview of the UIView and make it on the top by using "bringSubviewToFront" method. However, the UIButton still moves when I scroll the UITableView. Therefore, how can I make a static UIButton overlaying the UITableView?
Here is my code:
#import "DiscoverTimelineTableViewController.h"
#interface DiscoverTimelineTableViewController ()
#property (strong, nonatomic) UIView* myview;
#end
#implementation DiscoverTimelineTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self displayMakePlanButton];
NSLog(#"%f", self.view.layer.zPosition);
NSLog(#"%f", self.tableView.layer.zPosition);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 100.0f;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text = #"Sleepy";
return cell;
}
#pragma mark - Add the make plan button
- (void) displayMakePlanButton
{
CGFloat buttonWidth = self.view.frame.size.width;
CGFloat buttonHeight = 104.0f;
CGFloat navBarHeight = self.navigationController.navigationBar.frame.size.height;
CGFloat statBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
UIButton *makePlanButton = [UIButton buttonWithType: UIButtonTypeCustom];
[makePlanButton setFrame:CGRectMake(0, self.view.frame.size.height - buttonHeight - navBarHeight - statBarHeight, buttonWidth, buttonHeight)];
[makePlanButton setBackgroundColor:[UIColor colorWithRed:0.286 green:0.678 blue:0.231 alpha:1]];
[makePlanButton setTitle:#"MAKE PLAN" forState:UIControlStateNormal];
[self.view addSubview:makePlanButton];
//makePlanButton.layer.zPosition = 1;
[self.view bringSubviewToFront:makePlanButton];
NSLog(#"%f", makePlanButton.layer.zPosition);
}
#end
You're using a table view controller, so self.view is the table view. A table view is a scroll view, so the view scrolls along with everything else.
You should use a regular view controller with a table as a subview instead.
Alternatively, you could try resetting the view's frame in the scrollViewDidScroll: scroll view delegate method, but I think the view would still jitter a bit.
Finally, you could add the button directly to the UIWindow, but that's likely to bring up a whole host of other problems with rotations, animations, and transitions.

Perform animations on custom UITableViewCell

I'm trying to animate a few items in a custom UITableViewCell when a user presses a button in the cell. I have set addTarget: and added a method to animate the items in the cell. I've set a tag for the button so I can get the index. In the method, I call cellForRowAtIndexPath: to get the cell the button was called on. I'm casting the object returned by cellForRowAtIndexPath: to my custom cell. After I have the custom cell, I perform the animations on the objects. The problem is the animations aren't happening. When I try setting a property on one of the items in the cell, it doesn't work either. The custom cell is not returning nil so I'm not sure of the issue. What am I doing wrong?
Here is the code I'm using to call the animations
-(void)favButtonPressed:(id)sender{
FavoritesCell *favCell = (FavoritesCell *)[self tableView:self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:[sender tag] inSection:0]];
[UIView animateWithDuration:0.2 animations:^{
favCell.picButton.alpha = 0.5;
} completion:nil];
}
One way u can do it by using custom delegate like below, hope this helps u .
i took an example of your case go through this hope this helps u
in custom cell calss define delegate protocol like below
in FavoritesCell.h
#import <UIKit/UIKit.h>
#class FavoritesCell;
#protocol CellActionDelegate <NSObject>
- (void)doAnimationForCell:(FavoritesCell *)cell forButton:(UIButton *)picButton; //in this u can pass the cell itself
#end
#interface FavoritesCell : UITableViewCell
#property (nonatomic,retain)UIButton *picButton; //i am doing a simple test, say this is your pic button
#property (nonatomic,assign) id<CellActionDelegate>cellDelegate;
#end
and in FavoritesCell.m file
#import "FavoritesCell.h"
#implementation FavoritesCell
#synthesize cellDelegate;
#synthesize picButton = _picButton;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
_picButton = [[UIButton alloc]initWithFrame:CGRectMake(20, 3, 100, 100)];
//set the property // for test
[_picButton addTarget:self action:#selector(favButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[_picButton.layer setCornerRadius:50];
[_picButton.layer setMasksToBounds:YES];
[_picButton.layer setBorderColor:[[UIColor blackColor]CGColor]];
[_picButton.layer setBorderWidth:5];
_picButton.backgroundColor = [UIColor greenColor];
[self.contentView addSubview:_picButton];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)favButtonPressed:(UIButton *)sender
{
//or you can do the animation hear only no need to delegate to controller form cell
if([self.cellDelegate respondsToSelector:#selector(doAnimationForCell:forButton:)])
{
[self.cellDelegate doAnimationForCell:self forButton:sender]; //call this method
}
}
#end
in ViewController.h file
#import <UIKit/UIKit.h>
#import "FavoritesCell.h" //import it
#interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate,CellActionDelegate> //confirms to delegate
//.... other stuffs
in ViewController.m file
//...other stuffs
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
FavoritesCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CELL"];
if(cell == nil)
{
cell = [[FavoritesCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CELL"];
}
cell.cellDelegate = self; //set the deleagte to this class
[cell.picButton setImage:[UIImage imageNamed:#"Two-Red-Flower-.jpg"] forState:UIControlStateNormal]; //set it hear or in custom cell itself
//...other logics
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 130.0f;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
//define the delegate method
- (void)doAnimationForCell:(FavoritesCell *)cell forButton:(UIButton *)picButton //this the picButton
{
//you can get index path of cell
//you can get the tapped button of the cell
//then do your animation
[UIView animateWithDuration:0.2 animations:^{
picButton.alpha = 0.5;
} completion:nil];
}
I think you want something like this:
-(void)favButtonPressed:(id)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.myTableView];
// or try this one alternatively if the above line give wrong indexPath
//CGPoint buttonPosition = [sender convertPoint:((UIButton *)sender).center toView:self.myTableView];
NSIndexPath *indexPath = [self.myTableView indexPathForRowAtPoint:buttonPosition];
// I assume "self" here is your view controller
FavoritesCell *favCell = (FavoritesCell *)[self.myTableView cellForRowAtIndexPath:indexPath];
[UIView animateWithDuration:0.2 animations:^{
favCell.picButton.alpha = 0.5;
} completion:nil];
}

Enable and Disable UITableview scroll based on UITableview cell movement on dragging

I am creating one application based on FMMoveTableView where I have to drag cell on long press and change its position with in same section and different section.The cell is dragging fine and setting in the same and different section.But the problem is when I start dragging the cell upwards the table also starts scrolling up.So some of its cells are invisible because of bounce where we want to keep the dragged cell.The same thing is happening when I drag the cell to the bottom.
Is it anything related to UITableView property or I have to do it programmatically?
The app FMMoveTableView which I followed for this functionality,it is working fine where it is using UITableView class type.I implemented it in UIViewController class where I made some other views.
UITableView Properties:
self.GroupedTableView=[[UITableView alloc]initWithFrame:CGRectMake(20, 25, 280, 480) style:UITableViewStylePlain];
self.GroupedTableView.showsHorizontalScrollIndicator=YES;
self.GroupedTableView.showsVerticalScrollIndicator=YES;
self.GroupedTableView.bounces=YES;
self.GroupedTableView.alwaysBounceHorizontal=NO;
self.GroupedTableView.alwaysBounceVertical=YES;
self.GroupedTableView.bouncesZoom=YES;
self.GroupedTableView.delaysContentTouches=YES;
self.GroupedTableView.canCancelContentTouches=YES;
self.GroupedTableView.userInteractionEnabled=YES;
self.GroupedTableView.dataSource=self;
self.GroupedTableView.delegate=self;
self.GroupedTableView.rowHeight=30;
self.GroupedTableView.backgroundColor=[UIColor clearColor];
self.GroupedTableView.tag=202;
[self.view addSubview:self.GroupedTableView];
Long Press Gesture:
UILongPressGestureRecognizer *movingGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPress:)];
[movingGestureRecognizer setDelegate:self];
[self.GroupedTableView addGestureRecognizer:movingGestureRecognizer];
Auto Scroll Methods:
- (void)legalizeAutoscrollDistance
{
float minimumLegalDistance = [self.GroupedTableView contentOffset].y * -1;
float maximumLegalDistance = [self.GroupedTableView contentSize].height - ([self.GroupedTableView frame].size.height + [self.GroupedTableView contentOffset].y);
[self setAutoscrollDistance:MAX([self autoscrollDistance], minimumLegalDistance)];
[self setAutoscrollDistance:MIN([self autoscrollDistance], maximumLegalDistance)];
}
- (void)stopAutoscrolling
{
[self setAutoscrollDistance:0];
[[self autoscrollTimer] invalidate];
[self setAutoscrollTimer:nil];
}
- (void)maybeAutoscrollForSnapShotImageView:(FMSnapShotImageView *)snapShot
{
[self setAutoscrollDistance:0];
NSLog(#"Height====%f",[self.GroupedTableView frame].size.height);
NSLog(#"Height====%f",[self.GroupedTableView contentSize].height);
NSLog(#"Frame====%#",NSStringFromCGRect([snapShot frame]));
NSLog(#"Frame====%#",NSStringFromCGRect([self.GroupedTableView bounds]));
// Check for autoscrolling
// 1. The content size is bigger than the frame's
// 2. The snap shot is still inside the table view's bounds
if ([self.GroupedTableView frame].size.height < [self.GroupedTableView contentSize].height && CGRectIntersectsRect([snapShot frame], [self.GroupedTableView bounds]))
{
CGPoint touchLocation = [[self movingGestureRecognizer] locationInView:self.GroupedTableView];
touchLocation.y += [self touchOffset].y;
float distanceToTopEdge = touchLocation.y - CGRectGetMinY([self.GroupedTableView bounds]);
float distanceToBottomEdge = CGRectGetMaxY([self.GroupedTableView bounds]) - touchLocation.y;
if (distanceToTopEdge < [self autoscrollThreshold])
{
[self setAutoscrollDistance:[self autoscrollDistanceForProximityToEdge:distanceToTopEdge] * -1];
}
else if (distanceToBottomEdge < [self autoscrollThreshold])
{
[self setAutoscrollDistance:[self autoscrollDistanceForProximityToEdge:distanceToBottomEdge]];
}
}
if ([self autoscrollDistance] == 0)
{
[[self autoscrollTimer] invalidate];
[self setAutoscrollTimer:nil];
}
else if (![self autoscrollTimer])
{
NSTimer *autoscrollTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / 60.0) target:self selector:#selector(autoscrollTimerFired:) userInfo:snapShot repeats:YES];
[self setAutoscrollTimer:autoscrollTimer];
}
}
- (void)autoscrollTimerFired:(NSTimer *)timer
{
[self legalizeAutoscrollDistance];
CGPoint contentOffset = [self.GroupedTableView contentOffset];
contentOffset.y += [self autoscrollDistance];
[self.GroupedTableView setContentOffset:contentOffset];
// Move the snap shot appropriately
FMSnapShotImageView *snapShot = (FMSnapShotImageView *)[timer userInfo];
[snapShot moveByOffset:CGPointMake(0, [self autoscrollDistance])];
// Even if we autoscroll we need to update the moved cell's index path
CGPoint touchLocation = [[self movingGestureRecognizer] locationInView:self.GroupedTableView];
[self moveRowToLocation:touchLocation];
}
- (float)autoscrollDistanceForProximityToEdge:(float)proximity
{
return ceilf(([self autoscrollThreshold] - proximity) / 5.0);
}
I am unable to stop tableview scroll when I drag a cell.What I need that table should not move till the dragged cell has not reached to the top or bottom and then it should scroll to show hidden Cells.
// // ViewController.h // testingApp
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
UILongPressGestureRecognizer *reco; }
#property (nonatomic, weak) IBOutlet UITableView *table;
#end
//
// ViewController.m
// testingApp
#import "ViewController.h"
#implementation ViewController
#synthesize table;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
reco = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(recognize:)];
[self.table addGestureRecognizer:reco];
}
-(void)recognize:(id)sender
{
NSLog(#"recognize");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
return cell;
}
#end
I have got the solution.Actually I am using some gestures on my table view cell.So to enable this along with other gestures I was using:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
So this was actually activating the UITableView gestures too when it was not needed.And so When I dragged the cell Image my table also started scrolling along with the image.I misinterpreted it as my implementation for row sliding has got some issue.So code used in question works is fine if someone needs it in future.What I did is added some conditions in the above method and activated it when it was needed.

UIScrollview within UITableViewCell and maintaining scrollview page

I have a UIScrollView within a UITableViewCell for being able to scroll through images within a cell. However, as a cell is reused the scroll position/content is reloaded and therefore the cell doesn't remember what scroll position (page) it was on when it comes into view again.
What's the best way to have a scroll view within a UITableView cell and have it maintain position as it comes back into view. The AirBnB app (https://itunes.apple.com/us/app/airbnb/id401626263?mt=8) seems to have accomplished this for example.
You need to keep track of your scroll views' content offset in a property. In the example below, I do this with a mutable dictionary. In cellForRowAtIndexPath:, I give the scroll view a tag and set the controller as the delegate. In the scroll view delegate method, scrollViewDidEndDecelerating:, the scroll view's content offset is set as the object for the key corresponding to the scroll view's tag. In cellForRowAtIndexPath:, I check for whether the indexPath.row (converted to an NSNumber) is one of the keys of the dictionary, and if so, restore the correct offset for that scroll view. The reason I add 1 to the tags is because the table view has its own scroll view which has a tag of 0, so I don't want to use 0 as a tag for one of the cell's scroll views.
So in cellForRowAtIndexPath, you need something like this:
cell.scrollView.tag = indexPath.row + 1;
cell.scrollView.delegate = self;
if ([self.paths.allKeys containsObject:#(indexPath.row + 1)]) {
cell.scrollView.contentOffset = CGPointMake([self.paths[#(indexPath.row + 1)] floatValue],0);
}else{
cell.scrollView.contentOffset = CGPointZero;
}
return cell;
And in the delegate method:
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (scrollView.tag != 0)
[self.paths setObject:#(scrollView.contentOffset.x) forKey:#(scrollView.tag)];
}
paths is a property (NSMutableDictionary) that I create in viewDidLoad.
Use my tableView customs cells
homeScrollCell.h
#import <UIKit/UIKit.h>
#import "MyManager.h"
#interface homeScrollCell : UITableViewCell<UIScrollViewDelegate>
{
MyManager *manager;
UIScrollView *__scrollView;
}
-(void)setPage:(int)page;
#property int currentPage;
#end
homeScrollCell.m
#import "homeScrollCell.h"
#implementation homeScrollCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
manager=[MyManager sharedManager];
__scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width,self.bounds.size.height)];
[__scrollView setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
NSInteger viewcount= 3;
for(int i = 0; i< viewcount; i++)
{
CGFloat x = i * self.bounds.size.width;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(x, 0,self.bounds.size.width,self.bounds.size.height)];
[view setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
UILabel *label=[[UILabel alloc] initWithFrame:CGRectMake(50, 20, 200, 50)];
[label setBackgroundColor:[UIColor redColor]];
label.text=[NSString stringWithFormat:#"Hi, I am label %i",i];
[view addSubview:label];
view.backgroundColor = [UIColor greenColor];
[__scrollView addSubview:view];
}
[__scrollView setBackgroundColor:[UIColor redColor]];
__scrollView.contentSize = CGSizeMake(self.bounds.size.width *viewcount, 100);
__scrollView.pagingEnabled = YES;
__scrollView.bounces = NO;
__scrollView.delegate=self;
[self addSubview:__scrollView];
// Initialization code
}
return self;
}
-(void)setPage:(int)page
{
CGFloat pageWidth = __scrollView.frame.size.width;
float offset_X=pageWidth*page;
[__scrollView setContentOffset:CGPointMake(offset_X, __scrollView.contentOffset.y)];
_currentPage=page;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
static NSInteger previousPage = 0;
CGFloat pageWidth = scrollView.frame.size.width;
float fractionalPage = scrollView.contentOffset.x / pageWidth;
NSInteger page = lround(fractionalPage);
if (previousPage != page) {
_currentPage=page;
[manager setpage:_currentPage ForKey:[NSString stringWithFormat:#"%i",self.tag]];
previousPage = page;
}
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
And use a Singleton file for keeping record or pages inside cell.
MyManager.h
#import <Foundation/Foundation.h>
#interface MyManager : NSObject
+ (id)sharedManager;
-(void)setpage:(int)page ForKey:(NSString*)key;
-(int)getpageForKey:(NSString*)key;
#end
MyManager.m
#import "MyManager.h"
static NSMutableDictionary *dictionary;
#implementation MyManager
#pragma mark Singleton Methods
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
-(void)setpage:(int)page ForKey:(NSString*)key
{
[dictionary setValue:[NSString stringWithFormat:#"%i",page] forKey:key];
}
-(int)getpageForKey:(NSString*)key
{
return [[dictionary valueForKey:key] intValue];
}
- (id)init {
if (self = [super init]) {
dictionary=[[NSMutableDictionary alloc] init];
}
return self;
}
- (void)dealloc {
// Should never be called, but just here for clarity really.
}
#end
And use this custom cell in cellForRow as
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Home Scroll Cell";
homeScrollCell *cell =[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil) {
cell = [[homeScrollCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.tag=indexPath.row;
[cell setPage:[manager getpageForKey:[NSString stringWithFormat:#"%i",indexPath.row]]];
return cell;
}
Set your page inside CustomCell and scroll and after re scrolling get back to previous position will show you page set by you before scrolling.
It will persist your page moved as it is.
Download And Run
rdelmar's answer is missing something. scrollViewDidEndDecelerating will only be called if a users scroll triggers the deceleration behaviour.
A drag only scroll won't call this method so you will get inconsistent behaviour for the user who won't distinguish between the two types of scroll. You need to catch it with scrollViewDidEndDragging:willDecelerate
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate) {
self.tableCellContentOffsets[#(scrollView.tag)] = #(scrollView.contentOffset.x);
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
self.tableCellContentOffsets[#(scrollView.tag)] = #(scrollView.contentOffset.x);
}

UIButton inside UITableViewCell steals touch from UITableView

I have a problem similar to this one but answer provided there doesn't help much.
I have UITableView with some custom UITableViewCells, those cells have some nested custom UIViews and finally some UIButtons inside. The problem, as in question specified above, is that when I touch my button touch event won't populate to UITableView and it never scrolls.
Here's some code (it's just fastest way to reproduce, it's not my actual code):
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (strong, nonatomic) IBOutlet UITableView * tableView;
#end
#implementation ViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
{
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0,
self.view.bounds.size.width,
self.view.bounds.size.height)
style:UITableViewStylePlain];
[self.view addSubview:self.tableView];
self.tableView.delegate = self;
self.tableView.dataSource = self;
}
return self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell * cell = [[UITableViewCell alloc] init];
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
button.backgroundColor = [UIColor redColor];
button.frame = CGRectMake(0, 0, 50, 44);
[cell.contentView addSubview:button];
return cell;
}
#end
Red button in the only cell won't let table view to bounce scroll.
Can anyone help me a bit?
P.S. Don't pay attention to the stupidity of the code I've provided, I'm aware of all issues about it. I just provided it to show what the issue is all about. It's the conflict of buttonView and scrollView.
You can change the behaviour by overriding touchesShouldCancelInContentView: in the UITableView. For this to work you'll need to replace the table view with this subclass, either in loadView or in your xib file.
#interface AutoCancelTableView: UITableView
#end
#implementation AutoCancelTableView
//
// Overriding touchesShouldCanceInContentView changes the behaviour
// of button selection in a table view to act like cell selection -
// dragging while clicking a button will cancel the click and allow
// the scrolling to occur
//
- (BOOL)touchesShouldCancelInContentView:(UIView *)view {
return YES;
}
#end
This is the standard behaviour of UIScrollView which tableviews use. The system doesn't know that you want to scroll until you move your finger, but by that time you have already "pressed" on the button and so it assumes that's what you want to do.
You can play with a couple of properties on your tableview's scrollview to change the behaviour, but you may find they negatively impact the feel of your cells and buttons because of added delays.
self.tableView.delaysContentTouches = YES;
delaysContentTouches
If the value of this property is YES, the scroll view delays handling the touch-down gesture until it can determine if scrolling is the intent...
and
self.tableView.canCancelContentTouches = YES
canCancelContentTouches
If the value of this property is YES and a view in the content has begun tracking a finger touching it, and if the user drags the finger enough to initiate a scroll, the view receives a touchesCancelled:withEvent: message and the scroll view handles the touch as a scroll.
Because all the above answers not working for me. I add a imageView on the button and make the imageView user interface YES, then add a tap gesture on the iamgeView. In the tap gesture related methods I put the button related methods in. so all is well..
may be hack. But it work well..
Below code works for me:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
cell = [tableView dequeueReusableCellWithIdentifier:#"cell_id"];
cell.userInteractionEnabled = YES;
if (cell == nil) {
cell = [[[CustomCell1 alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell_id"]autorelease];
}
[cell.button addTarget:self action:#selector(button_action) forControlEvents:UIControlEventTouchUpInside];}
-(void)button_action{NSLog(#"Hello!");}
This is my custom cell:
#import "CustomCell.h"
#implementation CustomCell
#synthesize button;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
button = [[UIButton alloc]init];
button =[UIColor redColor];
[self.contentView addSubview: button];
}
return self;}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect contentRect = self.contentView.bounds;
CGFloat boundsX = contentRect.origin.x;
CGRect frame;
frame= CGRectMake(boundsX+50 ,+15, 100, 100);
button = frame;}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{ [super setSelected:selected animated:animated];
// Configure the view for the selected state
}

Resources