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
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.
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")
}
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
}
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;
}
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
}
}