How to create a grid of UIButtons with dynamic values in iOS? - ios

I am trying to create a grid of UIButtons . The row and column values are dynamic.I know how to create a grid .However making it using dynamic values is the problem.
-(void)makeLayoutWithMinRow:(int)minRow maxRow:(int)maxRow minColumn:(int)minColumn maxColumn:(int)maxColumn {
NSInteger intLeftMargin = 10; // horizontal offset from the edge of the screen
NSInteger intTopMargin = 10; // vertical offset from the edge of the screen
NSInteger intYSpacing = 30; // number of pixels between the button origins (vertically)
NSInteger intXTile;
NSInteger intYTile;
NSInteger width;
width = ((self.layoutView.frame.size.width-(maxColumn * 5))/maxColumn);
for (int y = minRow; y < maxRow; y++)
{
for (int x = minColumn; x < maxColumn; x++)
{
intXTile = (x * width) + intLeftMargin;
intYTile = (y * intYSpacing) + intTopMargin;
UIButton *buttons[x][y] = [[UIButton alloc] initWithFrame:CGRectMake(intXTile, intYTile, width, 15)];
//Here I get error : Variable-sized object may not be initialised.
[self.layoutView addSubview:buttons[x][y]];
}
}
}
I did try the option as suggested by Cornelius below to store the button in array.
sButton = [[UIButton alloc] initWithFrame:CGRectMake(intXTile, intYTile, width, 15)];
[buttons addObject:sButton];
How to add these buttons to view in this case?
for (UIButton *obj in buttons) {
[self.layoutView addSubview:obj]; //Doesn't work
}

Here is the one which replaces UICollectionView.I have tried
PSTCollectionView and it gives you the expected results. Try this.
You can use PSTCollectionView.

Use UICollectionView to create such grid.
Here is a tutorial. For your case, it's UIButton instead of UIImageView in this tutorial.

It seems all you're trying to achieve here is a lookup for the buttons later.
So you will need a variable (or property) on your instance to hold the references, not just a local variable during creation.
There are many ways of solving your problem, one simple yet efficient way to store the references is a 'NSMutableDictionary'.
Declare a property in your class:
#property (nonatomic, strong) NSMutableDictionary *buttonDictionary;
Set it up in your loop:
_buttonDictionary = [[NSMutableDictionary alloc] init];
In your loop, encode the x/y position, for example using an NSIndexPath, abusing row/section:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:y inSection:x];
Create button and add to your dictionary and superview:
UIButton *freshButton = [UIButton buttonWithType:...]; // Much better than initWithFrame
freshButton.frame = ...;
_buttonDictionary[indexPath] = freshButton;
[self.layoutView addSubview:freshButton];
If you want to look up a button later by x/y indices, just do
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:y inSection:x];
UIButton *requestedButton = _dictionary[indexPath];
Please note that I'm using the [] syntax on dictionaries here - you may use the classic methods objectForKey: and setObject:forKey: instead.

You can use UICollectionView and set the dynamic values as you desired or customized as per your requirement. This is very easy and effective way to develop grid view. Here I explained a simple code for grid view:
Like this :
#interface DashboardViewController : AbstractController <UICollectionViewDataSource, UICollectionViewDelegate>{
NSMutableArray *dataSource;
}
#property (nonatomic, strong) UICollectionView *dashboardCollectionView;
#property (nonatomic, strong) ModulesDataModel *modulesDataModel;
#end
/*****************.m********************/
- (void)viewDidLoad {
[super viewDidLoad];
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
_dashboardCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 135, 1024, 537) collectionViewLayout:layout];
[_dashboardCollectionView setDataSource:self];
[_dashboardCollectionView setDelegate:self];
[_dashboardCollectionView registerClass:[CellMaster class] forCellWithReuseIdentifier:#"Reuse"];
[_dashboardCollectionView setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:_dashboardCollectionView];
dataSource = [NSMutableArray arrayWithArray:#"your objects"];
}
#pragma mark - Collection View Datasource and Delegate Methods
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake( 22.0, 22.0, 22.0, 22.0);
}
-(CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section{
return 22.0f;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{
return 15.0f;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(312,150);
}
- (NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return dataSource.count;
}
- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
// Find the enum for this module and load the correct tile
self.modulesDataModel = [dataSource objectAtIndex:indexPath.item];
CellMaster * cell;
cell = (CellMaster *)[collectionView dequeueReusableCellWithReuseIdentifier:#"Reuse" forIndexPath:indexPath];
cell.tag = indexPath.item;
cell.iconImage.image = [UIImage imageNamed:#""];
cell.lblModuleName.text = self.modulesDataModel.moduleName;
cell.lblModuleName.textColor = self.modulesDataModel.color;
cell.btnInfo.tag = indexPath.item;
[cell.btnInfo addTarget:cell action:#selector(didPressInfoIcon:) forControlEvents:UIControlEventTouchUpInside];
cell.delegate = self;
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
// Enum for tile that was clicked
self.modulesDataModel = [dataSource objectAtIndex:indexPath.item];
}
Hope it would help you.

I made a little tweaks to your code and made it work with this:
You must manually initialize that array: meaning you have to say how big it's gonna be
#interface ViewController ()
#property (nonatomic) UIView *layoutView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.layoutView = [[UIView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.layoutView];
[self makeLayoutWithMinRow:0 maxRow:5 minColumn:0 maxColumn:5];
}
- (UIColor *)randomColor {
CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0
CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from white
CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from black
UIColor *color = [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1];
return color;
}
-(void)makeLayoutWithMinRow:(int)minRow maxRow:(int)maxRow minColumn:(int)minColumn maxColumn:(int)maxColumn {
NSInteger intLeftMargin = 10; // horizontal offset from the edge of the screen
NSInteger intTopMargin = 10; // vertical offset from the edge of the screen
NSInteger intYSpacing = 30; // number of pixels between the button origins (vertically)
NSInteger intXTile;
NSInteger intYTile;
NSInteger width;
id buttons[maxRow][maxColumn];
width = ((self.layoutView.frame.size.width-(maxColumn * 5))/maxColumn);
for (int y = minRow; y < maxRow; y++)
{
for (int x = minColumn; x < maxColumn; x++)
{
intXTile = (x * width) + intLeftMargin;
intYTile = (y * intYSpacing) + intTopMargin;
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(intXTile, intYTile, width, 15)];
button.backgroundColor = [self randomColor];
buttons[x][y] = button;
[self.layoutView addSubview:buttons[x][y]];
}
}
}
#end

You are trying to create a button-array or something like that here?
UIButton *buttons[x][y] = [[UIButton alloc] initWithFrame:CGRectMake(intXTile, intYTile, width, 15)];
What you really want to do is create the button object and then add it to an array (if you want to access it afterwards, otherwise it's enough to add it as a subview):
// Outside the for loop, probably as an instance variable or property:
NSMutableArray *buttons = [[NSMutableArray alloc] init];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(intXTile, intYTile, width, 15)];
[buttons addObject:button];
You may even need to put that buttons array inside another array to get the multidimensional aspect right, or use a NSMutableDictionary with corresponding keys.

Related

Obj-C- Update UICollectionView data without reloading entire collectionView?

I have a UICollectionView where when cells are selected, they change to a color selected by the user. To paint the full picture: The color is selected by the user from a color wheel (UIImageView) with a tap gesture attached to it.
That said, when the user taps a new color, say purple (and resets the defined rString, bString & gString...) after selecting 3 cells and making them green, I want to reload the color they're using without wiping the initial 3 selected green cells from the Collection View. How can I accomplish this?
See code below.
ViewController.m
#interface ViewController () {
CGPoint lastPoint;
NSInteger rString;
NSInteger bString;
NSInteger gString;
UIColor *colour;
}
#property (strong, nonatomic, nullable) NSIndexPath *trackingCellIndexPath;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.ringCollectionView.allowsMultipleSelection = YES;
UITapGestureRecognizer * tapRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(tapGesture:)];
[self.colorWheel addGestureRecognizer:tapRecognizer];
self.colorWheel.userInteractionEnabled = YES;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"RingCollectionViewCell" forIndexPath:indexPath];
if (!cell.selectedBackgroundView) {
cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.bounds];
cell.selectedBackgroundView.backgroundColor = [UIColor grayColor];
} else {
cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.bounds];
cell.selectedBackgroundView.backgroundColor = [UIColor colorWithRed:rString/255.0 green:gString/255.0 blue:bString/255.0 alpha:1.0];
}
if ((indexPath.row >=9 && indexPath.row <=14) || ((indexPath.row >=17 && indexPath.row < 23) || (indexPath.row >=25 && indexPath.row <=30) || (indexPath.row >=33 && indexPath.row <=38))) {
NSLog(#"NOT AVAILABLE SORRY");
cell.backgroundColor = [UIColor whiteColor];
[cell setUserInteractionEnabled:NO];
}
return cell;
}
-(void)tapGesture:(UITapGestureRecognizer *)recognizer {
CGPoint location = [recognizer locationInView:recognizer.view];
CGPoint p = { round(location.x), round(location.y) };
_colorView.backgroundColor = [self colorInViewAtPoint:p];
UIColor *mylovelycolor = [self colorInViewAtPoint:p];
const CGFloat *components = CGColorGetComponents(mylovelycolor.CGColor);
NSLog(#"Red: %f", components[0]);
NSLog(#"Green: %f", components[1]);
NSLog(#"Blue: %f", components[2]);
NSLog(#"Alpha: %f", CGColorGetAlpha(mylovelycolor.CGColor));
int red = components[0] * 255;
int green = components[1] * 255;
int blue = components[2] * 255;
NSString *red1 = [#(red) stringValue];
NSString *green1 = [#(green) stringValue];
NSString *blue1 = [#(blue) stringValue];
NSInteger redInt = [red1 integerValue];
NSInteger greenInt = [green1 integerValue];
NSInteger blueInt = [blue1 integerValue];
rString = [red1 integerValue];
bString = [blue1 integerValue];
gString = [green1 integerValue];
self.redValue.text = red1;
self.greenValue.text = green1;
self.blueValue.text = blue1;
NSMutableString *str1 = [NSMutableString string];
for(NSInteger numberCopy = redInt; numberCopy > 0; numberCopy >>= 1)
{
[str1 insertString:((numberCopy & 1) ? #"1" : #"0") atIndex:0];
}
NSMutableString *str2 = [NSMutableString string];
for(NSInteger numberCopy = greenInt; numberCopy > 0; numberCopy >>= 1)
{
[str2 insertString:((numberCopy & 1) ? #"1" : #"0") atIndex:0];
}
NSMutableString *str3 = [NSMutableString string];
for(NSInteger numberCopy = blueInt; numberCopy > 0; numberCopy >>= 1)
{
[str3 insertString:((numberCopy & 1) ? #"1" : #"0") atIndex:0];
}
self.binaryString = [NSString stringWithFormat:#" %# %# %#", str1, str2, str3];
}
You need to track your user-selected colors in your data model.
In cellForItemAtIndexPath you want to set the cell's background color (or whatever element you're using) to the data element color.
When the user has one or more cells selected, and taps your "colorWheel," update your data model and then either set the cell elements directly or reload those cells.
Here is a very simple example...
MyDataObject.h
//
// MyDataObject.h
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
#interface MyDataObject : NSObject
#property (strong, nonatomic) UIColor *userColor;
#end
NS_ASSUME_NONNULL_END
MyDataObject.m
//
// MyDataObject.m
//
#import "MyDataObject.h"
#implementation MyDataObject
#end
MyCollectionViewCell.h
//
// MyCollectionViewCell.h
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
#interface MyCollectionViewCell : UICollectionViewCell
#property (strong, nonatomic) UILabel *label;
#end
NS_ASSUME_NONNULL_END
MyCollectionViewCell.m
//
// MyCollectionViewCell.m
//
#import "MyCollectionViewCell.h"
#implementation MyCollectionViewCell
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit {
_label = [UILabel new];
_label.textAlignment = NSTextAlignmentCenter;
_label.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];
_label.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:_label];
UILayoutGuide *g = [self.contentView layoutMarginsGuide];
[NSLayoutConstraint activateConstraints:#[
[_label.widthAnchor constraintEqualToAnchor:g.widthAnchor multiplier:0.8],
[_label.heightAnchor constraintEqualToAnchor:g.heightAnchor multiplier:0.8],
[_label.centerXAnchor constraintEqualToAnchor:g.centerXAnchor],
[_label.centerYAnchor constraintEqualToAnchor:g.centerYAnchor],
]];
self.contentView.layer.borderColor = [UIColor yellowColor].CGColor;
}
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
self.contentView.layer.borderWidth = selected ? 2 : 0;
}
#end
MyTestViewController.h
//
// MyTestViewController.h
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
#interface MyTestViewController : UIViewController <UICollectionViewDataSource, UICollectionViewDelegate>
#end
NS_ASSUME_NONNULL_END
MyTestViewController.m
//
// MyTestViewController.m
//
#import "MyTestViewController.h"
#import "MyCollectionViewCell.h"
#import "MyDataObject.h"
#interface MyTestViewController ()
{
NSMutableArray <MyDataObject *>*myCellData;
UICollectionView *collectionView;
}
#end
#implementation MyTestViewController
- (void)viewDidLoad {
[super viewDidLoad];
UICollectionViewFlowLayout *fl = [UICollectionViewFlowLayout new];
fl.itemSize = CGSizeMake(50, 50);
fl.scrollDirection = UICollectionViewScrollDirectionHorizontal;
collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:fl];
collectionView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:collectionView];
UILayoutGuide *g = [self.view safeAreaLayoutGuide];
[NSLayoutConstraint activateConstraints:#[
[collectionView.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:20.0],
[collectionView.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:-20.0],
[collectionView.heightAnchor constraintEqualToConstant:240.0],
[collectionView.centerYAnchor constraintEqualToAnchor:g.centerYAnchor],
]];
// a few color views to tap, and an
// "Instructions" label
UILabel *label = [UILabel new];
label.text = #"Tap a color to change the selected cells:";
UIStackView *stack = [UIStackView new];
NSArray *colors = #[
[UIColor redColor],
[UIColor greenColor],
[UIColor blueColor],
[UIColor systemYellowColor],
[UIColor systemTealColor],
];
for (UIColor *c in colors) {
UIView *v = [UIView new];
v.backgroundColor = c;
UITapGestureRecognizer *t = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(gotTap:)];
[v addGestureRecognizer:t];
[stack addArrangedSubview:v];
}
stack.spacing = 20.0;
stack.distribution = UIStackViewDistributionFillEqually;
label.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:label];
stack.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:stack];
[NSLayoutConstraint activateConstraints:#[
[stack.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:20.0],
[stack.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:-20.0],
[stack.bottomAnchor constraintEqualToAnchor:g.bottomAnchor constant:-20.0],
[stack.heightAnchor constraintEqualToConstant:40.0],
[label.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:20.0],
[label.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:-20.0],
[label.bottomAnchor constraintEqualToAnchor:stack.topAnchor constant:-4.0],
]];
collectionView.dataSource = self;
collectionView.delegate = self;
collectionView.allowsMultipleSelection = YES;
[collectionView registerClass:MyCollectionViewCell.class forCellWithReuseIdentifier:#"c"];
// create 50 objects for our data
myCellData = [NSMutableArray new];
for (int i = 0; i < 50; i++) {
MyDataObject *obj = [MyDataObject new];
obj.userColor = [UIColor redColor];
[myCellData addObject:obj];
}
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return myCellData.count;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// dequeue a cell
MyCollectionViewCell *c = (MyCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"c" forIndexPath:indexPath];
// get the data object
MyDataObject *obj = (MyDataObject *)[myCellData objectAtIndex:indexPath.item];
// set cell's contentView.backgroundColor to the data object's .userColor
c.contentView.backgroundColor = obj.userColor;
// set the cell's label text
c.label.text = [NSString stringWithFormat:#"%ld", indexPath.item];
return c;
}
- (void)gotTap:(UITapGestureRecognizer *)g {
if (collectionView.indexPathsForSelectedItems.count == 0) {
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:#"Error"
message:#"No cells are selected!"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* okButton = [UIAlertAction
actionWithTitle:#"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
}];
[alert addAction:okButton];
[self presentViewController:alert animated:YES completion:nil];
return;
}
UIView *v = g.view;
if (v) {
// get the background color from the tapped view
UIColor *color = v.backgroundColor;
// loop through selected cells
for (NSIndexPath *p in collectionView.indexPathsForSelectedItems) {
// update the object in our data
[myCellData objectAtIndex:p.item].userColor = color;
// get a reference to the cell
MyCollectionViewCell *c = (MyCollectionViewCell *)[collectionView cellForItemAtIndexPath:p];
// set its background color
c.contentView.backgroundColor = color;
// if we want to auto-deselect the cells
[collectionView deselectItemAtIndexPath:p animated:YES];
}
}
}
#end
So,
our data object has just a single property: userColor
our cell class has a centered label
our controller
creates a horizontal scrolling collection view
creates an array of 50 data objects, with default userColor of red
adds 5 color views to select from
When a cell is selected, it will be outlined in yellow. When a color view is tapped, we:
update the data model for the currently selected cells
set the background color of the contentView of the currently selected cells
deselect the currently selected cells
It looks like this:
then we select cells 5, 9, 14:
tap on the Green view:
then we select cells 16, 17, 18:
tap on the Blue view:
then we scroll a little and select cells 17, 21, 24, 25, 26:
tap on the Yellow view:
and so on.

Adjusting code to include Lazy loading - scrollview and images

Im trying to refactor my code for better memory management and performance. I have an array of 12 images, but I want to load them as needed, not all at the same time. So maybe the current image -1, the current image and the current image +1. I viewed some of the answers on SO but found them unclear. I felt it would be clearer if I posted my code for reference.
//scroll view set up
- (void)scrollViewSetUp
{
self.scrollview.delegate = self;
for (int i = 0; i < _images.count; i++)
{
CGRect frame;
frame.origin.x = self.scrollview.frame.size.width * i;
frame.size = self.scrollview.frame.size;
self.scrollview.pagingEnabled = YES;
UIImageView *subview = [[UIImageView alloc] initWithFrame:frame];
subview.image = [UIImage imageNamed:[_images objectAtIndex:i]];
[self.scrollview addSubview:subview];
}
self.scrollview.contentSize = CGSizeMake(self.scrollview.frame.size.width * _images.count, self.scrollview.frame.size.height);
self.automaticallyAdjustsScrollViewInsets = NO;
//page control ie .... at bottom of
self.pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(100.0,0.0,100.0,40.0)];
[self.pageControl setNumberOfPages:_images.count];
[self.pageControl setCurrentPage:0];
self.pageControl.pageIndicatorTintColor = [UIColor lightGrayColor];
self.pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
[self.pageControl setBackgroundColor:[UIColor clearColor]];
[self.viewForPageControl addSubview:self.pageControl];
[self.viewForPageControl setBackgroundColor:[UIColor clearColor]];
}
#pragma mark - UIScrollView Delegate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
int newOffset = scrollView.contentOffset.x;
int newPage = (int)(newOffset/(scrollView.frame.size.width));
[_pageControl setCurrentPage:newPage];
}
Any advice or direction is greatly appreciated.
As per Gman's request I reposted my comment.
This tutorial will help you:
http://www.raywenderlich.com/10518/how-to-use-uiscrollview-to-scroll-and-zoom-content
You could try to reuse your UIImageView as they go offscreen... but you'll be just trying to redo what UITableview already does. UITableView with a custom UITableViewCell would take care of notifying you when new cells comes visible and dequeuing the ones that are offscreen.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"yourCustomImageCell";
//look if there are cells that could be reused
CustomImageCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) { //if not, create a new one
cell = [[CustomImageCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
//Set your image here
return cell;
}
Not sure if this is the best way of doing it, but it's an option.
You can set the tag property on your UIImageView to correspond to your index in your loop when setting the scrollView.
Then in your scrollViewDidEndDecelerating method:
for (int i = 0; i < _salonImages.count; i++)
{
if(i == (newPage-1))
{
UIImageView *imgView = (UIImageView*)[self.scrollView viewWithTag:newPage-1];
imgView.image = [_images objectAtIndex:newPage-1];
}
else if(i == newPage)
{
UIImageView *imgView = (UIImageView*)[self.scrollView viewWithTag:newPage];
imgView.image = [_images objectAtIndex:newPage];
}
else if(i == (newPage + 1 ))
{
UIImageView *imgView = (UIImageView*)[self.scrollView viewWithTag:newPage+1];
imgView.image = [_images objectAtIndex:newPage+1];
}
else
{
UIImageView *imgView = (UIImageView*)[self.scrollView viewWithTag:i];
imgView.image = nil;
}
}

strage uitableview cell behavior: view moves inside cell

I am having some strange uitableview behavior- my customs cells have a little extra space around them that I cannot fix. I can also move the cells in that space. I have attached a couple of pictures as my English is not letting me to explain better. Any ideas on what might the issue be? I can post my code for my custom cell but it even happens with admob add cell, so I am not sure it is related to the custom cell.
EDIT: Added code for heights
EDIT2: I changed the scroll view alloc to
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width,self.bounds.size.height)];
And it fixed the moving of the cell. But that white line is still there.
Table View
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// return (self.tableViewHome.bounds.size.height-49-6-self.tableViewHome.tableHeaderView.bounds.size.height-self.tableViewHome.tableFooterView.bounds.size.height-GAD_SIZE_320x50.height)/3;
float height = self.tableViewHome.frame.size.height-self.tableViewHome.tableHeaderView.bounds.size.height-30.0;
if (indexPath.item==5)
{
height=kGADAdSizeBanner.size.height;
}
else
{
if (indexPath.item==1 || indexPath.item==3)
{
height=15.0;
}
else
{
if (indexPath.item==0 || indexPath.item==2 || indexPath.item==4)
{
height=(height-kGADAdSizeBanner.size.height)/3;
}
}
}
NSLog(#"Height:%f",height);
return height;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 0.1;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 0.1;
}
Custom Cell
-(id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[scrollView setShowsHorizontalScrollIndicator:NO];
[scrollView setShowsVerticalScrollIndicator:NO];
// NSInteger viewcount= 3;
// for(int i = 0; i< viewcount; i++) {
// CGFloat x = 2 * self.bounds.size.width;
todayView = [HomeTodayView homeTodayView];
todayView.frame = CGRectMake(0, 0,self.bounds.size.width, self.bounds.size.height);
todayView.backgroundColor = [UIColor redColor];
avgView = [HomeAvgView homeAvgView];
avgView.frame = CGRectMake(self.bounds.size.width, 0, self.bounds.size.width, self.bounds.size.height);
// [[HomeTodayView alloc] initWithFrame:
todayView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
avgView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[scrollView addSubview:todayView];
[scrollView addSubview:avgView];
scrollView.contentSize = CGSizeMake(self.bounds.size.width *2, self.bounds.size.height+100);
scrollView.pagingEnabled = YES;
scrollView.bounces = NO;
[self addSubview:scrollView];
}
return self;
}
Try This:
[table setSeparatorStyle:UITableViewCellSeparatorStyleNone];
NOTE:- table = your tableview name.
If this does not work then please check that your custom cell height and the row height of tableView are same?

iOS 7 UITableView grouped style hide my cells

I have created an UITableView in my app programatically. I have a strange problem. I have never seen this and I think everything is alright. It seems like all the table goes down and I only can see the first row. I want to create the same UITableView grouped as the settings tableViews in iOS7
But the Image in iOS 6 it is strange too.. I have written a NSLog and the height is 132 = 3 items * 44 height cell.
Here it is the code.
static float x = 10.0;
static float y = 80.0;
static NSString *CategoryCellIdentifier = #"CategoryCell";
static float kHeightCell = 44.0;
#interface LKLHomeViewController ()
#property (nonatomic, strong) NSArray *itemsArray;
#property (nonatomic, strong) UITableView *categoryTableView;
#end
#implementation LKLHomeViewController
#synthesize itemsArray;
#synthesize categoryTableView;
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor grayColor]];
// Adding tableView to self.view
[self.view addSubview:self.categoryTableView];
}
#pragma mark - Custom getter
-(NSArray *)itemsArray
{
if(!itemsArray){
itemsArray = #[#"Near", #"Kind of" , #"More.."];
return itemsArray;
}
return itemsArray;
}
- (UITableView *)categoryTableView
{
//custom init of the tableview
if (!categoryTableView) {
CGFloat height = kHeightCell * [self.itemsArray count];
CGFloat width = self.view.frame.size.width - (x*2);
CGRect tableFrame = CGRectMake(x, y, width, height);
// regular table view
categoryTableView = [[UITableView alloc] initWithFrame:tableFrame style:UITableViewStyleGrouped];
categoryTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
categoryTableView.delegate = self;
categoryTableView.dataSource = self;
categoryTableView.backgroundColor = [UIColor whiteColor];
[categoryTableView setScrollEnabled:NO];
[[categoryTableView layer] setCornerRadius:5.0f];
return categoryTableView;
}
return categoryTableView;
}

Multiple TableViews in one View - Array of data sources?

I'm trying to recreate a view controller similar to the "weather" app that comes stock on the iPhone. I've got a scrollview that contains an individual tableview per page, and I'm struggling to figure out a way to specify the data for each table view.
The tricky part is that the info in each tableview and the tableviews themselves change based on user defaults. Basically, I have an Array of dictionaries stored in user defaults, and each object in this array has its own tableview. Each dictionary contains a title, a lat and a long. When I create the tables, I also use the lat and long to get some data from the internet via an api call and parser. Here's the code:
- (void)setupScrollView
{
scrollView.delegate = self;
[self.scrollView setBackgroundColor:[UIColor clearColor]];
[scrollView setCanCancelContentTouches:NO];
scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView.clipsToBounds = YES;
scrollView.scrollEnabled = YES;
scrollView.pagingEnabled = YES;
scrollView.showsHorizontalScrollIndicator = NO;
//this is an array of dictionaries that hold a location title, as well as a lat and lng.
NSArray *arrayForLocations = [NSArray arrayWithArray:[appDelegate.defaults objectForKey:#"arrayOfLocationDicts"]];
NSLog(#"Array of Location Dicts holds: %#",arrayForLocations);
for (int i = 0; i < arrayForLocations.count; i++) {
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
[self.scrollView addSubview:subview];
UITableView *tbView = [[UITableView alloc]initWithFrame:CGRectMake(0, 40, scrollView.frame.size.width, scrollView.frame.size.height - 40)];
tbView.backgroundColor = [UIColor grayColor];
tbView.tag = i;
tbView.delegate = self;
tbView.dataSource = self;
[subview addSubview:tbView];
UILabel *locationLabel = [[UILabel alloc]initWithFrame:CGRectMake(5, 5, 260, 40)];
locationLabel.textColor = [UIColor blackColor];
locationLabel.text = [[arrayForLocations objectAtIndex:i]objectForKey:#"location_address"];
[subview addSubview:locationLabel];
pageControl.numberOfPages = [arrayForLocations count];
//get coordinate from dictionary
CLLocationCoordinate2D eventCoordinate;
eventCoordinate.latitude = [[[arrayForLocations objectAtIndex:i]objectForKey:#"location_latitude"]floatValue];
eventCoordinate.longitude = [[[arrayForLocations objectAtIndex:i]objectForKey:#"location_longitude"]floatValue];
//turn coordinate into data
SDJConnection *connection = [[SDJConnection alloc]init];
NSMutableArray *singleDataSource = [connection getEventInfoWithCoordinate:eventCoordinate];
//store data in array
[arrayOfDataSources addObject:singleDataSource];
NSLog(#"array of Data Sources in the scrollsetup: %#",arrayOfDataSources);
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * arrayForLocations.count, self.scrollView.frame.size.height);
}
So now my problem is telling each of these tables what data to display. My first thought was to set the tag of the table, as I do above, and then have something like this in the cellForRowAtIndexPath -
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
int i = tableView.tag;
if (tableView.tag = i) {
cell.textLabel.text = [[[arrayOfDataSources objectAtIndex:i]objectAtIndex:indexPath.row]eventTitle];
}
that unfortunately hasn't been working for me correctly. Does anyone have any thoughts as to how to get this done?
Thanks!!
For sure
if (tableView.tag = i) {
should be
if (tableView.tag == i) {
and even then, it's an odd construct -- not sure what you're trying to achieve there. You set the i to the tag and then you check to see if the tag is i? Doesn't really make sense -- that's where I'd suggest you take a close look and rethink your logic.

Resources