I have requirement to scroll the images horizontally and vertically.
I have sections which will segregated vertically and in each section itself it will be so many images which will be scrolled horizontally.
I made vertical scrolling using UICollectionView with Ray wenderlich tutorial but how do I get horizontal scrolling in each section?
Should I use any other object like UITableView or UIScrollview for this purpose?
Any tutorial available how to achieve this?
Is it compulsory to implement Layout subclass or UICollectionviewFlowlayout when using collection view?
EDIT
Till now I have implemented this code which scrolls vertically and has 5 sections each but not able to scroll the individual sections
- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section;
{
NSArray *arrayReturn = [self returnArray:section];
return arrayReturn.count;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 5;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
ImageCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"imagecell" forIndexPath:indexPath];
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSArray *arrSection = [NSArray arrayWithArray:[self returnArray:indexPath.section]];
NSString *fileName = [arrSection objectAtIndex:indexPath.row];
UIImage *image = [UIImage imageNamed:fileName];
dispatch_async(dispatch_get_main_queue(), ^{
// cell.imgVw.image = ;
if([CollectionView.indexPathsForVisibleItems containsObject:indexPath]){
ImageCell *currentCell = (ImageCell *) [cv cellForItemAtIndexPath:indexPath];
currentCell.imgVw.image = image;
}
});
}];
[self.thumbnailQueue addOperation:operation];
return cell;
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
HeaderView *Header = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"PhotoHeaderView" forIndexPath:indexPath];
Header.lblHeaderTitle.text = #"Header title";
Header.backgroundColor = [UIColor yellowColor];
return Header;
}
Here is a similar tutorial:
http://www.raywenderlich.com/4723/how-to-make-an-interface-with-horizontal-tables-like-the-pulse-news-app-part-2
Basically you need to do following:
Take a tableView or CollectionView
In each cell you need to add a scrollview with horizontal scrolling enabled.
Add items to scroll view of each cell while creating cells and give the scroll view appropriate content size.
It will give you a desired result.
Try this
**viewController.h**
IBOutlet UIScrollView *scrollViewMain;
**viewController.m**
- (void)viewDidLoad
{
[super viewDidLoad];
[self createDisplay];
// Do any additional setup after loading the view, typically from a nib.
}
-(void) createDisplay
{
for(UIView *subView in scrollViewMain.subviews)
{
if(![subView isKindOfClass:[UIImageView class]])
{
[subView removeFromSuperview];
}
}
int yPos =5;
for (int i=0; i< 10; i++)
{
int xPosition=5;
UIScrollView *scrollView =[[UIScrollView alloc]initWithFrame:CGRectMake(xPosition, yPos, scrollViewMain.frame.size.width, 100)];
scrollView.backgroundColor =[UIColor clearColor];
scrollView.autoresizingMask =UIViewAutoresizingFlexibleWidth;
xPosition +=5;
for (int j=0; j<10; j++)
{
UILabel *lblTitle = [[UILabel alloc] initWithFrame:CGRectMake(xPosition, 0, 100, 100)];
lblTitle.textColor = [UIColor whiteColor];
lblTitle.backgroundColor =[UIColor greenColor];
lblTitle.text = #"test";
lblTitle.numberOfLines =0;
lblTitle.font = [UIFont boldSystemFontOfSize:15];
[scrollView addSubview:lblTitle];
xPosition +=100;
xPosition +=10;
}
[scrollView setContentSize:CGSizeMake(xPosition, 100)];
[scrollViewMain addSubview:scrollView];
yPos +=120;
}
[scrollViewMain flashScrollIndicators];
[scrollViewMain setContentSize:CGSizeMake(0, yPos)];
}
Related
In my coding the table view will display but when i am scrolling the table view, it will completely scrolled. i have scrolled only table view cell. please any one help me. here is my code.
[super viewDidLoad];
scrollview=[[UIScrollView alloc]initWithFrame:CGRectMake(0,0,320,460)];
scrollview.showsVerticalScrollIndicator=NO;
scrollview.scrollEnabled=YES;
scrollview.userInteractionEnabled=YES;
[self.view addSubview:scrollview];
scrollview.contentSize = CGSizeMake(320,900);
[scrollview addSubview:recipePhoto];
[scrollview addSubview:detailLabel];
[scrollview addSubview:prizeLabel];
[scrollview addSubview:discountLabel];
[scrollview addSubview:saveLabel];
UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 480, 600, 400) style:UITableViewStylePlain];
[tableView setAutoresizesSubviews:YES];
[tableView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
tableView.scrollEnabled = NO;
tableView.backgroundColor=[UIColor clearColor];
[tableView setDataSource:self];
[tableView setDelegate:self];
[scrollview addSubview:tableView];
[tableView reloadData];
I don't see any problem in the code provided by you. You might want to check other parts of views or share more info here so that I can help you.
I added your code in my sample project and i was able to scroll to see the table view. Below is the code I used (almost same as yours, commented the labels)
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
UIScrollView *scrollview=[[UIScrollView alloc]initWithFrame:CGRectMake(0,0,320,460)];
scrollview.showsVerticalScrollIndicator=NO;
scrollview.scrollEnabled=YES;
scrollview.userInteractionEnabled=YES;
[self.view addSubview:scrollview];
scrollview.backgroundColor = [UIColor grayColor];
scrollview.contentSize = CGSizeMake(320,900);
// [scrollview addSubview:recipePhoto];
// [scrollview addSubview:detailLabel];
// [scrollview addSubview:prizeLabel];
// [scrollview addSubview:discountLabel];
// [scrollview addSubview:saveLabel];
UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 480, 600, 400) style:UITableViewStylePlain];
[tableView setAutoresizesSubviews:YES];
[tableView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
tableView.scrollEnabled = NO;
tableView.backgroundColor=[UIColor clearColor];
[tableView setDataSource:self];
[tableView setDelegate:self];
[scrollview addSubview:tableView];
[tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:#"cell %d", indexPath.row];
cell.backgroundColor = [UIColor blueColor];
return cell;
}
Here Two Way to complete that requirements are:
1.
just set contentSize of UIScrollView related to UITableView contentSize.height
just add this code after your above code
tableView.frame = CGRectMake(tableView.frame.origin.x, tableView.frame.origin.y, tableView.frame.size.width, tableView.contentSize.height);
float fscrview = tableView.frame.origin.y + tableView.contentSize.height + 20;
yourScrollView.contentSize=CGSizeMake(320, fscrview);
also set scrollEnabled = NO; to the tableView as you set in your code
and 2. When TableView is scrolled at that time set scrollEnabled = NO of UIScrollView.
I have a custom cell designed with a scrollview and a pageview control, which I am displaying as follows
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString * CellIdentifier = #"ScrollViewCell";
cell = (ScrollViewCell*)[newsTable dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray * customcellArray = [[NSBundle mainBundle]loadNibNamed:#"ScrollViewCell" owner:self options:nil];
for(id customcellObject in customcellArray){
if([customcellObject isKindOfClass: [UITableViewCell class]]){
cell = (ScrollViewCell *)customcellObject;
break;
}
}
}
// Customize your UIScrollView here..
[cell.scrollView setDelegate:self];
[cell.scrollView setPagingEnabled:YES];
scrollView = cell.scrollView;
pageControl = cell.pageControl;
cell.backgroundColor = [UIColor grayColor];
NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor],[UIColor blueColor], nil];
cell.scrollView.contentSize = CGSizeMake(cell.scrollView.frame.size.width * colors.count,cell.scrollView.frame.size.height);
for (int i = 0; i < colors.count; i++) {
CGRect frame;
frame.origin.x = cell.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = cell.scrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
subview.backgroundColor = [colors objectAtIndex:i];
[cell.scrollView addSubview:subview];
}
// Configure the cell...
UIView* bgview = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
bgview.opaque = YES;
bgview.backgroundColor = [UIColor grayColor];
[cell setBackgroundView:bgview];
return cell;
}
The scrollview appears and scrolls just fine in cell , but problem is page control doesnt update with the scroll, basically I want to update the page control on scroll of scrollview but since page control and scrollview both are from cell I am not getting how to achieve this, I tried implementing UIScrollViewDelegate protocol with cell and then the parent view of table view but couldnt get it working, pleas guide.
Thanks
Vishal
Don't place your UIPageControll over UIScrollview in your custom cell, if it is then it will get scroll along UIScrollView itself.So create your Custom cell like this and make outlet for each UIScrollview & UIPageControll,
One change in your cellForRowAtIndexPath
// Customize your UIScrollView here..
[cell.scrollView setDelegate:self];
[cell.scrollView setPagingEnabled:YES];
[cell.scrollView setTag:indexPath.row]; // set indexpath.row as tag for cell.scrollview
NSArray * colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor],[UIColor blueColor],nil];
cell.pageControll.numberOfPages = [colors count];
And in,
- (void)scrollViewDidScroll:(UIScrollView *)sender {
CGFloat xOffset = sender.contentOffset.x;
CGFloat frameWidth = sender.frame.size.width;
int page = floor((xOffset - frameWidth / 2) / frameWidth) + 1;
GroupButtonCell * cell = (GroupButtonCell*)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:sender.tag inSection:0]]; // get appropriate cell based on scrollview tag (sender.tag).
cell.pageControll.currentPage = page; // assigning to pagecontroll
}
Hope this will help..
I have made an UITableView and I am fetching data from JSON from a webservice.
Firat, I want that I get first 5 objects first and load them in my tableView. That is happening properly.
Then I want that whenever the user scrolls to the footer ..the next 5 objects should be fetched and it should be shown in tableView..
I am stuck here ..can anyone give me any idea how to proceed next?
My tableview has all custom cells loading from the custom classes for different types?
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
if(section==[array count]-1)
{
UITableViewCell *cell = [self tableView:mtableview1 cellForRowAtIndexPath:myIP];
frame = cell.contentView.frame;
footerView = [[UIView alloc] init];
footerView.backgroundColor=[UIColor clearColor];
self.activityIndicator = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray] autorelease];
self.activityIndicator.hidesWhenStopped=YES;
self.activityIndicator.center = CGPointMake(65,50);
[self.activityIndicator startAnimating];
UILabel* loadingLabel = [[UILabel alloc]init];
loadingLabel.font=[UIFont boldSystemFontOfSize:12.0f];
loadingLabel.textAlignment = UITextAlignmentLeft;
loadingLabel.textColor = [UIColor colorWithRed:87.0/255.0 green:108.0/255.0 blue:137.0/255.0 alpha:1.0];
loadingLabel.numberOfLines = 0;
loadingLabel.text=#"Loading.......";
loadingLabel.frame=CGRectMake(95,35, 302,25);
loadingLabel.backgroundColor =[UIColor clearColor];
loadingLabel.adjustsFontSizeToFitWidth = NO;
[footerView addSubview:self.activityIndicator];
[footerView addSubview:loadingLabel];
[self performSelector:#selector(loadending) withObject:nil afterDelay:1.0];
[loadingLabel release];
NSLog(#"%f",mtableview1.contentOffset.y);
mtableview1.tableFooterView=footerView;
return footerView;
}
return nil;
}
I have been doing it like this, but its position is not correct all the time. That's my big issue.
You can use the below concept.Concept is when user pull the table view then reload the additional data like pull to refresh.
Code Sample :
//MARK: -UIScrollViewDelegate
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
if (scrollView.contentOffset.y <= - 65.0f) {
// fetch extra data & reload table view
}
}
Use UIScrollViewDelegate Methods
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
}
in scrollViewDidScroll Method you can check row index for call you loading method
NSIndexPath *indexPath = [[self.myTable indexPathsForVisibleRows]objectAtIndex:1]; //in middle visible of row
int visibleRowIndex = indexPath.row;
I already implement this please look this here is my code
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
if(footerView == nil)
{
footerView = [[UIView alloc] init];
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (ObjApp.checkDevice == 1)
{
UIImage *image = [[UIImage imageNamed:#"LoadMoreBtn.png"]
stretchableImageWithLeftCapWidth:8 topCapHeight:8];
btnLoadMore = [UIButton buttonWithType:UIButtonTypeCustom];
[btnLoadMore setBackgroundImage:image forState:UIControlStateNormal];
if(screenBounds.size.height == 568)
{
// iPhone 5
[btnLoadMore setFrame:CGRectMake(74, 13, 148, 34)];
}
else
{
// iPohne 4 and Older iPhones
[btnLoadMore setFrame:CGRectMake(74, 13, 148, 34)];
}
}
else if (ObjApp.checkDevice == 2)
{
UIImage *image = [[UIImage imageNamed:#"LoadMoreBtn_iPad.png"]
stretchableImageWithLeftCapWidth:8 topCapHeight:8];
btnLoadMore = [UIButton buttonWithType:UIButtonTypeCustom];
[btnLoadMore setBackgroundImage:image forState:UIControlStateNormal];
[btnLoadMore setFrame:CGRectMake(220, 26, 296, 67)];
}
[btnLoadMore.titleLabel setFont:[UIFont boldSystemFontOfSize:20]];
[btnLoadMore setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[btnLoadMore addTarget:self action:#selector(btnLoadmore_clicked:)
forControlEvents:UIControlEventTouchUpInside];
[footerView addSubview:btnLoadMore];
}
return footerView;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
if (ObjApp.checkDevice == 1)
{
return 47;
}
else
{
return 100;
}
return 0;
}
#pragma mark - Button Click Methods
-(void)btnLoadmore_clicked:(id)sender
{
if(page > 0)
{
sendpage++;
if(sendpage<= page)
{
[self loading];
NSString *urlString = [NSString stringWithFormat:#"data={\"name\":\"%#\",\"lat\":\"%f\",\"page\":\"%d\",\"long\":\"%f\"}",txtSearchFld.text,ObjApp.current_Latitude,sendpage,ObjApp.current_Longitude];
[WebAPIRequest WS_Search:self :urlString];
CGFloat height = tblSearchResult.contentSize.height - tblSearchResult.bounds.size.height;
[tblSearchResult setContentOffset:CGPointMake(0, height) animated:YES];
}
}
}
You can increase Number of rows In table View when you reach to the last row check do you have more content to show or not. If u have MOre content to show then increase number of rows.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
After increasing number of row you can scroll to the desired row which you wann to show...
I'm trying to implement a UIScrollView in each cell of `UITableView'. I wrote my code based on Apple's custom Scrollview project: https://developer.apple.com/library/ios/#samplecode/Scrolling/Listings/ReadMe_txt.html
Each table cell's UIScrollView scrolls through a set of labels, which are initialized in the cellForRowAtIndexPath method. Each label's text is set after initialization to equal a string from an array.
Everything works correctly until I scroll down to the 4th table cell. The UIScrollView in this cell has the same exact labels as the first cell. The same first 3 set of labels or the first 3 scrollViews keep repeating after the first 3 cells. The strange part is, when I log the label.text after it is set, the output shows the correct label.text of what should be displaying in the respective cell.
- (void)layoutScrollLabels: (float)arrayCount
{
UIView *view = nil;
NSArray *subviews = [cell.popularLinkScrollView subviews];
// reposition all image subviews in a horizontal serial fashion
CGFloat curXLoc = 0;
for (view in subviews)
{
if ([view isKindOfClass:[UILabel class]] && view.tag >= 0)
{
CGRect frame = view.frame;
frame.origin = CGPointMake(curXLoc, 0);
view.frame = frame;
curXLoc += (kScrollObjWidth);
}
}
[cell.popularLinkScrollView setContentSize:CGSizeMake((arrayCount * kScrollObjWidth), [cell.popularLinkScrollView bounds].size.height)];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Custom Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *dictionary = [parseDataArray objectAtIndex:indexPath.row];
NSArray *popularLinkTitleArray = [dictionary objectForKey:#"popularLinkTitleArray"];
cell.popularLinkScrollView.clipsToBounds = YES;
kScrollObjHeight = cell.popularLinkScrollView.frame.size.height;
kScrollObjWidth = cell.popularLinkScrollView.frame.size.width;
NSUInteger i;
for (i = 0; i < popularLinkTitleArray.count; i++)
{
NSString *string = [NSString stringWithFormat:#"%#", [popularLinkTitleArray objectAtIndex: i]];
UILabel *label = [[UILabel alloc] init];
label.text = [NSString stringWithFormat:#"%#", string];
label.backgroundColor = [UIColor clearColor];
label.numberOfLines = 5;
NSLog(#"%#", label.text);
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = label.frame;
rect.size.height = kScrollObjHeight;
rect.size.width = kScrollObjWidth;
label.frame = rect;
label.tag = i; // tag our images for later use when we place them in serial fashion
[cell.popularLinkScrollView addSubview:label];
}
[self layoutScrollLabels:popularLinkTitleArray.count];
}
return cell;
}
You should not add label as a subview to popularLinkScrollView in cellForRowAtIndexPath. If the count of labels is required to be dynamic, try this code before your for loop in cellForRowAtIndexPath.
for (UIView* subView in cell.popularLinkScrollView.subviews)
[subView removeFromSuperview];
I am using the 'swipe to delete' functionality of the UITableView.
The problem is I am using a customised UITableViewCell which is created on a per item basis in
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
I need to alter the position of the delete button (simply to move it around 10px to the left), how would I go about doing this?
Here is my existing code for creating the cell:
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cellForRowAtIndexPath");
#if USE_CUSTOM_DRAWING
const NSInteger TOP_LABEL_TAG = 1001;
const NSInteger BOTTOM_LABEL_TAG = 1002;
UILabel *topLabel;
UILabel *bottomLabel;
#endif
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
//
// Create the cell.
//
cell =
[[[UITableViewCell alloc]
initWithFrame:CGRectZero
reuseIdentifier:CellIdentifier]
autorelease];
#if USE_CUSTOM_DRAWING
const CGFloat LABEL_HEIGHT = 20;
UIImage *image = [UIImage imageNamed:#"trans_clock.png"];
//
// Create the label for the top row of text
//
topLabel =
[[[UILabel alloc]
initWithFrame:
CGRectMake(
image.size.width + 2.0 * cell.indentationWidth,
0.5 * (aTableView.rowHeight - 2 * LABEL_HEIGHT),
aTableView.bounds.size.width -
image.size.width - 4.0 * cell.indentationWidth
,
LABEL_HEIGHT)]
autorelease];
[cell.contentView addSubview:topLabel];
//
// Configure the properties for the text that are the same on every row
//
topLabel.tag = TOP_LABEL_TAG;
topLabel.backgroundColor = [UIColor clearColor];
topLabel.textColor = fontColor;
topLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0];
topLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
//
// Create the label for the top row of text
//
bottomLabel =
[[[UILabel alloc]
initWithFrame:
CGRectMake(
image.size.width + 2.0 * cell.indentationWidth,
0.5 * (aTableView.rowHeight - 2 * LABEL_HEIGHT) + LABEL_HEIGHT,
aTableView.bounds.size.width -
image.size.width - 4.0 * cell.indentationWidth
,
LABEL_HEIGHT)]
autorelease];
[cell.contentView addSubview:bottomLabel];
//
// Configure the properties for the text that are the same on every row
//
bottomLabel.tag = BOTTOM_LABEL_TAG;
bottomLabel.backgroundColor = [UIColor clearColor];
bottomLabel.textColor = fontColor;
bottomLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0];
bottomLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize] - 2];
//
// Create a background image view.
//
cell.backgroundView =
[[[UIImageView alloc] init] autorelease];
cell.selectedBackgroundView =
[[[UIImageView alloc] init] autorelease];
#endif
}
#if USE_CUSTOM_DRAWING
else
{
topLabel = (UILabel *)[cell viewWithTag:TOP_LABEL_TAG];
bottomLabel = (UILabel *)[cell viewWithTag:BOTTOM_LABEL_TAG];
}
topLabel.text = #"Example Text";
topLabel.textColor = fontColor;
bottomLabel.text = #"More Example Text";
bottomLabel.textColor = fontColor;
//
// Set the background and selected background images for the text.
// Since we will round the corners at the top and bottom of sections, we
// need to conditionally choose the images based on the row index and the
// number of rows in the section.
//
UIImage *rowBackground;
UIImage *selectionBackground;
NSInteger sectionRows = [aTableView numberOfRowsInSection:[indexPath section]];
NSInteger row = [indexPath row];
if (row == 0 && row == sectionRows - 1)
{
rowBackground = [UIImage imageNamed:#"topAndBottomRow.png"];
selectionBackground = [UIImage imageNamed:#"topAndBottomRowSelected.png"];
}
else if (row == 0)
{
rowBackground = [UIImage imageNamed:#"topRow.png"];
selectionBackground = [UIImage imageNamed:#"topRowSelected.png"];
}
else if (row == sectionRows - 1)
{
rowBackground = [UIImage imageNamed:#"bottomRow.png"];
selectionBackground = [UIImage imageNamed:#"bottomRowSelected.png"];
}
else
{
rowBackground = [UIImage imageNamed:#"middleRow.png"];
selectionBackground = [UIImage imageNamed:#"middleRowSelected.png"];
}
((UIImageView *)cell.backgroundView).image = rowBackground;
((UIImageView *)cell.selectedBackgroundView).image = selectionBackground;
cell.imageView.image = [UIImage imageNamed:#"Example_Image.png"];
#else
cell.text = #"Example";
#endif
return cell;
}
For me the best way to solve this was overriding -(void)layoutSubviews in MyCell:UITableViewCell
Here you can see not only the Delete button custom position, but also repositioning the Edit and Reorder controls for Edit mode
- (void)layoutSubviews
{
[super layoutSubviews];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.0f];
for (UIView *subview in self.subviews) {
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"]) {
CGRect newFrame = subview.frame;
newFrame.origin.x = 200;
subview.frame = newFrame;
}
else if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellEditControl"]) {
CGRect newFrame = subview.frame;
newFrame.origin.x = 100;
subview.frame = newFrame;
}
else if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellReorderControl"]) {
CGRect newFrame = subview.frame;
newFrame.origin.x = 200;
subview.frame = newFrame;
}
}
[UIView commitAnimations];
}
Iwat's code doesn't work for me. But this works.
- (void)willTransitionToState:(UITableViewCellStateMask)state {
[super willTransitionToState:state];
if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableViewCellStateShowingDeleteConfirmationMask) {
for (UIView *subview in self.subviews) {
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"]) {
subview.hidden = YES;
subview.alpha = 0.0;
}
}
}
}
- (void)didTransitionToState:(UITableViewCellStateMask)state {
[super didTransitionToState:state];
if (state == UITableViewCellStateShowingDeleteConfirmationMask || state == UITableViewCellStateDefaultMask) {
for (UIView *subview in self.subviews) {
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"]) {
UIView *deleteButtonView = (UIView *)[subview.subviews objectAtIndex:0];
CGRect f = deleteButtonView.frame;
f.origin.x -= 20;
deleteButtonView.frame = f;
subview.hidden = NO;
[UIView beginAnimations:#"anim" context:nil];
subview.alpha = 1.0;
[UIView commitAnimations];
}
}
}
}
I haven't been able to change the actual look of the delete button, but you can change the text. Perhaps you can use this to get the effect you are looking for?
Check out the following member of the UITableViewDelegate protocol:
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
Additionally, you can detect when the delete button is being displayed by subclassing UITableViewCell and overriding the the following:
- (void)willTransitionToState:(UITableViewCellStateMask)state
- (void)didTransitionToState:(UITableViewCellStateMask)state
For either of these, the state mask will be UITableViewCellStateShowingDeleteConfirmationMask when the delete button is being displayed.
Hopefully these clues will point you in the right direction.
I use a solution that on first sight looks kind of hacky but does the trick and is not relying on undocumented apis:
/**
* Transition to state
*/
-(void)willTransitionToState:(UITableViewCellStateMask)state {
if(state & UITableViewCellStateShowingDeleteConfirmationMask)
_deleting = YES;
else if(!(state & UITableViewCellStateShowingDeleteConfirmationMask))
_deleting = NO;
[super willTransitionToState:state];
}
/**
* Reset cell transformations
*/
-(void)resetCellTransform {
self.transform = CGAffineTransformIdentity;
_background.transform = CGAffineTransformIdentity;
_content.transform = CGAffineTransformIdentity;
}
/**
* Move cell around if we are currently in delete mode
*/
-(void)updateWithCurrentState {
if(_deleting) {
float x = -20;
float y = 0;
self.transform = CGAffineTransformMakeTranslation(x, y);
_background.transform = CGAffineTransformMakeTranslation(-x, -y);
_content.transform = CGAffineTransformMakeTranslation(-x, -y);
}
}
-(void)setFrame:(CGRect)frame {
[self resetCellTransform];
[super setFrame:frame];
[self updateWithCurrentState];
}
-(void)layoutSubviews {
[self resetCellTransform];
[super layoutSubviews];
[self updateWithCurrentState];
}
Basically this shifts the cell position and readjusts the visible portions.
WillTransitionToState just sets an instance variable indicating whether the cell is in delete mode. Overriding setFrame was necessary to support rotating the phone to landscape and vice-versa.
Where _background is the background view of my cell and _content is a view added to the contentView of the cell, holding all labels etc.
I don't know of any way to "move the delete button 10px to the left". However, you can animate the custom contents of your table cell around the static position of the unmovable delete button by listening for the willTransitionToState: message from a UITableViewCell sub-class see here.
To quote the docs:
Subclasses of UITableViewCell can
implement this method to animate
additional changes to a cell when it
is changing state. UITableViewCell
calls this method whenever a cell
transitions between states, such as
from a normal state (the default) to
editing mode. The custom cell can set
up and position any new views that
appear with the new state. The cell
then receives a layoutSubviews message
(UIView) in which it can position
these new views in their final
locations for the new state.
Subclasses must always call super when
overriding this method.
What you are looking for is the UITableViewCellStateShowingDeleteConfirmationMask value. This is one of those times where creating UITableViewCell subclass might be better, so from the controller you are just creating an instance of your custom cell. Then the cell can just adjust itself like animateLeft and animateRight and handle the inner workings of adjusting its own subviews.
I don't know the final solution, but as far as I tried the following code might be useful.
// subclass UITableViewCell
- (void)willTransitionToState:(UITableViewCellStateMask)state
{
[super willTransitionToState:state];
if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableCellStateShowingDeleteConfirmationMask)
{
for (UIView *subview in self.subviews)
{
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"])
{
subview.hidden = YES;
subview.alpha = 0;
}
}
}
}
- (void)didTransitionToState:(UITableViewCellStateMask)state
{
[super willTransitionToState:state];
if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableCellStateShowingDeleteConfirmationMask)
{
for (UIView *subview in self.subviews)
{
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"])
{
subview.frame = CGRectMake(subview.frame.origin.x - 10, subview.frame.origin.y, subview.frame.size.width, subview.frame.size.height);
subview.hidden = NO;
[UIView beginAnimations:#"anim" context:nil];
subview.alpha = 1;
[UIView commitAnimations];
}
}
}
}