Hear is just the idea what i am thinking to implement this,
I want to implement book like pages, for this i want to take UITableView and rotated-90 degree and its cell by 90 degree, and now i want to subclass UITableViewCell, now within this tableview cell it is possible to add UITableview so that user can scroll vertically to see the contents and user can also scroll horizontally to go to next cell of rotated tableview.
It is just i am thinking, is there any better way to implement this.
yes it is possible, I added the UITableVIew within the UITableView cell
.. :)
no need to add tableview cell in xib file - just subclass the UITableviewCell and use the code below, a cell will be created programatically.
//in your main TableView
#import "ViewController.h"
#import "CustomCell.h"
#interface ViewController ()<UITableViewDataSource , UITableViewDelegate>
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc
{
[_aTV release];
[super dealloc];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [self.aTV dequeueReusableCellWithIdentifier:#"Cell"];
if(cell == nil)
{
cell = [[[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"]autorelease];
}
cell.dataAraay = [NSMutableArray arrayWithObjects:#"subMenu->1",#"subMenu->2",#"subMenu->3",#"subMenu->4",#"subMenu->5", nil];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 150;
}
//in your custom tableview cell
// .m file
#import "CustomCell.h"
#implementation CustomCell
#synthesize dataAraay; //array to hold submenu data
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.frame = CGRectMake(0, 0, 300, 50);
UITableView *subMenuTableView = [[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStylePlain]; //create tableview a
subMenuTableView.tag = 100;
subMenuTableView.delegate = self;
subMenuTableView.dataSource = self;
[self addSubview:subMenuTableView]; // add it cell
[subMenuTableView release]; // for without ARC
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(void)layoutSubviews
{
[super layoutSubviews];
UITableView *subMenuTableView =(UITableView *) [self viewWithTag:100];
subMenuTableView.frame = CGRectMake(0.2, 0.3, self.bounds.size.width-5, self.bounds.size.height-5);//set the frames for tableview
}
//manage datasource and delegate for submenu tableview
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return dataAraay.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellID"];
if(cell == nil)
{
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cellID"]autorelease];
}
cell.textLabel.text = [self.dataAraay objectAtIndex:indexPath.row];
return cell;
}
#end
Swift version
Create a single view project add tableview inside storyboard and set up its datasource and delegate
Paste code below to ViewController.swift
import UIKit
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3;
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:CustomCell? = tableView.dequeueReusableCellWithIdentifier("Cell") as? CustomCell
if cell == nil {
cell = CustomCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
}
cell?.dataArr = ["subMenu->1","subMenu->2","subMenu->3","subMenu->4","subMenu->5"]
return cell!
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 150.0
}
}
create a new file CustomCell.swift which is the subclass of UITableViewCell and do not select with xib this file is without .xib file table and its cell will be created programatically as in objective-c code.
Paste code below to CustomCell.swift
import UIKit
class CustomCell: UITableViewCell,UITableViewDataSource,UITableViewDelegate {
var dataArr:[String] = []
var subMenuTable:UITableView?
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style , reuseIdentifier: reuseIdentifier)
setUpTable()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
setUpTable()
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
setUpTable()
}
func setUpTable(){
subMenuTable = UITableView(frame: CGRectZero, style:UITableViewStyle.Plain)
subMenuTable?.delegate = self
subMenuTable?.dataSource = self
self.addSubview(subMenuTable!)
}
override func layoutSubviews() {
super.layoutSubviews()
subMenuTable?.frame = CGRectMake(0.2, 0.3, self.bounds.size.width-5, self.bounds.size.height-5)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArr.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("cellID")
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cellID")
}
cell?.textLabel?.text = dataArr[indexPath.row]
return cell!
}
}
Better way: use a UIPageViewController for your left/right page scrolling. Each page can contain a table view.
Although rob's Idea is better but yes it is possible. Check how:
Take 2 table view, give them tag 1, 2, let's call these kTagBaseTableView, kTagInnerTableView. Now below is the blue print, how to deat with two table view, with delegate and data source attached to single view controller.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ // Default is 1 if not implemented
switch (tableView.tag) {
case kTagBaseTableView:
return baseSectionCount;
break;
case kTagInnerTableView:
return innerSectionCount;
break;
default:
break;
}
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
switch (tableView.tag) {
case kTagBaseTableView:
return [baseDataSource count];
break;
case kTagInnerTableView:
return [innerDataSource count];
break;
default:
break;
}
return 0;
}
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = nil;
switch (tableView.tag) {
case kTagBaseTableView:{
static NSString* baseIdentifier = #"baseTableViewCell";
cell = [tableView dequeueReusableCellWithIdentifier:genderIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:genderIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
cell.textLabel.text = NSLocalizedString(titleKey, nil);
return cell;
}
break;
case kTagInnerTableView:{
static NSString* innerIdentifier = #"innerTableViewCell";
cell = [tableView dequeueReusableCellWithIdentifier:genderIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:genderIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
cell.textLabel.text = NSLocalizedString(titleKey, nil);
return cell;
}
default:
break;
}
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ // fixed font style. use custom view (UILabel) if you want something different
switch (tableView.tag) {
case kTagBaseTableView:
break;
case kTagInnerTableView:
break;
default:
break;
}
return nil;
}
//TABLE VIEW DELEGATE
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
selectedIndexPath = indexPath;
switch (tableView.tag) {
case kTagBaseTableView:{}
break;
case kTagInnerTableView:{
}
break;
default:
break;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Create a subclass for tableView and override the intrinsicContentSize. I have answered here.
#import "API.h"
#import "Parsing.pch"
#import "HomeViewController.h"
#import "ASIFormDataRequest.h"
#import "MBProgressHUD.h"
#import "UIImageView+WebCache.h"
#import "HomeCollectionViewCellForSubCat.h"
#import "CollectionViewTableViewCell.h"
#import "NewsTableViewCell.h"
#import "CategoryTableViewCell.h"
#import "HomeCollectionViewCellForSubCat.h"
#import "WebviewController.h"
#import "TopFreeAppsCollectionViewTableViewCell.h"
#import "TopSitesCollectionViewTableViewCell.h"
#import "TrandingVideoCollectionViewTableViewCell.h"
#import "SportsTableViewCell.h"
#import "JokesTableViewCell.h"
#interface HomeViewController ()
{
MBProgressHUD *hud;
NSMutableArray *Details;
NSIndexPath *IndexPath;
CollectionVIewTableViewCell *TrafficCell;
NewsTableViewCell *NewsCell;
CategoryTableViewCell *CategoryCell;
TopFreeAppsCollectionViewTableViewCell *TopAppsCell;
TopSitesCollectionViewTableViewCell *TopSitesCell;
TrandingVideoCollectionViewTableViewCell *TrendingVideosCell;
SportsTableViewCell *SportsCell;
JokesTableViewCell *JokesCell;
}
#end
NSString *More;
NSMutableArray *news;
#implementation HomeViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.automaticallyAdjustsScrollViewInsets = NO;
//[self.navigationController setNavigationBarHidden:YES];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
return dataArray.count;
}
- (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 ([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"TopApps"])
{
if(!TopAppsCell)
{
TopAppsCell = [tableView dequeueReusableCellWithIdentifier:#"TopFreeAppsCollectionViewTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
TopAppsCell.TopApps = [[dict valueForKey:#"detail"]valueForKey:#"small_banner"];
[TopAppsCell.TopAppsCollectionView reloadData];
return TopAppsCell;
}
return TopAppsCell;
}
else if ([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"TopSites"])
{
if(!TopSitesCell)
{
TopSitesCell = [tableView dequeueReusableCellWithIdentifier:#"TopSitesCollectionViewTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
TopSitesCell.TopSites = [dict valueForKey:#"detail"];
[TopSitesCell.TopSitesCollectionView reloadData];
return TopSitesCell;
}
return TopSitesCell;
}
else if ([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"Category"])
{
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;
}
else if ([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"TrendingVideos"])
{
if(!TrendingVideosCell)
{
TrendingVideosCell= [tableView dequeueReusableCellWithIdentifier:#"TrandingVideoCollectionViewTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
TrendingVideosCell.TrendingVideos = [[dict valueForKey:#"detail"]valueForKey:#"small_banner"];
[TrendingVideosCell.VideosCollectionView reloadData];
return TrendingVideosCell;
}
return TrendingVideosCell;
}
else if ([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"Sports"])
{
if(!SportsCell)
{
SportsCell= [tableView dequeueReusableCellWithIdentifier:#"SportsTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
SportsCell.Sports = [dict valueForKey:#"detail"];
[SportsCell.SportsTableView reloadData];
return SportsCell;
}
return SportsCell;
}
else if ([[dataArray[indexPath.row] valueForKey:#"type"] isEqual:#"Jokes"])
{
if(!JokesCell)
{
JokesCell= [tableView dequeueReusableCellWithIdentifier:#"JokesTableViewCell" forIndexPath:indexPath];
NSDictionary *dict=dataArray[indexPath.row];
JokesCell.Jokes = [dict valueForKey:#"detail"];
[JokesCell.JokesTableView reloadData];
return JokesCell;
}
return JokesCell;
}
else
{
}
return nil;
}
- (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 if([dict[#"type"] isEqual:#"Category"])
{
//Tap on Category cells
}
else if([dict[#"type"] isEqual:#"TopApps"])
{
//Tap on TopApps cells
}
else if([dict[#"type"] isEqual:#"TopSites"])
{
//Tap on TopSites cells
}
else if([dict[#"type"] isEqual:#"TrendingVideos"])
{
//Tap on Trending cells
}
else if([dict[#"type"] isEqual:#"Sports"])
{
//Tap on Sports cells
}
else if([dict[#"type"] isEqual:#"Jokes"])
{
//Tap on Jokes cells
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dict = dataArray[indexPath.row];
if([dict[#"type"] isEqual:#"Traffic" ])
{
return 155;
}
else if([dict[#"type"] isEqual:#"News"])
{
return 300;
}
else if([dict[#"type"] isEqual:#"Category"])
{
return 120;
}
else if([dict[#"type"] isEqual:#"TopApps"])
{
return 180;
}
else if([dict[#"type"] isEqual:#"TopSites"])
{
return 240;
}
else if([dict[#"type"] isEqual:#"TrendingVideos"])
{
return 270;
}
else if([dict[#"type"] isEqual:#"Sports"])
{
return 310;
}
else if ([dict[#"type"] isEqual:#"Jokes"])
{
return 280;
}
return 200;
}
Related
I am using tableView to display some information which is just four line of information. And i want to assign respective information to each row.
Like how shown in the below image there are four rows, same as in the image so i am using tableView for that. Here my problem is that i have created four cells but don't know how should i use label in specific cell and show the info.
and also if the value is null that row should not be there means if two values among four are null then only two rows having values should be there in tableView. How can i achieve this. Till now i am only able to show one row information only.
- (NSArray *)myTableViewCells
{
if (!_myTableViewCells)
{
_myTableViewCells = #[
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil],
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil],
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil],
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]
];
}
return _myTableViewCells;
}
if([managedObject valueForKey:#"personality_company_master_values"] != nil)
{
[_displayValues addObject:[NSString stringWithFormat:#"Personality %#",[managedObject valueForKey:#"personality_company_master_values"]]];
}
if([managedObject valueForKey:#"video_tag"] != nil)
{
[_displayValues addObject:[NSString stringWithFormat:#"Tag %#",[managedObject valueForKey:#"video_tag"]]];
}
if([managedObject valueForKey:#"industry_master_values"] != nil)
{
[_displayValues addObject:[NSString stringWithFormat:#"Industry %#",[managedObject valueForKey:#"industry_master_values"]]];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.myTableViewCells.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = self.myTableViewCells[indexPath.row];
// NSManagedObject *managedObject = [self.devices lastObject];
cell.backgroundColor = [self colorFromHexString:#"#014455"];
cell.textLabel.text = _displayValues[indexPath.row];
cell.textLabel.backgroundColor = [self colorFromHexString:#"#014455"];
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.font=[UIFont systemFontOfSize:14.0];
// UILabel *lbl=(UILabel*)[cell viewWithTag:900];
// [lbl setText:[managedObject valueForKey:#"personality_company_master_values"]];
// lbl.textColor=[UIColor blackColor];
return cell;
}
Get the value you want display in an array.
Something like this
#property (monatomic, strong)NSMuatableArray *displayValues;
-(void)viewDidLoad
{
self.displayValues = [[NSMutableArray alloc]init];
NSManagedObject *managedObject = [self.devices lastObject];
if([managedObject valueForKey:#"personality_company_master_values"] != nil)
{
[self.displayValues addObject:[managedObject valueForKey:#"personality_company_master_values"]];
}
if([managedObject valueForKey:#"company_master_values"] != nil)
{
[self.displayValues addObject:[managedObject valueForKey:#"company_master_values"]];
}
if([managedObject valueForKey:#"tag_master_values"] != nil)
{
[self.displayValues addObject:[managedObject valueForKey:#"tag_master_values"]];
}
}
- (NSArray *)myTableViewCells
{
if (!_myTableViewCells)
{
_myTableViewCells = #[
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil],
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil],
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil],
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]
];
}
return _myTableViewCells;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.displayValues.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = self.myTableViewCells[indexPath.row];
// NSManagedObject *managedObject = [self.devices lastObject];
//cell.textLabel.text = [NSString stringWithFormat:#"%#",[managedObject valueForKey:#"personality_company_master_values"]];
cell.textLabel.text = self.displayValues[indexPath.row];
//not getting have to do this way or any other way please help
// secondLabel.text = [NSString stringWithFormat:#"%#",[managedObject valueForKey:#"company_master_values"]];
// thirdLabel.text = [NSString stringWithFormat:#"%#",[managedObject valueForKey:#"tag_master_values"]];
return cell;
}
I'm afraid you're doing several things wrong, starting with preallocating an array of cells. Tableviews don't work like that, you provide cells on demand and populate them with values from your data model. When you want to remove a cell update your data model then call reloadData(). Here's a simple example:
import UIKit
class MyCell: UITableViewCell {
var row: Int = -1 // serves no purpose but to show how you might subclass a UITableViewCell
}
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var dataModel = [
"Hello", "World,", "this", "is", "a", "tableview"
]
var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
var frame = view.bounds
let statusBarHeight = UIApplication.sharedApplication().statusBarFrame.height
frame.origin.y += statusBarHeight
frame.size.height -= statusBarHeight
tableView = UITableView(frame: frame, style: .Plain)
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(MyCell.self, forCellReuseIdentifier: "mycell")
view.addSubview(tableView)
}
// MARK: - UITableViewDataSource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataModel.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("mycell") as! MyCell
let row = indexPath.row
cell.row = row // there is no point in doing this other than to show it as an example
cell.textLabel!.text = dataModel[row]
return cell
}
// MARK: - UITableViewDelegate
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
dataModel.removeAtIndex(indexPath.row)
tableView.reloadData()
}
}
EDIT: Here's an objective c version
////////////////////////////
/// Objective C Version //
////////////////////////////
#import "ViewController.h"
#interface MyCell: UITableViewCell
#property(assign) NSInteger row; // serves no purpose but to show how you might subclass a UITableViewCell
#end
#implementation MyCell #end
#interface ViewController() <UITableViewDataSource, UITableViewDelegate>
#property NSMutableArray *dataModel;
#property UITableView *tableView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_dataModel = [NSMutableArray arrayWithArray: #[#"Hello", #"World,", #"this", #"is", #"a", #"tableview"]];
CGRect frame = self.view.bounds;
CGFloat statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
frame.origin.y += statusBarHeight;
frame.size.height -= statusBarHeight;
_tableView = [[UITableView alloc] initWithFrame: frame style: UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
[_tableView registerClass: [MyCell class] forCellReuseIdentifier: #"mycell"];
[self.view addSubview: _tableView];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _dataModel.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCell *cell = (MyCell *) [tableView dequeueReusableCellWithIdentifier: #"mycell"];
NSInteger row = indexPath.row;
cell.row = row; // there is no point in doing this other than to show it as an example
cell.textLabel.text = _dataModel[row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[_dataModel removeObjectAtIndex: indexPath.row];
[_tableView reloadData];
}
#end
You dont need to create a fixed amount of cells this is not an efficient solution to the problem. You should create NSMutableDictionary and save the data like this:
NSMutableArray *data = [NSMutableDictionary dictionary];
[data setValue:#"Vijayakanth" forKey:#"Personality"];
Now in the table view delegate you can return the keys count for noOfRowsInSection and in cellForRowAtIndexPath you can get the key from dictionary get the value w.r.t that key and assign the values to your cell. In your case:
Key: Personality (which is shown on the left side)
Value: Vijayakanth (which is shown on the right side)
Hope you understand the point.
When I involve [tableView setEditing:YES animated:YES], delete control shows on every cell on the left,what I want to do is to get the event when I tap delete control,and directly delete cell but not to show delete button on the right.
I know apple's standard way to do this is to show delete button on the right, and when I tap it ,datasource's
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
gets involved, the reason I don't want to do like this is my cell is customised by scrollview which scroll horizontally so scroll to show delete button would made it a mess, so I wouldn't implement
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
in my datasource.
Have any idea?
one way u do is, customising the cell and put your own way of deleting the cell for example,
create a new custom cell by subclassing the UITableviewCell name it as something like CustomCellTableViewCell
in CustomCellTableViewCell.h define a delegate method for example,
#import <UIKit/UIKit.h>
#class CustomCellTableViewCell;
#protocol CellDelegate <NSObject>
- (void)deleteCell:(CustomCellTableViewCell *)cell;
#end
#interface CustomCellTableViewCell : UITableViewCell
+ (CustomCellTableViewCell *)createCell;
#property (weak, nonatomic) IBOutlet UIButton *deleteButton;
#property (weak, nonatomic) IBOutlet UILabel *descriptionLabel;
#property (weak,nonatomic) id<CellDelegate> cellDelegate;
- (IBAction)deleteAction:(id)sender;
- (void)showDeleteButton;
- (void)hideDeleteButton;
#end
and in CustomCellTableViewCell.xib add a button and set label connect to deleteButton and descriptionLabel
in CustomCellTableViewCell.m file
#import "CustomCellTableViewCell.h"
#implementation CustomCellTableViewCell
- (void)awakeFromNib {
// Initialization code
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self)
{
self = [CustomCellTableViewCell createCell];
}
return self;
}
+ (CustomCellTableViewCell *)createCell
{
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:#"CustomCellTableViewCell" owner:nil options:nil];
if ([arrayOfViews count] < 1) {
return nil;
}
for (id item in arrayOfViews) {
if([item isKindOfClass:[UITableViewCell class]])
return item;
}
return nil;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (IBAction)deleteAction:(id)sender {
if([self.cellDelegate respondsToSelector:#selector(deleteCell:)])
{
[self.cellDelegate deleteCell:self];
}
}
- (void)showDeleteButton
{
CGRect destRect = self.descriptionLabel.frame;
destRect.origin.x += 80;
[UIView animateWithDuration:0.3 animations:^{
self.descriptionLabel.frame = destRect;
}];
}
- (void)hideDeleteButton
{
CGRect destRect = self.descriptionLabel.frame;
destRect.origin.x = 0;
[UIView animateWithDuration:0.3 animations:^{
self.descriptionLabel.frame = destRect;
}] ;
}
#end
and in controller .m file
- (void)viewDidLoad {
[super viewDidLoad];
stringsArray = [[NSMutableArray alloc]initWithObjects:#"apple",#"dell",#"windows",#"nokia",#"sony",#"hp",#"lenovo", nil];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [stringsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SuggestionCell"];
if(cell == nil)
{
cell = [[CustomCellTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"SuggestionCell"];
}
if(customEditTableView)
[cell showDeleteButton];
else
[cell hideDeleteButton];
cell.cellDelegate = self;
cell.descriptionLabel.text = [stringsArray objectAtIndex:indexPath.row];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 50.0f;
}
- (IBAction)deleteCellsAction:(id)sender
{
if(customEditTableView)
customEditTableView = NO;
else
customEditTableView = YES;
[self.aTableView reloadData];
}
- (void)deleteCell:(CustomCellTableViewCell *)cell
{
NSIndexPath *indexPath = [self.aTableView indexPathForCell:cell];
[stringsArray removeObjectAtIndex:indexPath.row];
[self.aTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
try out in new project u will get it
You can achive this thing using UIViewController
Add tableview and tableviewcell in UIViewController
I have achive this same thing using swift. It will give you idea how to do in Objective-C
Below is Code:
var data:[String] = ["One","Three","Four","Five","Six"]
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.rightBarButtonItem = self.editButtonItem()
// Do any additional setup after loading the view, typically from a nib.
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel.text = self.data[indexPath.row]
if editing
{
cell.imageView.image = UIImage(named: "Button-Delete-icon.png")
}
else
{
cell.imageView.image = UIImage(named: "")
}
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if editing
{
self.data.removeAtIndex(indexPath.row)
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
}
}
override func setEditing(editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
self.tableView.reloadData()
}
Hope It will Help
I have implemented an empty ViewController i.e SearchViewController with a SearchBar in it. Ans as i am searching from a web service, i want the search results to be displayed only when the user presses the search button. That has been implemented. Bt the problem is, the results appear in a weird manner as shown below:
Dont know what are they getting hidden. How do i bring them to front??
Here is my code:
override func viewDidLoad() {
super.viewDidLoad()
self.api.delegate = self
activateSearch()
searchTableView.delegate = self
searchTableView.dataSource = self
searchBar.delegate = self
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as UITableViewCell
var rowData: NSDictionary = self.tableData[indexPath.row] as NSDictionary
cell.textLabel?.text = rowData["title"] as? String
return cell
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
func didReceiveAPIResults(results: NSDictionary) {
var resultsArr: NSArray = results["posts"] as NSArray
dispatch_async(dispatch_get_main_queue(), {
self.tableData = resultsArr
self.searchTableView!.reloadData()
})
}
func activateSearch() {
// self.navigationController?.navigationBarHidden = true
searchTableView.scrollRectToVisible(CGRectMake(0, 0, 1, 1), animated: false)
searchBar.becomeFirstResponder()
}
override func viewWillAppear(animated: Bool) {
var newBounds:CGRect = self.searchTableView.bounds;
newBounds.origin.y = newBounds.origin.y + self.searchBar.bounds.size.height;
self.searchTableView.bounds = newBounds;
self.navigationController?.navigationBarHidden = true
}
func searchBarSearchButtonClicked( searchBar: UISearchBar!)
{
api.searchItunesFor(searchBar.text)
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
self.viewWillAppear(true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
I might hv done something silly. bt m not able to figure out what is it.. pls help
It looks like your search bar has been placed over your table view. Try to scale your table view down in the storyboard so the top of the table view is below the search bar element. The results should display correctly
You are changing the searchTableView frame inside the viewWillAppear method which will not get call when you are in the same view controller.
Try changing the searchTableView frame inside the searchBarSearchButtonClicked method.
Hope this will solve your problem. :)
Edit:
Also try adding the search bar to the searchTableView header.
Below is the objective-c code for adding the search bar to the tableView header.
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 44.0f)] ;
self.searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
self.searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
self.searchBar.keyboardType = UIKeyboardTypeAlphabet;
self.searchBar.delegate = self;
self.tableView.tableHeaderView = self.searchBar;
Just posting the answer incase someone ends in a situation like mine.
I didn't connect the tableView to the SearchDisplayController.
The tableView should be the dataSource and Delegate for the SearchDisplayController.
We just need to control+Drag to connect.
PS. in XCODE 6.1 the SearchDisplayController is displayed as a button like thing in the header of ViewController.
#import <UIKit/UIKit.h>
#interface TableViewController : UITableViewController
#end
#import "TableViewController.h"
#interface TableViewController () {
NSInteger _rows;
}
#property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
#end
#implementation TableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_rows = 3;
// [self hideSearchBar];
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.tableView setContentOffset:CGPointMake(0,44) animated:NO];
// self.tableView.tableHeaderView = self.searchBar;
}
-(void)viewDidDisappear:(BOOL)animated{
//self.tableView.tableHeaderView = nil;
//[self.tableView.tableHeaderView removeFromSuperview];
[self.tableView setContentInset:UIEdgeInsetsMake(-0.3, 0, 0, 0)];
[super viewDidAppear:animated];
}
- (void)hideSearchBar {
// hide search bar
[self.tableView setContentOffset:CGPointMake(0,44) animated:NO];
}
- (IBAction)toggleCount:(UIBarButtonItem *)sender {
if (_rows == 20) {
_rows = 3;
} else {
_rows = 20;
}
[self.tableView reloadData];
}
- (IBAction)hideBar:(UIBarButtonItem *)sender {
[self hideSearchBar];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return _rows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text = #"cell";
return cell;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
/*
#pragma mark - Navigation
// In a story board-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
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
}
}
I want to make this type of expandable/collapsible table view.
there are categories and subcategories as in picture.
for example "health and beauty" is a category and when i click this cell than its open subcategories as in picture below.
So how can I make this type of table view?
please suggest me.
Finally i get two very useful helping link below which describes exact what the requirement is here
Expanding/Collapsing TableView Sections
Collapsable Table View for iOS
Really, good articles for such kind of expanding/collapsing tableview sections
Use Following code for expandable Cell into UITableView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text=[[self.arForTable objectAtIndex:indexPath.row] valueForKey:#"name"];
[cell setIndentationLevel:[[[self.arForTable objectAtIndex:indexPath.row] valueForKey:#"level"] intValue]];
return cell;
}
code for expanding & collapsing rows – TableView DidSelectRow Method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSDictionary *d=[self.arForTable objectAtIndex:indexPath.row];
if([d valueForKey:#"Objects"]) {
NSArray *ar=[d valueForKey:#"Objects"];
BOOL isAlreadyInserted=NO;
for(NSDictionary *dInner in ar ){
NSInteger index=[self.arForTable indexOfObjectIdenticalTo:dInner];
isAlreadyInserted=(index>0 && index!=NSIntegerMax);
if(isAlreadyInserted) break;
}
if(isAlreadyInserted) {
[self miniMizeThisRows:ar];
} else {
NSUInteger count=indexPath.row+1;
NSMutableArray *arCells=[NSMutableArray array];
for(NSDictionary *dInner in ar ) {
[arCells addObject:[NSIndexPath indexPathForRow:count inSection:0]];
[self.arForTable insertObject:dInner atIndex:count++];
}
[tableView insertRowsAtIndexPaths:arCells withRowAnimation:UITableViewRowAnimationLeft];
}
}
}
A Method which will help to minimize & maximize/expand-collapse rows.
-(void)miniMizeThisRows:(NSArray*)ar{
for(NSDictionary *dInner in ar ) {
NSUInteger indexToRemove=[self.arForTable indexOfObjectIdenticalTo:dInner];
NSArray *arInner=[dInner valueForKey:#"Objects"];
if(arInner && [arInner count]>0){
[self miniMizeThisRows:arInner];
}
if([self.arForTable indexOfObjectIdenticalTo:dInner]!=NSNotFound) {
[self.arForTable removeObjectIdenticalTo:dInner];
[self.tableView deleteRowsAtIndexPaths:
[NSArray arrayWithObject:[NSIndexPath indexPathForRow:indexToRemove inSection:0]]
withRowAnimation:UITableViewRowAnimationRight];
}
}
}
You can download the source code from my tutorial site.
If this helps: [Access uitableview's expandable and collapsable sections] https://github.com/OliverLetterer/UIExpandableTableView
I have a little bit of a different approach to expandable table views - one that aligns with how these kinds of table views are generally built.
There are headers and there are cells. Headers should be tappable, and then cells underneath the headers would show or hide. This can be achieved by adding a gesture recognizer to the header, and when tapped, you just remove all of the cells underneath that header (the section), and viceversa (add cells). Of course, you have to maintain state of which headers are "open" and which headers are "closed."
This is nice for a couple of reasons:
The job of headers and cells are separated which makes code cleaner.
This method flows nicely with how table views are built (headers and cells) and, therefore, there isn't much magic - the code is simply removing or adding cells, and should be compatible with later versions of iOS.
I made a very simple library to achieve this. As long as your table view is set up with UITableView section headers and cells, all you have to do is subclass the tableview and the header. Try it :)
Link: https://github.com/fuzz-productions/FZAccordionTableView
Try Using this code... May be this can help..
And Feel free to Edit the code according to your requirements...
#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface ViewController ()
#end
#implementation ViewController
#synthesize myTable;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//myTable.backgroundColor=[UIColor clearColor];
// self.view.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"wood.png"]];
muArr= [[NSMutableArray alloc]initWithObjects:#"Vinay",#"Anmol",#"Jagriti", nil];
ExpArr=[[NSMutableArray alloc]initWithObjects:#"Useeee",#"Thissss",#"Codeee", nil];
otherExpand=100;
checker=100;
}
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return muArr.count;
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(otherExpand==section)
return ExpArr.count;
return 0;
}
-(BOOL)tableView:(UITableView *)table canCollapse:(NSIndexPath *)indexPath
{
return NO;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *Identifier=#"Cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:Identifier];
if (cell==nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:Identifier];
}
cell.textLabel.text=[ExpArr objectAtIndex:indexPath.row];
cell.textLabel.backgroundColor=[UIColor clearColor];
UIView *viewww=[[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
viewww.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"wood.png"]];
cell.backgroundView=viewww;
// cell.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"wood.png"]];
[tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLineEtched];
[tableView setSeparatorColor:[UIColor purpleColor]];
return cell;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *view1=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 44)];
[view1.layer setCornerRadius:20];
view1.layer.borderWidth=2;
view1.layer.borderColor=[UIColor brownColor].CGColor;
UILabel *label=[[UILabel alloc]initWithFrame:CGRectMake(10, 0, 295, 44)];
label.backgroundColor=[UIColor clearColor];
label.text=[muArr objectAtIndex:section];
UIButton *btn=[UIButton buttonWithType:UIButtonTypeDetailDisclosure];
btn.frame=CGRectMake(280, -5, 50, 50);
btn.backgroundColor=[UIColor clearColor];
btn.tag=section;
view1.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"wood.png"]];
label.textColor=[UIColor blackColor];
label.font=[UIFont fontWithName:#"American TypeWriter" size:18];
//btn.backgroundColor=[UIColor blackColor];
[view1 addSubview:btn];
[view1 addSubview:label];
[btn addTarget:self action:#selector(Btntap:) forControlEvents:UIControlEventTouchUpInside];
return view1;
}
-(void)Btntap : (UIButton *)btn
{
if(otherExpand!=100)
{
if (otherExpand==btn.tag)
{
NSMutableArray *tempArr2=[[NSMutableArray alloc]init];
for(int j=0;j<ExpArr.count;j++)
{
NSIndexPath *indexx1=[NSIndexPath indexPathForRow:j inSection:otherExpand];
[tempArr2 addObject:indexx1];
}
checker=0;
otherExpand=100;
[myTable deleteRowsAtIndexPaths:tempArr2 withRowAnimation:UITableViewRowAnimationAutomatic];
}
else
{
NSMutableArray *tempArr2=[[NSMutableArray alloc]init];
for(int j=0;j<ExpArr.count;j++)
{
NSIndexPath *indexx1=[NSIndexPath indexPathForRow:j inSection:otherExpand];
[tempArr2 addObject:indexx1];
}
checker=1;
otherExpand=100;
[myTable deleteRowsAtIndexPaths:tempArr2 withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
if(checker!=0)
{
otherExpand=btn.tag;
//checker=
NSMutableArray *tempArr=[[NSMutableArray alloc]init];
for(int i=0;i<ExpArr.count;i++)
{
NSIndexPath *indexx=[NSIndexPath indexPathForRow:i inSection:btn.tag];
[tempArr addObject:indexx];
}
[myTable insertRowsAtIndexPaths:tempArr withRowAnimation:UITableViewRowAnimationAutomatic];
checker=1;
}
checker=100;
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 44;
}
#end
There is a great video in WWDC 2011 called UITableView Changes, Tips and Tricks - session 125 that shows how to do things like this.
Also check out the example code TVAnimationsGestures
You may take a look at this accordion example in Swift: https://github.com/tadija/AEAccordion
It's got very little code to create accordion effect (not by using sections but cells), and as a bonus there is also a solution to use XIB files inside other XIB files (useful for custom cells which use custom views).
Please try this example :
best example for Expandable TableView
https://github.com/OliverLetterer/UIExpandableTableView
TLIndexPathTools can do this sort of thing naturally. In fact, there is are extensions for both expandable sections and expandable tree structures. Try running the Collapse sample project for expandable sections and the Outline sample project for expandable trees.
One advantage of using TLIndexPathTools is that, as a simple, low-level API, it can solve all kinds of dynamic table view and collection view problems using a common approach. And it works interchangeably with Core Data and plain arrays.
it is so easy to create an expandable tableview
here is an example how I did this,
data I m using for this one
struct ItemList {
var name: String
var items: [String]
var collapsed: Bool
init(name: String, items: [String], collapsed: Bool = false) {
self.name = name
self.items = items
self.collapsed = collapsed
}
}
var sections = [ItemList]()
var items: [ItemList] = [
ItemList(name: "Mac", items: ["MacBook", "MacBook Air"]),
ItemList(name: "iPad", items: ["iPad Pro", "iPad Air 2"]),
ItemList(name: "iPhone", items: ["iPhone 7", "iPhone 6"])
]
now just add this piece of code and use accordingly
extension ViewController:UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 60
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerHeading = UILabel(frame: CGRect(x: 5, y: 10, width: self.view.frame.width, height: 40))
let imageView = UIImageView(frame: CGRect(x: self.view.frame.width - 30, y: 20, width: 20, height: 20))
if items[section].collapsed{
imageView.image = UIImage(named: "collapsed")
}else{
imageView.image = UIImage(named: "expand")
}
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 60))
let tapGuesture = UITapGestureRecognizer(target: self, action: #selector(headerViewTapped))
tapGuesture.numberOfTapsRequired = 1
headerView.addGestureRecognizer(tapGuesture)
headerView.backgroundColor = UIColor.red
headerView.tag = section
headerHeading.text = items[section].name
headerHeading.textColor = .white
headerView.addSubview(headerHeading)
headerView.addSubview(imageView)
return headerView
}
func numberOfSections(in tableView: UITableView) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let itms = items[section]
return !itms.collapsed ? 0 : itms.items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! UITableViewCell
cell.textLabel?.text = items[indexPath.section].items[indexPath.row]
return cell
}
#objc func headerViewTapped(tapped:UITapGestureRecognizer){
print(tapped.view?.tag)
if items[tapped.view!.tag].collapsed == true{
items[tapped.view!.tag].collapsed = false
}else{
items[tapped.view!.tag].collapsed = true
}
if let imView = tapped.view?.subviews[1] as? UIImageView{
if imView.isKind(of: UIImageView.self){
if items[tapped.view!.tag].collapsed{
imView.image = UIImage(named: "collapsed")
}else{
imView.image = UIImage(named: "expand")
}
}
}
tableView.reloadData()
}
}
and the result is Bingo :)
I had the requirement of expanding a single cell to a fuller view and collapsing it back to a summarised view.
So what I did was to design my cell using UIStackView. And I kept the view I didn't want to show in the collapsed state hidden and then showing it when the cell was tapped.
The trick here is to show and hide the view within tableView.beginUpdates() and tableView.endUpdates() statements. In this way table view automatically adjusts the cell height and does it animatedly.
Here is how a basic cell would look in the IB:
Cells Custom Class:
class AccordionCell: UITableViewCell {
#IBOutlet weak var stackView: UIStackView!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var descriptionLabel: UILabel!
#IBOutlet weak var extendedDescriptionLabel: UILabel!
var expanded: Bool = false {
didSet {
if let extended = self.extendedDescriptionLabel {
extended.isHidden = !expanded
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.expanded = false
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
UITableView Delegate Implementation:
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier) as! AccordionCell
cell.titleLabel.text = "Row: \(indexPath.row)"
cell.expanded = indexPath.row == expanded
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? AccordionCell {
tableView.beginUpdates()
if expanded == indexPath.row {
cell.expanded = false
expanded = -1
}
else {
cell.expanded = true
expanded = indexPath.row
}
tableView.endUpdates()
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? AccordionCell {
tableView.beginUpdates()
cell.expanded = false
tableView.endUpdates()
}
}
}
In order to keep track which cell is expanded, I introduced a variable saving indexpath of currently expanded cell so that the right cell is expanded when tableview is scrolled.
Check this Link :
http://iostechnotips.blogspot.in/2014/05/expandable-uitableview.html
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
*Use UITableView delegate method viewForHeaderInSection and return a custom UIView.
*Add a UIButton as subview with action "expandable:(id)sender" check the sender id as section number and reload the table view.
In your .h file
LoadCustomCell *cell1;
NSMutableArray *arrayForBool;
NSMutableArray *questionArray;
NSMutableArray *answerArray;
In your .m file
viewDidLoadMethod {
_faqTblView.estimatedRowHeight = 30;
_faqTblView.rowHeight = UITableViewAutomaticDimension;
arrayForBool = [[NSMutableArray alloc]init];
_questionArray = [[NSMutableArray alloc]init];
_answerArray = [[NSMutableArray alloc]init];
for (int i = 0; i < _questionArray.count; i++) {
[arrayForBool addObject:#"0"];
}
self.faqTblView.dataSource = self;
self.faqTblView .delegate = self;
[self.faqTblView reloadData];
}
after that
#pragma mark - TableView Datasource & Delegate Method.
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [_questionArray count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
UILabel *lblText = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 260, 100)];
lblText.text = [_questionArray objectAtIndex:section];
return [lblText getLabelHeight] + 20;(created custom class)
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UITapGestureRecognizer *headerTapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(sectionHeaderTapped:)];
cell1 = [[[NSBundle mainBundle] loadNibNamed:#"LoadCustomCell" owner:self options:nil] objectAtIndex:0];
[cell1 setFrame:CGRectMake(0, 0, cell1.frame.size.width, cell1.frame.size.height)];
NSString *numStr = [NSString stringWithFormat:#"%ld. ",section + 1];
[cell1.sideMenuUserNameLabel setText:[numStr stringByAppendingString:[_questionArray objectAtIndex:section]]];
[cell1 setBackgroundColor:[UIColor lightGrayColor]];
cell1.tag = section;
[cell1 addGestureRecognizer:headerTapped];
return cell1;
}
- (void)sectionHeaderTapped:(UITapGestureRecognizer *)gestureRecognizer {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:gestureRecognizer.view.tag];
if (indexPath.row == 0) {
BOOL collapsed = [[arrayForBool objectAtIndex:indexPath.section] boolValue];
for (int i = 0; i < [_questionArray count]; i++) {
if (indexPath.section==i) {
[arrayForBool removeObjectAtIndex:i];
[arrayForBool insertObject:[NSString stringWithFormat:#"%d", !collapsed] atIndex:i];
}
}
NSLog(#"%#", arrayForBool);
[self.faqTblView reloadSections:[NSIndexSet indexSetWithIndex:gestureRecognizer.view.tag] withRowAnimation:UITableViewRowAnimationAutomatic];
for (NSIndexPath *indexPath in self.faqTblView.indexPathsForSelectedRows) {
[self.faqTblView deselectRowAtIndexPath:indexPath animated:NO];
}
cell1.imageView.transform = CGAffineTransformMakeRotation(M_PI);
}
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *questionCellIdentifier = #"questionCellIdentifier";
QuestionCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:questionCellIdentifier];
if (cell == nil) {
NSArray * myNib;
myNib =[[NSBundle mainBundle]loadNibNamed:#"QuestionCustomCell" owner:self options:nil];
cell = (QuestionCustomCell *)[myNib lastObject];
}
BOOL manyCells = [[arrayForBool objectAtIndex:indexPath.section] boolValue];
if(manyCells){
cell.questionNameLbl.text = [_answerArray objectAtIndex:indexPath.section];
}
return cell;
}
You can use ExpyTableView
Which makes an expandable section from your given cell. Compatible down to iOS 8.0. You will have flexibility by generating an expandable table view with multiple table view cells. Just manipulate the separators for states and then no one will know you are using multiple cells for expanding.
Other solutions: You manipulate the height to expand a cell, when an update needed in design of the cell, you have to re-construct all the auto-layout constraints or logic in code.
ExpyTableView: You make an expandable table view by using multiple cells and inserting and deleting them(which can mean expanding and collapsing), you will have a great chance in future design requests. All you will have to do is adding a new UITableViewCell and writing the code for it. You will easily have the new design.
All you have to do is to import ExpyTableView and then:
class ViewController: ExpyTableViewDataSource, ExpyTableViewDelegate {
#IBOutlet weak var expandableTableView: ExpyTableView!
// First, set data source and delegate for your table view.
override func viewDidLoad() {
super.viewDidLoad()
expandableTableView.dataSource = self
expandableTableView.delegate = self
}
// Then return your expandable cell instance from expandingCell data source method.
func expandableCell(forSection section: Int, inTableView tableView: ExpyTableView) -> UITableViewCell {
// this cell will be displayed at IndexPath with section: section and row 0
}
}
You can see your former table view section is now an expandable table view section. You can also download the example project and see more detailed examples.
UITableView with Collapsible (expand and collapse) Cells swift 5
Very Easy to Use with Custom Cells
Expendable
Dynamic Content
Check Github Link : https://github.com/Murteza12/ExpandableTablew/wiki/UITableView-with-Collapsible-(expand-and-collapse)-Cells