I want to create a view like this in my iPhone App:
I do not know exactly what is this control in iOS, that maybe I can set an icon and text in the left side and that small sign in the right side.
I have implemented a TableView, there I was able to set these stuff, like this:
[[cell textLabel] setText:customer.name];
[[cell textLabel] setTextColor:[UIColor blackColor]];
[[cell imageView] setImage:[UIImage imageNamed:#"icon.png"]];
//[[cell detailTextLabel] setText:#"Awsome weather idag"];
cell.accessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
But how can I make it works like that view in the picture?
It is pretty simple, follow the steps below and in case of doubts check out the UITableView documentation:
1. Create a grouped table view:
Programmatically:
CGRect tableFrame = CGRectMake(0, 0, 200, 200);
UITableView *tableView = [[UITableView alloc] initWithFrame:tableFrame style:UITableViewGroupedStyle];
tableView.delegate = self;
tableView.dataSource = self;
[self.view addSubview:tableView];
Allocating a UITableViewController subclass (common case):
MyTableViewController *controller [[MyTableViewController alloc] initWithStyle: UITableViewGroupedStyle];
[self.navigationController pushViewController:controller animated:NO];
Through Interface Build:
Expand the Utilities Menu (top right corner icon);
Select your table view (click on it);
Click on the attributes inspector (top right corner fourth icon);
Under Table View, click on the style dropdown and select grouped.
2. Implement the UITableViewDataSource protocol:
Basically add this three functions to your controller.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in a given section.
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Configure the cells.
return cell;
}
3. Configuring the cells:
The default style of a UITableViewCell has an image view (UIImageView), a title label (UILabel) and an accessory view (UIView). All you need to replicate the table view in the image you provided.
So, you're looking for something like this in tableView:cellForRowAtIndexPath::
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString * const cellIdentifierDefault = #"default";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifierAccount];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifierAccount];
}
if (indexPath.section == 0) {
cell.imageView.image = [UIImage imageName:#"bluetooth_icon"];
cell.textLabel.text = #"Bluetooth";
// Additional setup explained later.
}else{
if (indexPath.row == 0) {
cell.imageView.image = [UIImage imageName:#"general_icon"];
cell.textLabel.text = #"General";
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}else{
cell.imageView.image = [UIImage imageName:#"privacy_icon"];
cell.textLabel.text = #"Privacy";
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
}
return cell;
}
The property accessoryType defines what is going to appear on the right side of a cell, a list of accessory types can be found here.
In the first cell (bluetooth), you'll need to create a custom accessory view and assign it to the cell's accessoryView property. A very naive example of how to achieve this is given below:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString * const cellIdentifierDefault = #"default";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifierAccount];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifierAccount];
label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 44)];
label.textAlignment = NSTextAlignmentRight;
cell.accessoryView = label;
}else{
label = (UILabel *) cell.accessoryView;
}
cell.imageView.image = [UIImage imageName:#"bluetooth_icon"];
cell.textLabel.text = #"Bluetooth";
label.text = #"Off";
return cell;
}
Hope this helps, Mateus
For fast output, you can use some library like
https://github.com/escoz/QuickDialog
protip, in my experience, solutions like this leaves you more tangled when Changes come in.
Some times you only want to change one specific label on once specific view, thats not gona be easy in any ready-made solution.
Look into UITableView Sections. That is what separates the groups apart.
Related
I have a tableviewcontroller that has dynamic controls created in cells. If it's a dropdown type, I take the user to a different tableviewcontroller to select the value. Once selected, I pop back and reload the data, but when I do that it overwrites the cells on top of one another. I know this is because I'm reusing the cells, but I cannot seem to figure out how to prevent it.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
EWHInboundCustomAttribute *ca = [visibleCustomAttributes objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
cell.tag=indexPath.row;
if (ca.CustomControlType == 1) {
cell.detailTextLabel.hidden=true;
cell.textLabel.hidden=true;
UITextField *caTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 185, 30)];
caTextField.adjustsFontSizeToFitWidth = YES;
caTextField.textColor = [UIColor blackColor];
caTextField.placeholder = ca.LabelCaption;
if (ca.ReadOnly) {
[caTextField setEnabled: NO];
} else {
[caTextField setEnabled: YES];
}
caTextField.text=nil;
caTextField.text=ca.Value;
caTextField.tag=indexPath.row;
caTextField.delegate=self;
[cell.contentView addSubview:caTextField];
} else if (ca.CustomControlType == 4) {
cell.detailTextLabel.text=ca.Value;
cell.textLabel.text=ca.LabelCaption;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else {
cell.detailTextLabel.hidden=true;
cell.textLabel.hidden=true;
UITextField *caTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 185, 30)];
caTextField.adjustsFontSizeToFitWidth = YES;
caTextField.textColor = [UIColor grayColor];
caTextField.placeholder = ca.LabelCaption;
[caTextField setEnabled: NO];
caTextField.text = ca.Value;
caTextField.tag=indexPath.row;
caTextField.delegate=self;
[cell.contentView addSubview:caTextField];
}
return cell;
}
Instead of creating the UITextfield each time I would suggest at least using [UIView viewWithTag:tag] to capture the same UITextField object.
I'd suggest you to create custom UITableViewCell subclass and put all subviews related logic there.
Next, in order to reset/clear cell before reuse - you should override prepeareForReuse function.
Swift:
override func prepareForReuse() {
super.prepareForReuse()
//set cell to initial state here
}
First,I suggest you to use custom cells.If not and your cells are not so many,maybe you can try unique cell identifier to avoid cell reuse:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// unique reuseID
NSString *cellReuseID = [NSString stringWithFormat:#"%ld_%ld", indexPath.section, indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellReuseID];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellReuseID];
// do something
}
return cell;
}
Hope it's helpful.
I'm making a tableview with multiple row selected option. So, I used the checkmark accessory type action. I also require to edit/rename the text in the selected row.
Basically, I need to put checkmark (checkbox) on the left side and detail disclosure on the right side of the cell, both functional.
Below code is for checkmark that i have, currently checkmark appears on the right side of the cell.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
TSIPAppDelegate *appDelegate = (TSIPAppDelegate *)[[UIApplication sharedApplication]delegate];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = cell.textLabel.text;
if (cell.accessoryType==UITableViewCellAccessoryNone)
{
cell.accessoryType=UITableViewCellAccessoryCheckmark;
appDelegate.selectedFile = cellText;
if (prevSP!=indexPath.row) {
cell=[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:prevSP inSection:0]];
cell.accessoryType=UITableViewCellAccessoryNone;
prevSP=indexPath.row;
}
}
else if (prevSP!=indexPath.row){
cell.accessoryType=UITableViewCellAccessoryNone;
}
}
Any suggestions, please?
When a row selected, checkmark should be enabled/disabled AND disclosure button selected, it should open a new view for editing the selected row.
accessoryType type is of enum UITableViewCellAccessoryType, by definition it will not accept multiple values as it not bitwise enum. So, you have to choose one and mimic the other by custom code.
I'd recommend using the UITableViewCellAccessoryCheckmark accessory type on the tableview and adding a "Detail Disclosure" button to the cell. Unfortunately you can't do exactly what you're looking for, but this is the cleanest alternative approach that I've found.
This is sample code which i have used in one of my app
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.textLabel.text=[NSString stringWithFormat:#"%#",[cellarray objectAtIndex:indexPath.row]];
cell.textLabel.textColor=[UIColor blackColor] ;
cell.textLabel.tag=indexPath.row;
cell.textLabel.font=[UIFont fontWithName:#"HelveticaNeue-Bold" size:15];
// cell.textLabel.highlightedTextColor=[UIColor colorWithRed:242.0f/255.0f green:104.0f/255.0f blue:42.0f/255.0f alpha:1] ;
cell.selectionStyle=UITableViewCellSelectionStyleNone;
}
UIImageView *ima=[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"tick.png"]];
ima.frame=CGRectMake(280, 15, 14, 14);
ima.autoresizingMask=UIViewAutoresizingFlexibleLeftMargin |UIViewAutoresizingFlexibleRightMargin;
int row = [indexPath row];
//cell.accessoryType = (row == selectedRow) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
cell.textLabel.textColor= (row == selectedRow) ? [UIColor colorWithRed:242.0f/255.0f green:104.0f/255.0f blue:42.0f/255.0f alpha:1] : [UIColor blackColor] ;
if (row==selectedRow) {
[cell.contentView addSubview:ima];
}
UIImageView *tempImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Background.png"]];
[tempImageView setFrame:tableView.frame];
tableView.backgroundView = tempImageView;
[tempImageView release];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
selectedRow = [indexPath row]; // selected row is of type int declared in .h
[tableView reloadData];
}
This code will have only one checkmark in entire tableView.. You can modify it to have multiple checkmark in that
Hope this helps !!!
I have a custom cell in TableView and there is a button in the cell. When I select the cell, the background turns to blue and the button disappears. Is there any way to prevent this?
The cellForRowAtIndexPath like this -
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
MyTableCell *cell = (MyTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[MyTableCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
Search *current = [self.retrievedTweets objectAtIndex:indexPath.row];
cell.textLabel.text = current.text;
cell.textLabel.font = [UIFont systemFontOfSize:15.0];
cell.textLabel.numberOfLines = 2;
cell.detailTextLabel.text = current.name;
cell.imageView.image = current.userImage;
btnUncheck =[[UIButton alloc] initWithFrame:CGRectMake(400, 35, 20, 20)];
btnUncheck.backgroundColor = [UIColor redColor];
btnUncheck.layer.cornerRadius = 10;
btnUncheck.hidden =NO;
btnUncheck.tag=indexPath.row;
//[btnUncheck addTarget:self action:#selector(didSelectRowAtIndexPath:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:btnUncheck];
return cell;
}
use custom image for selected table cell. or try with buttons images.
paste below line in your tableview Delegate Method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
///// your code ///////////
cell.selectionStyle=UITableViewCellSelectionStyleNone;
//// your code////////
}
here your blue backgound will not display..
What you can do is this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{[tableView deselectRowAtIndexPath:indexPath animated:YES];}
Hope this helps
Also, if you have already implemented this, what else do you have in this delegate method?
Instead of this line:
btnUncheck = [[UIButton alloc] initWithFrame:CGRectMake(400, 35, 20, 20)];
use:
btnUncheck = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
[btnUncheck setFrame:CGRectMake(400, 35, 20, 20)];
Create a "custom" view with background color clear and set to it.
UIView* vista=[[[UIView alloc] init] autorelease];
vista.backgroundColor=[UIColor clearColor];
cell.selectedBackgroundView=vista;
The way to fix this right, is to create a custom cell that you then add a button to in the xib editor.
So, in xib editor, add a 'UITableViewCell' item. Then add the button to that cell item in the xib editor. You'll then attach your custom cell to the table in the corresponding .m file here:
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
I have tried this out with just a one row table and the custom cell tied as a property from the xib to the .h file that has the table view. The highlight is there and just grays out the button (still viewable). To get this to work with more rows is more involved. You'll need to load the custom utableviewcell xib and alloc your custom cell dynamically for that to work.
I wanna create the uitableview like this image . loading data from server and assigning the values to columns of Row. I saw the link of stack, but not helpful to me.
UPDATE
My code: -
#pragma mark UITableViewDelegate methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section {
return [modelArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
static NSString *AutoCompleteRowIdentifier = #"AutoCompleteRowIdentifier";
cell = [tableView dequeueReusableCellWithIdentifier:AutoCompleteRowIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AutoCompleteRowIdentifier] autorelease];
}
cell.selectionStyle = UITableViewCellSelectionStyleGray;
// Configure the cell...
RankModel *model = [modelArray objectAtIndex:indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:#"%# %# %# %# %# %#", model.level, model.name, model.score, model.rightAnswersCount, model.currentRank, model.country];
return cell;
}
but I wanna display like the given image. so please help me to overcome this problem. thanks in advance.
Well this will require a bit more code than the method you present.
My suggestion is you could create a UILabel for each of your fields, instrad of using a single NSString. Don't use cell.textLabel, but rather add your content on cell.contentView and then you can manage each label's color, background color and labels' sizes. The "grid" look can be rendred by assigning a white color to contentView and assigning a green color for example to each label's background. For example, after your cell is created :
cell.contentView.backgroundColor = [UIColor clearColor];
UILabel* aLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 0.0, 100, 44)];
aLabel.tag = indexPath.row;
aLabel.textAlignment = UITextAlignmentLeft;
aLabel.textColor = [UIColor whiteColor];
aLabel.text = #"Test";
aLabel.backgroundColor = [UIColor greenColor];
[cell.contentView addSubview:aLabel];
[aLabel release];
Start your next label at 201 or more to leave an impression of a white vertical line.
Keep the row index in the tag so you can manage alternate colors in :
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell
*)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0 || indexPath.row%2 == 0) {
// use light green, get access to the labels via [cell.contentView viewWithTag:indexPath.row]
} else {
// use dark green
}
}
Hope this helps.
I am following the Google AdMob Ads iOS tutorial to get Ads working.
Everything works well until i try to add Ads to a UITableView.
My design was to have two sections on a Table where the Ad would appear on the first section and the table data on the second section. This however does not work too well as i get the ad in the first section BUT it is also repeated every 10th cell. I only want the Ad once. How do i do this.
Here is my code...
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *refreshButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:#selector(refresh:)];
self.navigationItem.rightBarButtonItem = refreshButtonItem;
[refreshButtonItem release];
// Create a view of the standard size at the bottom of the screen.
bannerView_ = [[GADBannerView alloc]
initWithFrame:CGRectMake(0.0,
0.0,
GAD_SIZE_320x50.width,
GAD_SIZE_320x50.height)];
// Specify the ad's "unit identifier." This is your AdMob Publisher ID.
bannerView_.adUnitID = #"blablabla";
// Let the runtime know which UIViewController to restore after taking
// the user wherever the ad goes and add it to the view hierarchy.
bannerView_.rootViewController = self;
GADRequest *adMobRequest = [GADRequest request];
adMobRequest.testDevices = [NSArray arrayWithObjects:
GAD_SIMULATOR_ID, // Simulator
#"fafasfasdfasdrasdasfasfaasdsd", nil];
// Initiate a generic request to load it with an ad.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
if (section == 0) {
return 1;
} else {
return 50;
}
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
if (indexPath.section == 0) {
if (indexPath.row == 0) {
[cell addSubview:bannerView_];
}
} else {
cell.textLabel.text = #"Test";
cell.detailTextLabel.text = #"Test";
cell.imageView.image = nil;
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 50;
}
Produces this..
In cellForRowAtIndexPath:, you need to give the cell with the ad a different cell identifier when you dequeue old cells for reuse. Cells with different subview contents need to have different identifiers, otherwise it will simply pop off the cell that contains the adView whenever it is dequeuing cells from the stack for the Cell identifier.
Basically, when the ad cell moves offscreen, it is put in the reuse queue and is subsequently popped off and reused for a normal cell when the normal cell at the opposite end of the table view comes into view from offscreen.
When indexPath.row == 0 (for each section), you'll need to dequeue the ad cell instead of a normal cell, like so:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellId = "Cell";
if(indexPath.row == 0) //first cell in each section
cellId = #"ad";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if(indexPath.row == 0)
[cell addSubview:bannerView_];
}
if (indexPath.row != 0){
cell.textLabel.text = #"Test";
cell.detailTextLabel.text = #"Test";
cell.imageView.image = nil;
}
return cell;
}
Also, check out an open-source library I wrote to manage both iAds and (fallback) AdMob ads with a single line of code. I haven't tested it with this particular config, but it may help nonetheless.