I want number of item to add by user like :
-__+
If user add item that he add + button and increase item. so i added textfield to table and add two button Plus(+) and Minus(-). Here is my code in cellForRowAtIndexPath:
if(isPlus){
countFruitQty++;
cell.txtQty.text = [NSString stringWithFormat:#"%i",countFruitQty];
}
else{
countFruitQty--;
if(countFruitQty > 0)
cell.txtQty.text = [NSString stringWithFormat:#"%i",countFruitQty];
else{
cell.txtQty.text = #"";
countFruitQty = 0;
}
But on scroll it change data to all added textField.
How to Prevent this?
You have to manage array for it,
Check below code for your reference, Hope it will help you out
#interface YourViewController ()
{
NSMutableArray *arrMain; // Your main array (Table row count)
NSMutableArray *arrCounter; // Counter array
int a;
}
- (void)viewDidLoad {
arrMain = [[NSMutableArray alloc] init];
arrCounter = [[NSMutableArray alloc] init];
a = 0;
for (int i = 0, i < [arrMain count], i++) {
[arrCounter addObject:[NSString stringWithFormat:#"%d",a]];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
cell.btnPlus.tag = indexPath.row;
[cell.btnPlus addTarget:self action:#selector(click_Plus:) forControlEvents:UIControlEventTouchUpInside];
cell.btnMinus.tag = indexPath.row;
[cell.btnMinus addTarget:self action:#selector(click_Minus:) forControlEvents:UIControlEventTouchUpInside];
cell.txtQty.text = [arrCounter objectAtIndex:indexPath.row];
}
-(IBAction)click_Plus:(UIButton *)sender {
int qnt = [cell.txtQty.text intValue];
cell. txtQty.text = [NSString stringWithFormat:#"%d",++qnt];
[arrCounter replaceObjectAtIndex:sender.tag withObject:cell.txtQty.text];
}
-(IBAction)click_Minus:(UIButton *)sender {
int qnt = [cell.txtQty.text intValue];
cell.txtQty.text = [NSString stringWithFormat:#"%d",--qnt];
[arrCounter replaceObjectAtIndex:sender.tag withObject:cell.txtQty.text];
}
this happens because when you scroll your tableview cell is reused and reset all your textfield
if you want to achieve this functionality you should use scrollview and addSuview when you need
Related
I am trying to create a custom questionnaire. I have multiple NSMutableArray(btnAr) where I store the groups of buttons. To keep things in order, I use another NSMutableArray(radioGroupBtns) where I store all the NSMutableArrays(btnAr).
I use tableview to display the buttons. The problem I am facing is this:
When I click on a button in the first group, after scrolling to the last group the same button is clicked also.
The right image is when I scrolled at the bottom.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
-(UITableViewCell* )tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
FeedbackViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
NSInteger rowNum = [indexPath row];
NSLog(#"RowNumb: %ld",rowNum);
NSMutableArray *btns = [radioGroupBtns objectAtIndex:rowNum];
NSMutableArray *lbls = [radioGroupLabels objectAtIndex:rowNum];
for (int i=0; i<[btns count]; i++)
{
[cell addSubview:[btns objectAtIndex:i]];
[cell addSubview:[lbls objectAtIndex:i]];
}
return cell;
}
-(void) getData
{
int totalSections = 5;
for (int j=0; j<totalSections; j++)
{
NSMutableArray *btnAr = [[NSMutableArray alloc]init];
NSMutableArray *lblAr = [[NSMutableArray alloc]init];
int numOfQuestions = 4;
for (int i=0; i<numOfQuestions; i++)
{
RadioUIButton *button = [self getButton:i];
button.sectionTag = j;
button.stringTag = [NSString stringWithFormat:#"%d%d", i,button.sectionTag];
[button setTag:i];
UILabel *lbl = [self getLabel:i text:#"Question"];
[lblAr addObject:lbl];
[btnAr addObject:button];
}
[radioGroupBtns addObject:btnAr];
[radioGroupLabels addObject:lblAr];
}
}
- (void) btnPressed:(id) b
{
RadioUIButton *btn = (RadioUIButton *) b;
NSMutableArray *group = [radioGroupBtns objectAtIndex:btn.sectionTag];
for (RadioUIButton *bn in group)
{
if ([bn tag] != [b tag])
{
if ([bn isSelected])
[bn setSelected:!bn.selected];
}
}
if (![btn isSelected])
[btn setSelected:!btn.selected];
NSLog(#"Button %ld clicked. Row: %d , String: %#", (long int)[b tag], btn.sectionTag, btn.stringTag);
}
- (RadioUIButton*) getButton:(int) i {
RadioUIButton *button = [RadioUIButton buttonWithType:UIButtonTypeCustom];
int hpos = i*30 + 30;
button.frame = CGRectMake(30.0f, hpos, 30.0f, 30.0f);
[button addTarget:self action:#selector(btnPressed:) forControlEvents:UIControlEventTouchUpInside];
//[button setTitle:#"Option A" forState:UIControlStateNormal];
[button setImage: [UIImage imageNamed:#"radio_button_off.png"]forState:UIControlStateNormal];
[button setImage: [UIImage imageNamed:#"radio_button_on.png"]forState: UIControlStateSelected];
return button;
}
- (UILabel*) getLabel:(int) i text:(NSString *) txt{
int hpos = i*30 + 30;
UILabel *label = [[UILabel alloc] init];
label.frame = CGRectMake(80,hpos,200,30);
label.text = txt;
return label;
}
Table view reuses cells. There are ways to handle this. But, in your case you dont seem to need to reuse cells. So use scroll view instead and inflate views inside that.
And as a suggestion, try to store model objects instead of buttons. Manipulate views and their state based on the data model.
I am facing issue regarding Dynamic cell in UITableView. I want to create dynamic rows while user clicked on button in tableview.
E.g.: in mytableview there are two rows as following :
Car :+
Bike :+
When user clicked add button then I have to show two more rows below car cell same thing as while user clicked on in front of bike add button then I have to show two more cells.
I think you need to have 2 sections, a bike and a car section with two data arrays to manage content of all cells. You may need to have two types of cell, an "add" cell and a "standard" cell.
Here is an example:
-In your viewDidiLoad:
self.bikeArray = [NSMutableArray arrayWithArray:#[#"Add bike"]]; // Aray to fill section 0
self.carArray = [NSMutableArray arrayWithArray:#[#"Add car"]]; // Aray to fill section 1
self.typeOfVehicleArray = #[#"Bike", #"Car"];
self.dataArray = #[self.bikeArray, self.carArray];
To create two types of cell, check indexPath.row:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
switch (indexPath.row) {
case 0:{
NSString *addIdentifier = #"addIdentifier";
cell = [tableView dequeueReusableCellWithIdentifier:addIdentifier];
if (!cell){
// Add button...
CGFloat buttonWidth = 60.f;
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:addIdentifier];
UIButton *b = [[UIButton alloc] initWithFrame:CGRectMake(cell.frame.size.width - buttonWidth - 10.f , 5.f, buttonWidth, cell.frame.size.height - 10.f)];
[b setTitle:#"ADD" forState:UIControlStateNormal];
// ...with a wonderful color
b.backgroundColor = [UIColor greenColor];
[b addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:b];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
break;
}
default:{
NSString *standardIdentifier = #"standardIdentifier";
cell = [tableView dequeueReusableCellWithIdentifier:standardIdentifier];
if (!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:standardIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
break;
}
}
NSArray *vehicleArray = self.dataArray[indexPath.section];
cell.textLabel.text = [vehicleArray objectAtIndex:indexPath.row];
return cell;
}
Don't forget number of cells / sections:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.dataArray count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *vehicleArray = self.dataArray[section];
return [vehicleArray count];
}
Then you can implement buttonPressed:
- (void) buttonPressed: (id)sender{
// Find the section
UIButton *b = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *)[b superview];
NSInteger section = [self.tableView indexPathForCell:cell].section;
// Get vehicle array (bikeArray or carArray)
NSMutableArray *vehicleArray = self.dataArray[section];
NSString *vehicleType = [self.typeOfVehicleArray objectAtIndex:section];
NSInteger nextVehicle = [vehicleArray count];
NSString *firstRowToAdd = [NSString stringWithFormat:#"%# %lu", vehicleType, (long)nextVehicle];
NSString *secondRowToAdd = [NSString stringWithFormat:#"%# %lu", vehicleType, (long)(nextVehicle + 1)];
// Add object in vehicle array
[vehicleArray addObject:firstRowToAdd];
[vehicleArray addObject:secondRowToAdd];
// Create array of corresponding indexPath and update tableview
NSArray *indexPathArray = #[[NSIndexPath indexPathForRow:nextVehicle inSection:section],
[NSIndexPath indexPathForRow:(nextVehicle + 1) inSection:section]];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationRight];
[self.tableView endUpdates];
}
You can control number rows in UITableView's tableView:numberOfRowsInSection: function that is defined in UITableViewDataSource Protocol. Just define an integer variable that holds the number rows user should see. On every Add button click increase the value of variable.
#implementation ViewController {
int numberOfRows;
}
- (void)viewDidLoad {
[super viewDidLoad];
numberOfRows = 3;
}
-(IBAction) addButtonClicked
{
numberOfRows++;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return numberOfRows;
}
I'm currently facing a strange issue with a UITableView in iOS whereby deselected rows are no longer selectable immediately, you must tap three times before you can select again. I'm implementing something akin to a checklist, with a "clear" button to go through and deselect all the cells. This effect only occurs when the cell had been previously selected, but the "clear" button is pressed. If a cell had been untouched before and is touched after the clear button, it will be presented and toggle fine.
Here is what I have
I should mention that the VC this Table is in is stored inside a container, hence the reference to it.
The deselect
- (IBAction)btnClearTapped:(id)sender {
UITableView *locationList = self.locationsVc.tableView;
for (NSUInteger i = 0; i < [locationList numberOfSections]; i++) {
for (NSUInteger j = 0; j < [locationList numberOfRowsInSection:i]; j++) {
[locationList deselectRowAtIndexPath:[NSIndexPath indexPathForRow:j inSection:i] animated:YES];
}
}
}
The didSelectRowAtIndexPath method
- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
BOOL isChecked = !((NSNumber *) cellToggleDict[indexPath]).boolValue;
cellToggleDict[indexPath] = #(isChecked);
UIView *selectionColorView = [[UIView alloc] init];
if (isChecked) {
selectionColorView.backgroundColor = selectedColor;
selectedLocations[indexPath] = [[Search sharedManager] locationAtIndexPath:indexPath];//PFObject
}
else {
selectionColorView.backgroundColor = unselectedColor;
[selectedLocations removeObjectForKey:indexPath];
}
cell.selectedBackgroundView = selectionColorView;
}
And finally the dequeue and redraw method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Reuse" forIndexPath:indexPath];
PFObject *object = [[Search sharedManager] locationAtIndexPath:indexPath];
cell.textLabel.text = object[#"Name"];
BOOL isChecked = ((NSNumber *) cellToggleDict[indexPath]).boolValue;
UIView *selectionColorView = [[UIView alloc] init];
if (isChecked) {
selectionColorView.backgroundColor = selectedColor;
}
else {
selectionColorView.backgroundColor = unselectedColor;
}
cell.selectedBackgroundView = selectionColorView;
return cell;
}
You don't clear the cellToggleDict entries in the btnClearTapped: method. You should have.
- (IBAction)btnClearTapped:(id)sender {
UITableView *locationList = self.locationsVc.tableView;
[cellToggleDict removeAllObjects]; // Clear all objects from the selected store
for (NSUInteger i = 0; i < [locationList numberOfSections]; i++) {
for (NSUInteger j = 0; j < [locationList numberOfRowsInSection:i]; j++) {
[locationList deselectRowAtIndexPath:[NSIndexPath indexPathForRow:j inSection:i] animated:YES];
}
}
}
I'm developing a shopping app, in which i'm implementing a shopping cart. In my app, i need to increase the product quantity when the plus button is clicked and reduce the product quantity when the minus button is clicked. Here my problem is, when i click the plus button, all text field value is changing in the tableviewcell. Help me,below is
plus button action method
-(IBAction)plusBtn:(UIButton*)plus
{
[self.tbleView beginUpdates];
UITableViewCell *clickedCell = (UITableViewCell *)[[plus superview] superview];
NSIndexPath *clickedButtonIndexPath = [self.tbleView indexPathForCell:clickedCell];
plus.tag = clickedButtonIndexPath.row;
quantity.tag = clickedButtonIndexPath.row;
_curr =_curr+1;
quantity.text = [NSString stringWithFormat:#"%d",_curr];
[self.tbleView endUpdates];
[self.tbleView reloadData];
}
like this
getting..
can u check this functionality. it will useful for you. i hope it.
- (void)viewDidLoad
{
[super viewDidLoad];
quantity =[NSMutableArray new];
occu_list = [[NSArray alloc] initWithObjects:#"Occupation", #"two", #"three", #"four", #"five", #"six", #"seven", #"eight", nil];
for(int i=0;i<[occu_list count];i++)
{
[quantity addObject:#"0"];
}
click_textView=[[UIView alloc]init];
click_textView.frame=self.view.frame;
[self.view addSubview:click_textView];
[self tableviewone];
}
-(void)tableviewone
{
tbl_view = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
tbl_view.delegate = self;
tbl_view.dataSource = self;
tbl_view.backgroundColor = [UIColor whiteColor];
tbl_view.layer.borderColor=[[UIColor orangeColor]CGColor];
tbl_view.layer.borderWidth=2.0f;
tbl_view.layer.cornerRadius=5.0f;
tbl_view.layer.masksToBounds=YES;
[click_textView addSubview:tbl_view];
}
-(IBAction)check_btn_action:(id)sender
{
UIButton *btntag=(UIButton*)sender;
NSLog(#"%li",(long)btntag.tag);
NSLog(#"%#",[quantity objectAtIndex:btntag.tag]);
int ad=[[quantity objectAtIndex:btntag.tag]integerValue];
ad=ad+1;
[quantity removeObjectAtIndex:btntag.tag];
[quantity insertObject:[NSString stringWithFormat:#"%i",ad] atIndex:btntag.tag];
[tbl_view reloadData];
}
Write action method for your button and then inside that just use this one line of code for setting your value to the textfield:-
self.yourTxtFld.text=#"yourString"
Don`t write the Button action in ViewController,
write it in the CustomCell class.
example:
in the CustomCell.m
- (IBAction)plusButtonDidClicked:(UIButton *)sender {
int i = [self.textField.text intValue];
i++;
self.textField.text = [NSString stringWithFormat:#"%d", i];
}
Then back to the ViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CustomCellIdentifier];
return cell;
}
It will be work well.
-(IBAction)plusBtn:(UIButton*)plus
{
UITableViewCell *clickedCell = (UITableViewCell *)[[plus superview] superview];
_curr=_curr+1;
UITextField *qty = (UITextField *) [clickedCell viewWithTag:90];
qty.text=[NSString stringWithFormat:#"%d",_curr];
}
I have a UITableView with several sections.
I would like click on a section to "close/open" its content, in order to show/hide the rows under it. So that, I can keep some sections open (with its rows visible) and others close, with the next section immediately below the previous section header.
How can I implement it? Do I need to subclass the UITableView and add a gesture recognizer and somehow add an animation to the rows? But I'm not sure this is easy...
thanks
Use reloadSections:withRowAnimation to trigger the change;
Provide the updated number of rows in UITableViewDataSource delegate
I can't comment for the question as I don't have enough reputation.
As per my understanding, you want to achieve accordion functionality for your table view. For this, please check this:- effect or animation in UItableVIew and How to implement an accordion view for an iPhone SDK app?
Just subclass sectionHeaderView and define delegate methods like this.
#protocol SectionHeaderViewDelegate <NSObject>
#optional
-(void)sectionHeaderView:(SectionHeaderView*)sectionHeaderView sectionOpened:(NSInteger)section;
-(void)sectionHeaderView:(SectionHeaderView*)sectionHeaderView sectionClosed:(NSInteger)section;
#end
And then in tableViewCOntroller.h
#interface TableViewController : UITableViewController <SectionHeaderViewDelegate>
And in tableViewCOntroller.m
-(void)sectionHeaderView:(SectionHeaderView*)sectionHeaderView sectionOpened:(NSInteger)sectionOpened
{
SectionInfo *sectionInfo = [self.sectionInfoArray objectAtIndex:sectionOpened];
sectionInfo.open = YES;
/*
Create an array containing the index paths of the rows to insert: These correspond to the rows for each quotation in the current section.
*/
NSInteger countOfRowsToInsert = [sectionInfo.play.quotations count];
NSMutableArray *indexPathsToInsert = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < countOfRowsToInsert; i++) {
[indexPathsToInsert addObject:[NSIndexPath indexPathForRow:i inSection:sectionOpened]];
}
/*
Create an array containing the index paths of the rows to delete: These correspond to the rows for each quotation in the previously-open section, if there was one.
*/
NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];
NSInteger previousOpenSectionIndex = self.openSectionIndex;
if (previousOpenSectionIndex != NSNotFound) {
SectionInfo *previousOpenSection = [self.sectionInfoArray objectAtIndex:previousOpenSectionIndex];
previousOpenSection.open = NO;
[previousOpenSection.headerView toggleOpenWithUserAction:NO];
NSInteger countOfRowsToDelete = [previousOpenSection.play.quotations count];
for (NSInteger i = 0; i < countOfRowsToDelete; i++) {
[indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:previousOpenSectionIndex]];
}
}
// Style the animation so that there's a smooth flow in either direction.
UITableViewRowAnimation insertAnimation;
UITableViewRowAnimation deleteAnimation;
if (previousOpenSectionIndex == NSNotFound || sectionOpened < previousOpenSectionIndex) {
insertAnimation = UITableViewRowAnimationTop;
deleteAnimation = UITableViewRowAnimationBottom;
}
else {
insertAnimation = UITableViewRowAnimationBottom;
deleteAnimation = UITableViewRowAnimationTop;
}
// Apply the updates.
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:indexPathsToInsert withRowAnimation:insertAnimation];
[self.tableView deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:deleteAnimation];
[self.tableView endUpdates];
self.openSectionIndex = sectionOpened;
}
-(void)sectionHeaderView:(SectionHeaderView*)sectionHeaderView sectionClosed:(NSInteger)sectionClosed
{
/*
Create an array of the index paths of the rows in the section that was closed, then delete those rows from the table view.
*/
SectionInfo *sectionInfo = [self.sectionInfoArray objectAtIndex:sectionClosed];
sectionInfo.open = NO;
NSInteger countOfRowsToDelete = [self.tableView numberOfRowsInSection:sectionClosed];
if (countOfRowsToDelete > 0)
{
NSMutableArray *indexPathsToDelete = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < countOfRowsToDelete; i++) {
[indexPathsToDelete addObject:[NSIndexPath indexPathForRow:i inSection:sectionClosed]];
}
[self.tableView deleteRowsAtIndexPaths:indexPathsToDelete withRowAnimation:UITableViewRowAnimationTop];
}
self.openSectionIndex = NSNotFound;
if ([selectedIndexes count]>0)
{
for(NSIndexPath *indexPath in selectedIndexes)
{
if(sectionClosed == indexPath.section)
{
[sectionInfo.headerView changeOnHighlighted:YES];
break;
}
else
{
[sectionInfo.headerView changeOnHighlighted:NO];
}
}
}
else
{
[sectionInfo.headerView changeOnHighlighted:NO];
}
}
And for further details you can refer this sample project from iOS dev lib..
Here is a simple solution by which you can even create a custom expanded/ collapse view.
here are simple step
1) create a custom view add button over it.
///
join all outlet and create on BOOL variable in view class
#property (weak, nonatomic) IBOutlet UIButton *BtnAction;
#property(assign, nonatomic)BOOL isOpen;
// Create a header where tableview is added and you want it.
here is a simple logic to added as much as you need . I have added which are in headertitle array I wanted it to be dynamic .
NSMutableArray * headerTitle = [NSMutableArray arrayWithObjects:#"Your Order", #"Delivery Address", #"Pay By", nil];
for (NSUInteger index = 0; index<headerTitle.count; index++) {
VGOrderHeader* HeaderView = [[[NSBundle mainBundle] loadNibNamed:#"VGOrderHeader" owner:self options:nil] lastObject];
HeaderView.frame = CGRectMake(0, 0, 32, 40);
HeaderView.BtnAction.tag = index;
if (index == 0) {
HeaderView.isOpen = YES;
HeaderView.lblPlus.text = [NSString stringWithFormat:#"open"];
}
[HeaderView.BtnAction addTarget:self action:#selector(selectSectionToOpen:) forControlEvents:UIControlEventTouchUpInside];
[headerArray addObject:HeaderView];
}
/// Here is header click action.
-(void)selectSectionToOpen:(UIButton *)sender{
for (NSUInteger Increment=0; Increment<headerArray.count; Increment++) {
if (sender.tag == Increment) {
DCOrderHeader* HeaderView= headerArray[Increment];
HeaderView.isOpen = !HeaderView.isOpen;
}
}
// little animation
dispatch_async(dispatch_get_main_queue(), ^{
[UIView transitionWithView:self.tableView
duration:0.55f
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^(void) {
[self.tableView reloadData];
} completion:NULL];
});
}
/// Finally Assign view in header method of table view and provide a height
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 40;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
return [headerArray objectAtIndex:section];
}
// Final Touch
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return headerArray.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
DCOrderHeader* HeaderView = headerArray[section];
if (HeaderView.isOpen == YES) {
return self.someArray.count;
}else{
return 0;
}
}