How to Unexpand an expanded UITableView Cell? - ios

I'm expanding my cell via:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if(selectedRow && indexPath.row == selectedRow.row) {
tableView.scrollEnabled = NO;
return 480;
}
return 250;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedRow = indexPath;
[tableView beginUpdates];
[tableView endUpdates];
CGFloat height = 250.0f;//cell height
tableView.contentInset = UIEdgeInsetsMake(0, 0, height * indexPath.row, 0);
[tableView setContentOffset:CGPointMake(0, (indexPath.row * height) )animated:YES];
}
It works fine, whenever I select a cell, it do expands, but I couldn't figure out how to bring it back to its original height. Any thoughts?

Try this
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if(selectedRow && indexPath.row == selectedRow.row) {
tableView.scrollEnabled = NO;
return 480;
}
tableView.scrollEnabled = YES;
return 250;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat height = 250.0f;
if (selectedRow && indexPath.row == selectedRow.row) {
NSIndexPath *index = [NSIndexPath indexPathForRow:selectedRow.row inSection:selectedRow.section];
selectedRow = nil;
[tableView reloadRowsAtIndexPaths:#[index] withRowAnimation:UITableViewRowAnimationNone];
tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
[tableView setContentOffset:CGPointMake(0, 0 )animated:NO];
} else {
selectedRow = indexPath;
[tableView beginUpdates];
[tableView endUpdates];
tableView.contentInset = UIEdgeInsetsMake(0, 0, height * indexPath.row, 0);
[tableView setContentOffset:CGPointMake(0, (indexPath.row * height) )animated:NO];
}
}

Try This :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(selectedRow.row == indexPath.row)
selectedRow = nil;
else
selectedRow = indexPath;
[tableView beginUpdates];
[tableView endUpdates];
[tableView reloadData];
}

I would suggest you to add a custom property like isExpanded in your tableView datasource object and switch that property based on selection and return height according to this value.
For ex: In your heightForRowAtIndexPath method, you could have somthing like this.
if(yourCustomCell.isExpanded == true){
return 480;
}
else{
return 250;
}
In didSelectRowAtIndexPath method, just set or unset this property.
yourCustomCell.isExpanded = !yourCustomCell.isExpanded
[tableView reloadData]; //Which will call heightForRow and then assign new height based on the property value.
Now if you dont have a custom cell object, then I think you can make use of cell's isSelected property.
I haven't tried these, but I guess this should work.

Related

reloadRowsAtIndexPaths cannot reload index path as expected

I add a image as avatar at indexPath [0,0], and use detailLabel display nickname at indexPath [0,1].
When use reloadRowsAtIndexPaths indexPath the indexPath [0,1] get a image...
I find when invoke reloadRowsAtIndexPaths the dequeue cell return nil.
Maybe the [0,0] cell be reuse at [0,1], I don't know why so that.
The code is:
- (void)viewDidLoad {
[super viewDidLoad];
_titles = #[#"Avator", #"Nickname"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kDelayTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
_avator = [UIImage imageNamed:#"cat"];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kDelayTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
_nickName = #"Smallfly";
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:1 inSection:0];
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
});
});
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _titles.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *const cellIdenfier = #"cellIdentifier";
// Why reloadRowsAtIndexPaths [0,0] returned cell is nil?
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdenfier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdenfier];
}
if (indexPath.row == 0) {
[self configureCell:cell indexPath:indexPath];
} else {
NSString *nickName = _nickName ?: #"nickname";
cell.detailTextLabel.text = nickName;
}
cell.textLabel.text = _titles[indexPath.row];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath {
for (UIView *sv in cell.contentView.subviews) {
if ([sv isKindOfClass:[UIImageView class]]) {
[sv removeFromSuperview];
}
}
UIImage *avator = _avator ?: [UIImage imageNamed:#"user_profile_avatar"];
UIImageView *avatorImageView = [[UIImageView alloc] initWithImage:avator];
...
[cell.contentView addSubview:avatorImageView];
}
reloadRowsAtIndexPaths is a void method.
dequeueReusableCell always returns a cell (remove UITableViewCell alloc)
Objective-C
- (void)reloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
withRowAnimation:(UITableViewRowAnimation)animation
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:#"reuseIdentifier"
forIndexPath:indexPath];
// Configure the cell...
return cell;
}
Swift 3
open func reloadRows(at indexPaths: [IndexPath],
with animation: UITableViewRowAnimation)
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell =
tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier",
for: indexPath)
// Configure the cell...
return cell
}
You may want to look at a more recent tutorial or sample code.

Loading cell in table view from xib bug

I am loading cell from xib. But then table view controller opens the cell is white. And showing the labes and other stuff only after click on cell.
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.tableView registerNib:[UINib nibWithNibName:#"FixedCell" bundle:nil] forCellReuseIdentifier:#"FixedCell"];
}
//cellForRow......
if(indexPath.section==1){
if(indexPath.row==0){
FixedCell *cell = [tableView dequeueReusableCellWithIdentifier:#"FixedCell"];
return cell;
}
}
Can anybody find it, what is wrong here?
Use this code it may help...
-(void)tableView:(UITableView *) willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
FixedCell *newCell = (FixedCell *)cell;
[newCell layoutIfNeeded];
}
Instead of loading the UINib inside UITableView just load it in viewDidLoad method..
Use this approach
UINib *nib = [UINib nibWithNibName:#"FixedCell" bundle:nil];
[self.tablView registerNib:nib forCellReuseIdentifier:#"FixedCell"];
Objective C
try this one...
cell =(FixedCell *)[tableView dequeueReusableCellWithIdentifier:#"FixedCell" forIndexPath:indexPath];
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));
[cell layoutIfNeeded];
CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return size.height;
}
Swift:
var cell: FixedCell! = tableView.dequeueReusableCellWithIdentifier("FixedCell", forIndexPath: indexPath) as! HistoryTableViewCell
if (cell == nil) {
cell = FixedCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "FixedCell")
}

I am having a tableview with multiple cell in it and in each cell having tableview, collectionview, tableview, like that

How to handle didSelectRowAtIndexPath so that it works on all the three different cell for each cell in it?
Preview
Flow of my code
- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"Traffic" ])
{
if(!TrafficCell)
{
TrafficCell = [tableView dequeueReusableCellWithIdentifier:#"CollectionVIewTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
TrafficCell.Traffic = [dict valueForKey:#"detail"];
[TrafficCell.collectionView reloadData];
return TrafficCell;
}
return TrafficCell;
}
else if([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"News"])
{
if(!NewsCell)
{
NewsTableViewCell *cell = (NewsTableViewCell*)[tableView dequeueReusableCellWithIdentifier:#"NewsTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
cell.News = [dict valueForKey:#"detail"];
[cell.NewsTableView reloadData];
return cell;
}
return NewsCell;
}
else
{
if(!CategoryCell)
{
CategoryCell= [tableView dequeueReusableCellWithIdentifier:#"CategoryTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
CategoryCell.Category = [dict valueForKey:#"detail"];
[CategoryCell.CategorycollectionView reloadData];
return CategoryCell;
}
return CategoryCell;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
You can handle tap on UITableViewCell the same as you implement in cellForRowAtIndexPath method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *dict = dataArray[indexPath.row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath: indexPath];
if([dict[#"type"] isEqual:#"Traffic" ]){
//Find your collectionView in cell
//Tap on Traffic cells
}
else if([dict[#"type"] isEqual:#"News"]){
//Tap on News cells
}
else {
//Tap on other cells
}
}
And in cellForRowAtIndexPath you need
TrafficCell.collectionView.delegate = self;
CategoryCell.CategorycollectionView.delegate = self;
for handle tap on UICollectionViewCell and implement UICollectionViewDelegate method
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
//Tapped on your collectionViewCell inside the uitableviewcell
}

UITableView cell allocate mark when checked...it would checked automatically when scrolling tblview

When i select index 0 or 1 or any else that same time it also selected index according to above index
i need solution
there are many rows and when i select cell 1 same time another cell selected automatically..
#property (nonatomic, retain) NSIndexPath * checkedIndexPath;
in ViewDidLoad
self.checkedIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];//Default 1st row will be checkMarked
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kSimpleCell];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kSimpleCell]autorelease];
}
if (self.checkedIndexPath== indexPath)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *currentcell = [tableView cellForRowAtIndexPath:self.checkedIndexPath];
currentcell.accessoryType = UITableViewCellAccessoryNone;
self.checkedIndexPath = indexPath;
UITableViewCell *currentcell = [tableView cellForRowAtIndexPath:self.checkedIndexPath];
currentcell.accessoryType = UITableViewCellAccessoryCheckmark;
}

Multiple UITableview in Single Viewcontroller

I have a viewcontroller in that i want to show 3 tableviews(because the content and the table properties are different). How do i add these delegate methodes for 3 tables in one viewcontroller?
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [array1 count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {}
EDIT
So what will i do if i want add a uislider to one table row using custom cell and when i slide the value i want to change the display brightness?
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (tableView == _displayThemes) {
return 1;
} else {
return 1;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(tableView==_displayThemes) {
return 1;
} else {
return 5;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (tableView == _displayThemes) {
cell.textLabel.text = [displaytheme objectAtIndex:indexPath.row];
return cell;
} else {
cell.textLabel.text = [fontlist objectAtIndex:indexPath.row];
return cell;
}
}
- (IBAction)fontButton:(id)sender {
_fontList = [[UITableView alloc]init];
[self.view addSubview:_fontList];
[UIView animateWithDuration:1.5
delay:0
options: UIViewAnimationOptionTransitionCurlUp
animations:^{
_fontList.fram e= CGRectMake(0,800,320,200);
}
completion:^(BOOL finished){
_fontList.frame = CGRectMake(0,280,320,200);
}];
[_fontList reloadData];
}
- (IBAction)button:(id)sender {
_displayThemes = [[UITableView alloc]init];
[self.view addSubview:_displayThemes];
[UIView animateWithDuration:1.5
delay:0
options: UIViewAnimationOptionTransitionCurlUp
animations:^{
_displayThemes.frame=CGRectMake(0,800,320,200);
}
completion:^(BOOL finished){
_displayThemes.frame=CGRectMake(0,280,320,200);
}];
}
It will be the same as you do it with one table view, but you should check which tableview is currently using.
myTableView1.dataSource = self;
...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == myTableView1) {
// your code 1
}
else
if (tableView == myTableView2) {
// your code 2
}
else
if (tableView == myTableView3) {
// your code 3
}
}
Edit:
About brightness:
How to change brightness in iOS 5 app?
And about UISlider it has minimunValue and maximumValue properties.
- (void) sliderChanged:(UISlider*)sender{
UISlider *slider = (UISlider*)sender;
[[UIScreen mainScreen] setBrightness:slider.value];
}
Edit:
slider.tag = 1;
[cell addSubview:slider];
...
// when you need..
indexPath = [NSIndexPath indexPathForRow:myRow inSection:mySecion];
UISlider* slider = (UISlider*) [[self.tableView cellForRowAtIndexPath:indexPath] viewWithTag:1];
You always get a reference and can always check for which tableView delegate or dataSource method is called.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (tableView == self.tableView1)
{
return 1;
}
if (tableView == self.tableView2)
{
return 1;
}
if (tableView == self.tableView3)
{
return 1;
}
}
You don't gain anything by using same identifier for all tables. Use something like:
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
if (tableView == self.tableView1)
{
static NSString *CellIdentifier1 = #"cellForTable1";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1];
}
cell.textLabel.text = [NSString stringWithFormat: #"table1: %d.%d", indexPath.section, indexPath.row];
return cell;
}
if (tableView == self.tableView2)
{
static NSString *CellIdentifier2 = #"cellForTable2";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier2];
}
cell.textLabel.text = [NSString stringWithFormat: #"table2: %d.%d", indexPath.section, indexPath.row];
return cell;
}
if (tableView == self.tableView1)
{
static NSString *CellIdentifier3 = #"cellForTable3";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier3];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier3];
}
cell.textLabel.text = [NSString stringWithFormat: #"table3: %d.%d", indexPath.section, indexPath.row];
return cell;
}
}
//add tag in tableView .
myTable1.tag = 200;
myTable2.tag = 201;
myTable3.tag = 202;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (tableView.tag == 200)
{
return 1;
}
if (tableView.tag == 201)
{
return 1;
}
if (tableView.tag == 202)
{
return 1;
}
}
You can manage multiple tableView in a single ViewController by
writing below code inside UItableViewDelegate and UItableViewDatasource.
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == tableView1
{
// place your code here
}
else if tableView == tableView2 {
// place your code here
}
else {
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == tableView1
{
// place your code here
}
else if tableView == tableView2 {
// place your code here
}
else {
return 0
}
}
// You can set a different size of your tableView using below lines of code
if tableView == tableView1{
return 50
}
else{
return 40
}
None of the previous worked for me, I come up with the following solution:
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if((tableView1 != nil) && (tableView == tableView1)) {
return Items1.count
}
else if((tableView2 != nil) && (tableView == tableView2)) {
return Items2.count
}
else if((tableView3 != nil) && (tableView == tableView3)) {
return Items3.count
}
else {
return 0
}
}

Resources