Is that possible to use UIPageControl to control the move of UITableView? - ios

From Apple sample "PageControl" we can know that UIPageControl can be used to control movement of pages in scrollview.
As UITableView is subclass of UIScrollView,I want to use UIPageControl to control the movement of table view cell just like in "PageControl".
But can not find any interface of delegate for me to do that.
Question is :
Is that possible to do this ? And Why ?
Thanks
Let me answer my question with :
Programmatically Selecting and Scrolling
Listing 6-5 Programmatically selecting a row
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)newIndexPath {
NSIndexPath *scrollIndexPath;
if (newIndexPath.row + 20 < [timeZoneNames count]) {
scrollIndexPath = [NSIndexPath indexPathForRow:newIndexPath.row+20 inSection:newIndexPath.section];
} else {
scrollIndexPath = [NSIndexPath indexPathForRow:newIndexPath.row-20 inSection:newIndexPath.section];
}
[theTableView selectRowAtIndexPath:scrollIndexPath animated:YES
scrollPosition:UITableViewScrollPositionMiddle];
}

It sure is possible, but why would you want this? A table view scrolls vertically, while a page control has a horizontal layout, so it would probably look/feel weird.
Anyway, if you really want to do this, add your view controller as a target of the page control:
[pageControl addTarget:self action:#selector(pageChanged:) forControlEvents:UIControlEventValueChanged];
Then implement the scrolling in the action:
- (void)pageChanged:(UIPageControl *)sender {
float scrollPosition = ((float)sender.currentPage / (float)sender.numberOfPages) * tableView.contentSize.height;
[tableView scrollRectToVisible:CGRectMake(0, scrollPosition, 1, 1) animated:YES];
}

Related

Scroll one cell at a time in collection View

Using the willDisplayCell method I got the index of the last visible cell:
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
indexVisibleCell = [indexPath indexAtPosition:[indexPath length] - 1];
}
where indexVisibleCell is an NSUInteger that is declared in the class' interface. My problem is that I want to shift only one cell when user taps on the right or left button. I have applied this code for that purpose:
- (IBAction)rightButton:(id)sender {
NSUInteger indexOfScrolledCell;
indexOfScrolledCell = indexVisibleCell;
if (indexVisibleCell < 9) {
NSIndexPath *path = [NSIndexPath indexPathForRow:indexOfScrolledCell+1 inSection:0];
[self.obj_CollectionView1 scrollToItemAtIndexPath:path atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];
}
}
as I show 3 cells at a time. By using that rightButton action method it shifts 3 cells at a time, not one. Please help me figure out how to scroll one cell at time.
Try using UICollectionView with paging enabled. Use following code, hopefully it works out for you.
[yourCollectionView setPagingEnabled:YES];
Use visibleCells to get your visible Cells, get the leftmost Cell index to figure out the next index, then scroll to that Cell on the left (similar logic to your code).
willDisplayCell is not reliable since it is called both times when you scroll left/right, and you're thinking that index is the left/right most is not correct.
Edit:
Or you need to compare the index in willDisplayCell correctly, to get the correct left/right most index, based on your logic.
For right button you can use following
[self.obj_CollectionView1 scrollToItemAtIndexPath:path atScrollPosition:UICollectionViewScrollPositionRight animated:YES];
and for left button following
[self.obj_CollectionView1 scrollToItemAtIndexPath:path atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];
I am changing UICollectionViewScrollPosition so that when you scroll to right new item shows up on right side of collection view and when you scroll to left new item shows on left side of collection view.

XCode iOS7 - Dynamic cell with UITextView like Reminder App

I need to create an application that have the same behavior as built-in Reminder App. There are some problems to create this:
Cells that have dynamic height and "grow" as the content of the UITextView
Select the touched cell
Refresh the height of the cell when the user has edited the content(on the fly)
I've already solved the dynamic height, using some trick.
The problem that remains is:
How to know which cell the user has selected if the cell is "fully" with the UITextView ?
Right Now i've used the method textViewDidBeginEditing to know the cell and scroll the UITableView to it:
- (void)textViewDidBeginEditing:(UITextView*)textView
{
MemoViewCell* cell = (MemoViewCell *)[self parentCellFor:textView];
if (cell)
{
NSIndexPath* indexPath = [self.tableView indexPathForCell:cell];
currentIndexPath = indexPath;
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
}
- (UITableViewCell*)parentCellFor:(UIView*)view
{
if (!view)
return nil;
if ([view isMemberOfClass:[MemoViewCell class]])
return (UITableViewCell*)view;
return [self parentCellFor:view.superview];
}
How to refresh the cell height without lost the focus?
To this, i've used this method:
-(void)textViewDidChange:(UITextView *)textView
{
NSMutableDictionary *dataSourceItem = [self.model.dataSource objectAtIndex:currentIndexPath.row];
[dataSourceItem setObject:textView.text forKeyedSubscript:#"body"];
[self.model.dataSource setObject:dataSourceItem atIndexedSubscript:currentIndexPath.row];
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
When the text change, i get the new text, i change it in the Model and i call beginUpdated and endUpdates.
Sure, this works, but all is extremly slow... do you have some idea to to this in a more elegant way and maybe... efficient?
If i call reloadRowsAtIndexPaths: i lost the focus on the cell.
First of all, if you use the delegate method - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; in your dynamic height trick, remember to implement this method along - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath;, it helps a lot in terms of performance.
Then to focus on your specific project, if I correctly understood your goal, what you really want is to update the layout of your table view only when your text view is modified. Currently you're updating it at each text change. You might consider using a condition inside -(void)textViewDidChange:(UITextView *)textView, such as :
if ([textView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height !=
textView.frame.size.height) {
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
The condition given as example will work only if your existing cell layout respects the intrinsic content size of the text view, otherwise you will need to adapt the condition.

Scroll tableview cell directly beneath the navigation bar?

I have a tableview. On tap, a cell expands into a form, and I would like the cell to scroll up to start right below the navigation bar. How do I achieve this?
Here's the starting state:
Currently, after tap:
And here's what I want:
You need something like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Perform cell change height code here
// ...
// After that scroll to this cell
CGFloat sectionHeaderHeight = [self tableView:tableView heightForHeaderInSection:indexPath.section];
CGRect cellFrame = [tableView rectForRowAtIndexPath:indexPath];
[tableView setContentOffset:CGPointMake(0, cellFrame.origin.y - sectionHeaderHeight) animated:YES];
}
scrollToRowAtIndexPath... or scrollToNearestSelectedRow... both take "scroll position" arguments which allow the selection to go to the top, middle or bottom of the table view. That should give you what you want.

Pop UITableViewCell subview over entire screen

I have a tableView, with a UIWebView in each row.
When the webView is tapped, I'd like for it to just expand and take over the entire screen.
However, there a few problems, and I'm not sure which is interfering. First I tried something like this:
webView.frame = self.view.bounds;
webview.bounds = self.view.bounds;
cell.clipsToBounds = NO;
webView.clipsToBounds = NO;
However, the webView seems to have trouble overtaking the cell, doesn't expand to proper width and generally doesn't work. I also thought about manipulating the cell height, but it seems to be more trouble than it should be.
So basically, I'd like to move this webView to the top of the stack and change its frame size.
Otherwise I may just instantiate a new webView which seems like a waste. Any ideas? Thanks
Don't change the frame of the web view. Have the web view tied to all four sides of the cell using constraints (or at least the top and bottom), and when you tap on the cell, and it gets selected, use the indexPathForSelectedRow property in heightForRowAtIndexPath to make that cell as big as the table view.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([[tableView indexPathForSelectedRow] isEqual:indexPath]) {
return tableView.frame.size.height;
}else{
return 44;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
I don't know why you would put a WebView in a cell.. I'm no expert but wouldn't the webview be recreated everytime you scroll?
You could use SVWebViewController and place the following code in your didselectrowatindexpath to present it modally.
SVModalWebViewController *webViewController = [[SVModalWebViewController alloc] initWithAddress:#"http://google.com"];
[self presentViewController:webViewController animated:YES completion:NULL];

Identifying the table cell, when tapping on a Tap Recogniser

I have a tableview in my View. The cells are created using custom Cells. I need to display a large string in the table view cells So I had added the text Label in a Scrollview. Also I need to execute some code when the user taps on table view cell. Please see the below code:
[cell.textLabelLine2 setFrame:CGRectMake(cell.textLabelLine2.frame.origin.x, cell.textLabelLine2.frame.origin.y, 500, cell.textLabelLine2.frame.size.height)];
cell.scrollView.contentSize = CGSizeMake(cell.textLabelLine2.text.length*10 , 10);
cell.scrollView.pagingEnabled = NO;
The problem is when the user touches above the Scroll View, the Tableview did select method will not be called. The solution I found for this problem is to add a gesture recogniser to the scroll view. But in this solution, we have no ways to check which cell(or which gesture recogniser) was selected. Could anyone help me to find a solution for this problem?
You can get to know the cell by the following code
if(gestureRecognizer.state == UIGestureRecognizerStateBegan) {
CGPoint p = [gestureRecognizer locationInView:[self tableView]];
NSIndexPath *indexPath = [[self tableView] indexPathForRowAtPoint:p];
if(indexPath != nil) {
UITableViewCell *cell = [[self tableView] cellForRowAtIndexPath:indexPath];
...
}
}
It's generally a bad idea putting scroll views inside scroll views. UITableView is also just a UIScrollView. That only kind of works if they are scrolling on different axis, i.e. the outer scroll view scrolling vertically and the inner scrolling horizontally.
For your specific scenario you would have to trigger the selection yourself. Once you have a reference to the cell you can ask the table view for the indexPath of it. Then you would call the delegate method for didSelectRow... yourself.
In the solution with the scrollview you are not able to scroll in the scrollview because the gestureRecognizer 'gets' the touch. Therefor I would not use the scrollview at all.
Make the label resize to its content like:
CGSize customTextLabelSize = [cell.customTextLabel.text sizeWithFont:cell.customTextLabel.font constrainedToSize:CGSizeMake(cell.customTextLabel.frame.size.width, 999999)];
cell.customTextLabel.frame = CGRectMake(cell.customTextLabel.frame.origin.x, cell.customTextLabel.frame.origin.y, cell.customTextLabel.frame.size.width, customTextLabelSize.height);
You also need to implement this in the heightForRowAtIndexPath
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
CGSize cellSize = [bigTextString sizeWithFont:customTextLabel.font constrainedToSize:CGSizeMake(generalCellWidth, 999999)];
return cellSize.height;
}
This way you can just use the didSelectRowAtIndex method.
If you really want to use the scrollview, add a button to your cell in the cellForRowAtIndexPath: method. Make the button just as big as the cell and add a button tag like this:
UIButton *cellButton = [UIButton buttonWithType:UIButtonTypeCustom];
cellButton.frame = CGRectMake(0, 0, cell.frame.size.width, cell.frame.size.height);
cellButton.tag = indexPath.row;
[cellButton addTarget:self action:#selector(cellButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:cellButton];
Then add:
-(void)cellButtonAction:(UIButton*)sender
{
//do something with sender.tag
}

Resources