So i have a UITableview with 3 different tabs setup.
I want to scroll the table to a specific item.
If user added a new item, table to scroll all the way to the bottom because that's where the item will be added.
If user picks one of the items and edits it, it should come back to the same position on the table. Not scrolled to the top or bottom.
This is what I have:
This is a class variable.
NSIndexpath lastScrollY;
In my ViewWillDisappear :
lastScrollY = this.tableView.IndexPathForSelectedRow() ;
In my ViewWillAppear:
if(lastScrollY != null) {
this.tableView.ScrollToRow(lastScrollY, UITableViewScrollPosition.None, true);
}
this does not seem to work.
And that is only for when user selects a saved item.
What about when then add a new item/row to the table?
Please explain in detail as I am new to this.
Thank you for your time!
For after you add a new cell to your tableView, use the same method you did before, but change the scroll position (this code is in Objective-C, but does the same thing as yours. I'll try to help with a translation if you need one):
[tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionBottom
animated:true];
You might also want to set lastScrollY in an override of the method
(void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath
using the automatically passed in value indexPath to save to lastScrollY.
Lastly, I'm not sure if this will help, but in your current scrollToRow call, you have it scrolling to "none", try having it scroll to UITableViewScrollPositionTop instead. If that still doesn't work, try calling [tableView reloadData] at the end of your viewWillAppear method, which is probably something along the lines of tableView.reloadData() in your language.
Hope this helps!
Related
What I'm doing?
I'm adding dynamic views to my UITableViewCell (which isn't subclassed).
Cell Hierarchy :
UITableView > UITableViewCell > cell.contentView > MainView > ([Number Of PointView] + [Options View]).
Here it is:
When a user will tap "Add Another Point", I'll add a PointView (which will be same as above) :
Y position [ ] X position [ ]
which will be look like this,
What is my logic to get this done?
I'm taking MainView from cell.contentView.
Then fetch last two views (Point View & Options View) added into MainView.
Add Another PointView in MainView.
Update frames for newly added PointView based on last PointView and also update frame of OptionsView.
Resizing height of MainView
And reloading particular cell.
I'm able to get it work, to confirm I've logged frame and subviews for that MainView. But once I tap on "Add Another Point" button again, I found that MainView isn't updated at all?
My simple question is, if I have a MainView (which I fetch from a Cell), can I update it directly or not?
P.S. I already have a poor solution for this is, to remove MainView and recreate new – which I found unnecessary. Any thoughts?
Short answer, yes you can.
cell.contentView is a placeholder. What you are likely running into is an entirely different problem: UITableViewCells are cached, then recycled and reused by the system.
Anytime you respond to cellForRowAtIndexPath, you basically need to reset the content.
I think what you should do. Just make this one cell class
This one other cell subclass
Use this method to insert your rows and also update your data source for table view that is the number of rows in section part
Your + button on click method can be like this..
//Use your own logic what you want to do.
Update your data source
NSIndexPath* index=[NSIndexPath indexPathForRow:[table count]-1 inSection:0];
NSMutableArray* indexPathArray=[[NSMutableArray alloc]init];
[indexPathArray addObject:index];
//index will be your new added point cell. Updating your datasource
[_myTableView insertRowsAtIndexPaths:indexPathArray
withRowAnimation:UITableViewRowAnimationTop];
Make this YES
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return YES if you want the specified item to be editable.
return YES;
}
I have an iOS application where I am displaying a UITableView, which in turn is composed of custom rows that are made up of UITextFields, and UILabels. On first launch, I have a UIImageView that covers the UITableView until the user presses a button in order to dismiss the UIImageView (thus revealing the UITableView behind it).
However, my problem is that instead of returning control to the first row of the UITableView, it is selecting the last row of the UITableView, and on top of that, despite me making an explicit call to the method, "becomeFirstResponder", the UITextField in the last row of the UITableView does not allow me to enter text until I explicitly select a row from the table. Then and only then am I able to enter text. I am assuming that my method "cellForRowAtIndexPath" populates my table from the top down, which is why the last row of the table is being selected, and not the top (this is my guess, and if I am wrong please correct me).
What I would like to do is enable the very first row of the UITableView once the user dismisses the UIImageView AND have it become the "firstResponder" automatically, allowing the user to enter text right away without having to explicitly select a particular row.
My code that dismisses the UIImageView after pressing a button is here:
- (IBAction)beginDataEntry:(id)sender {
[_imageView removeFromSuperview];
[_cell.dataField becomeFirstResponder];
}
It is as if my UITableView is in a "limbo" state until I explicitly select a row from the table. What am I doing wrong?
Use UITableView scrollToRowAtIndexPath:atScrollPosition:animated: to display the correct row when the view is redisplayed.
It is always safer to use index paths to refer to table rows rather than keeping references to cells. So, here's an alternative:
- (IBAction)beginTireCountEntry:(id)sender {
[_imageView removeFromSuperview];
NSIndexPath firstCellPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView scrollToRowAtIndexPath: firstCellPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
MyCell cell = (MyCell *)[self.tableView cellForRowAtIndexPath:firstCellPath];
[cell.dataField becomeFirstResponder];
}
I have a UITableView with over 50 rows but only 5 are shown at a time. How can I force the middle row to always be selected? For example 2,3,4,5,6 are shown, 4 will be selected.
The user scrolls -> 14,15,16,17,18 , 16 will be selected etc'.
Thanks
This method worked pretty well for me. I had a table view that showed 5 rows at a time, but when I log visibleRows, I always got a count of 7, so I get the index paths for those seven, and select the middle one (index 3):
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSArray *vis = self.tableView.indexPathsForVisibleRows;
if (vis.count %2 == 1) {
[self.tableView selectRowAtIndexPath:vis[3] animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}
Use the tableView:willDisplayCell:forRowAtIndexPath: method that is part of the UITableViewDelegate protocol.
In here you can check the indexPath.row value, and if it is within your specified range, use cell.selected.
Further information:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html
Although I recommend you maintain whether or not a cell should be selected within your datasource, rather than hooking into the position of a cell, this way you can check your datasource if a cell should be selected rather than forcing yourself to use a particular index cell for a particular thing.
Hope this helps.
Purpose is UIPickerView custom i think,
Take a look here and this question will help you
I'd like to launch my "add item" form in response to touching an empty cell (the next blank cell), sort of like the stock "Reminders" app. didSelectRowAtIndexPath doesn't work for this and I don't have a clue what does.
Thanks
add a button to the tableFooterView
https://developer.apple.com/library/IOs/#documentation/UIKit/Reference/UITableView_Class/Reference/Reference.html
You could add a tap gesture recognizer to the table view, but be sure to test if the user tapped a table view cell or not.
If you wanna the last cell of your table view to be an add button so that you can add a cell directly without putting the table view in edit mode, then here is what you can do:
For the array you use to populate the table view, always make sure the last cell is a dummy object you use to add a row only.
in your -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath, make sure check whether indexPath.row is equal to [array count], if that's the same, then
insert whatever the object you create to your array at index = [array count]-1.
Call your [tableview reload] method. Then you will see the cell append to the table view.
Hope this helps.
I have a UITableview cell that gets a tally from a core data database. The tallyTable is in a view controller inside a UITab view. I have an NSLog statement that prints out the tally value whenever it gets updated. Another tab has a list to change the source (different day) for the tallies. I am using iOS5 with ARC targeting iOS 4.2.
Here's the problem. When I load the application, the correct tallies for whatever the last selected day show up in the table tab. If I then go to the day tab and change the day and return to the tally tab there is no change in the display. However, the viewWillAppear on the tally tab runs and as the table cycles through cellForIndexPath, my NSLog statement prints out all the correct new values. If I then scroll the top label off the screen and back the label updates to the new value.
I've tried setNeedsLayout and setNeedsDisplay on the UILabel, the UITableViewCell, the UITableView and the view controller loading the table. I tried changing the CellReuse identifier so that it would never reuse a cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CollectionItemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CollectionItemTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.collectionKeys objectAtIndex:row] valueForKey:#"collectionTitle"];
NSInteger test1 = indexPath.row + 150;
NSLog(#"tag = %i", test1);
cell.tallyButton.tag = test1;
NSNumber * questionID = [[self.collectionKeys objectAtIndex:row] valueForKey:#"answerID"];
cell.tallyLabel.text = [NSString stringWithFormat:#"%i",[self updatePointTotal:questionID]];
NSLog(#"Collection text should be = %#", [NSString stringWithFormat:#"%i",[self updatePointTotal:questionID]]);
[cell setNeedsLayout];
return cell;
}
I've read over a half dozen other similar questions. Got about three hours invested so far in trying to solve this.
EDIT: I thought I fixed it by using the navigation controller to repush the top level view controller on to the view again. I'll admit now this feels like a classically kludgy hack in every way. When the view is PUSHED everything updates and it is seamless. However, in order to have a fixed footer to make selection settings for the table buttons, I used a UIView with two subviews, a UITableView on top and a simple UIView with four buttons below.
The captions on the buttons need to change with the data source. Now when the view controller is pushed onto the view it obscures my fixed footer view. So, I inserted the fixed footer into the UITableview and everything appeared fine until I scrolled the UITableView and the footer scrolled up with it. The table is basically a tally sheet with buttons next to each item and in the footer is four buttons to note the color of the tallied item. Say the next item was a green lego, you would tap "green" in the footer and the button next to "lego" in the table. When I push the view controller with the two subviews the UITableview labels do not update. Thus the tableview needs to be pushed itself (as far as I can tell).
ANSWER: see comment below but ultimately I needed to reload both the visible UITableView data and the delegate UITableView controller data behind it.
I'll give it a shot. First, are you using ARC? If not, you need to add autorelease when you alloc/init a new cell. Otherwise, it's fine as is.
If I'm understanding your question correctly:
The tableView displays the correct data at app launch
You switch away from the tab with the tableView and change the tableView dataSource
You switch back to the tab with the tableView and you see (via NSLog) that the table cells are reloaded with the correct data yet the old data is still visible in the cells
If you scroll a cell off the display and back forcing it to refresh it contains the correct data
Some thoughts:
the tableView will not reload itself automatically when it's view appears. You need to call [tableView reloadData] whenever the dataSource changes. This is independent of whether the tableView is currently displayed or not. My guess is this alone will solve your problem.
You don't need to call setNeedsLayout on the cell unless you want the cell to relayout its subviews based on the data. You also don't need setNeedsDisplay.
I'm assuming there aren't other complicating factors (such as multiple tableViews displaying the same data) that could confuse things.
If you use prepare for reuse method, remember to over the original method with [super prepareForReuse];
Another method if the above way does not work is re setup cell as describe here.
I use the same method i applied for some of my collection view : we should remove/reset your subview where you create/add it to cell 's content. That mean we need set up data each cell completely for each row.
I move the code reset data value from prepare reuse to where i set value and I worked simply !
In my CustomCell.m :
- (void)configCellWith:(id)item At:(NSUInteger)row {
if (_scrollView) {
[[_scrollView subviews]
makeObjectsPerformSelector:#selector(removeFromSuperview)];
_scrollView = nil;
[_scrollView removeFromSuperview];
}
else {
CGFloat y = labelHeight+15;
float scrollHeight = _imgArray.count*200;
_scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(10, y,SCREEN_WIDTH-20, scrollHeight)];
_scrollView.scrollEnabled=YES;
_scrollView.userInteractionEnabled=YES;
_scrollView.layer.masksToBounds = YES;
[self.contentView addSubview:_scrollView]; } }
Remember to change your data source appropriately too.