UITableView Cell Layout - iphone

I am trying to change the look of the tableviewcells by adding columns. I know the normal tableview doesn't allow this. Can someone point me in the right direction to achieve something similar to the attached image? The basic functionality is to have a grid of cells. 3x3 and any of the 9 cells can be clicked and it opens another page. its similar to the image picker but instead of images it would be cells with subtitles etc.
http://www.bronron.com/apps/IpadMenu.jpg
Any ideas?
Thanks in advance.

I would recommend that you try using a UIScrollView instead of a UITableView for this.
Each item in your menu can be a UIImageView, or a UIButton which you add as subviews to your UIScrollView.
The following code can be insterted in viewDidLoad inside your view controller and assumes that you have setup your UISCrollView in interface builder, otherwise you would need to allocate your scroll view inside viewDidLoad.
The code will add a variable number of menu items to a UIScrollView with two columns. To deal with user input you can make all the menu items UIButtons which call associated IBAction methods, or in this case the menuItems are you views, so you can identify which menu item the user is touching by looking at the users touch location within the scroll view, and then carrying out the appropriate action based on this.
UIImageView *menuItem = nil;
//The x and y view location coordinates for your menu items
int x = 0, y = 0;
//The number of items you want in your menu
int numOfItemsToAdd = 10;
//The height and width of your menu items
int menuItemHeight = 50, menuItemWidth = 50;
//The content seize needs to refelect the number of menu items that will be added
//The hieght of the ocnten size is calclutated by multiplying the menu item height by the number of
//menu items devided by the number of menu items that fit across in the width of the view.
[scrollView setContentSize:CGSizeMake(320, menuItemHeight*numOfItemsToAdd];
for(int i=0; i<numOfItemsToAdd; i++){
if(i%2 == 0){//% the number of columns you want in your menu
x = 0;
if(i!=0)
y += menuItemHeight;
}else{
x = menuItemWidth;
}
menuItem = [[UIImageView alloc] initWithFrame: CGRectMake(x, y, menuItemWidth, menuItemHeight)];
//set the center of the menu item in the scroll superviews coordinate system
menuItem.center = CGPointMake(x, y);
//Add the name of the image you want for the menu item
//These strings could be stored in an array and retrieved in order
menuItem.image = [UIImage imageNamed:#"MyImage"];
//Finaly add the menu item to the scorll view
[scrollView addSubview:menuItem];
}

You can go for multi column grid table view layout , where you can define each and every row and column.
you can check this tutorial for Drawing a Grid in a iPhone UITableView – Tabular Cell Data
http://www.iphonedevx.com/?p=153

This is a completely custom view layout and IMHO, not really suitable for a table view. As with anything custom there are many ways to achieve what you want. Here's how I would approach this implementation myself. There may very well be some good open source implementations out there.
GridViewController : UIViewController
This is the top most view controller and has a UIScrollView containing 1 or more pages of GridView objects. This view controller would communicate with a dataSource that provides 0..N objects to display on the individual grid views.
GridView : UIView
Each grid view would be a custom UIViewSubclass that knows how to layout 0 to N objects as dictated by the data provided by the GridViewController dataSource. Each icon in the grid would be an appropriate UIView subclass, maybe UIButton or UIImageView or maybe custom depending on what it needs to look and act like.
More behavior would be added as needed to drag icons around, create new pages, persist state in the data model, etc etc.

Related

Scroll view with dynamically created thumbnails on iPhone and iPad

I need one long scrollable view with 2 thumbnails (wallpapers) in every row.
Every thumbnail has also a button to share and download photo, and when you click the thumbnail it shows full size wallpaper. So I was thinking about making a custom view (200x200) which will contain thumbnail and two buttons, and add them dynamically to scroll view depending how many wallpapers are on server.
Something like this:
NSUInteger i;
int xCoord=0;
int yCoord=0;
int thumbnailWidth=200;
int thumbnailHeight=200;
int buffer = 10;
for (i = 1; i <= [items count]; i++)
{
UIView *aView = [[ThumbnailView alloc] initWithThumnailAtIndex: i ];
aView.frame = CGRectMake(xCoord, yCoord, thumbnailWidth, thumbnailHeight );
[scrollView addSubview:aView];
xCoord += thumbnailWidth + buffer;
yCoord += thumbnailHeight + buffer;
}
[scrollView setContentSize:CGSizeMake(700, yCoord)];
Do you think that is a good way to do this?
Also, how would I handle lazy loading of thumbnails if there are a lot of thumbnails in scrollview?
As everybody else here has said, use a UITableView. I will add that you should use a custom UITableViewCell subclass. Create the class, then use Storyboards to make a table view scene with prototype cells. Set the class of the prototype cell to your cell subclass. Add as many imageview, labels, buttons, whatever nonsense you want to the prototype cell on the storyboard, then hook those up to your custom class using IBOutlets. Now when it's time to display something in the cell, just pass an object or dictionary containing all the info that's needed to the custom cell subclass, and have it populate the various view via the outlets. Here's a tutorial: http://www.techotopia.com/index.php/Using_Xcode_Storyboards_to_Build_Dynamic_TableViews_with_Prototype_Table_View_Cells
I would suggest you use the UITableView with custom UITableViewCell implementations. The tableview will automatically handle the recycling of the cells, so you would not need to worry as much about performance.
You could pre-load all your assets during the view initialization and then simply use them in the tableview's datasource.
I would use a UITableView and each cell would contain both images. Take a look at this answer.
About loading the images, try using EGOImageLoader, is very simple and effective. Here is the Github project.

moving UIImageView form first tapped UIControl to second tapped UIControl

I have 25 UIControls and 10 UIImageView. It looks like this:
Now the images are the UIImageVIews and the grids are the UIControls. What I want is when the user taps at a image and then taps at any of the grids (any blank grids of-course) the UIImageView is then removed from the current superView and added as the subView of the blank grid tapped. For example, if the user taps at the A1 grid first and then in the B2 grid, two actions occur,
UIImageView from A1 grid is removed,
UIImageView is added to B2 grid
This means when the user taps at the image at A1 grid and then taps at the B2 grid, the output window looks like this:
EDIT
So, at a time I need to have track for two UIControls:
1.which one is pressed first, and
2.which one is pressed second. And then remove the UIImageView from the first UIControl and add it to the second UIControl. I have tried giving the UIControls a tag like,
//....
A1.tag = 1;
//...
-(void)a1ViewTapped:(id)sender
{
int i = A1.tag;
[self switch:i];
}
//...
-(void)switch:(int)_tag
{
//....
UIView *view = (UIView*)[self.view viewWithTag:_tag];
[view removeFromSuperview];
//...
}
By this I can track a single UIControl, but need to track two of them.
How can I accomplish this, can anyone help?
UIControl inherits from UIView, so you can add a subview to your UIControl by calling addSubview:.
You can remove your UIImageView from the previous control by calling removeFromSuperview on the UIImageView
edit:
A very simple implementation would be to create a property that holds a reference to the selected UIControl. When the property is nil, then you are in selection mode. Touching up inside a control puts a reference to the control into the property. When the property is not nil, you are looking for a grid control in which to place the image.
You'll also need a way to keep track of whether your UIControl has one of the UIImageView instances as a subview. There are a number of ways to do that. One way would be to subclass UIControl to add a property to it that points to the UIImage it contains. Another way might be to simply examine the subviews of the UIControl to see if it contains one of the images in question. Another way would be to create some data structure to keep track of the positions of the images. How you do it is up to you, and the best way depends on the specifics of your implementation.
Just for the sake of discourse, let's assume you set up an NSMutableDictionary called imageMap that uses the tags of your UIControls as keys and sets references to the images as values. Then you could do something like:
-(void)selectGridControl:(UIView*)view
{
if (selectedControl == nil) // In this case nothing is selected
{
selectedControl = view;
}
else // In this case we are moving the image to the new view
{
UIImageView *selectedImage = [imageMap objectForKey:selectedControl.tag];
if (selectedImage != nil)
{
[selectedImage removeFromSuperview];
[view addSubview:selectedImage];
[imageMap removeObjectForKey:selectedControl.tag];
[imageMap addObject:selectedImage forKey:view.tag];
selectedControl = nil;
}
}
Initializing imageMap and handling cases when the destination control already has an image are left as exercises for the reader.

How to get the visible center of a UITable

I have a standard UITable. When the user scrolls through the rows and then clicks on one of the cells; they will be transfered to another view. There will be some process time from the tap of the cell to the new view. I would like to display a UIActivityIndicator in a view that over lays the center of the UITable. I am not sure though how to obtain the visible center of the UITable.
The code I have:
myView.center = self.tableView.center;
Puts it in the center of the UITable until I start scrolling further and further down. Then the UIActivityIndicator stays up at the top, so it appears UITableView.center does not represent the "Visible Center".
Any tips on how I can achieve this?
Thanks!
Flea
There are two ways to achieve this.
Either you add your activity indicator view to the same view holding the tableView and THEN they can have the same center:
UIView* superview = [tableView superview];
yourActivityIndicator.center = tableView.center;
[superview addSubview:yourActivityIndicator];
or you decide to add your monitor view to the tableView but then the center of this view must be calculated and will depend on the size of indicator view.
CGSize tSize = tableView.frame.size;
CGSize aSize = yourActivityIndicator.frame.size;
yourActivityIndicator.center = CGRectMake(
(tSize.width-aSize.width)*0.5,
(tSize.height-aSize.height)*0.5,
aSize.width,
aSize.height);
[tableView addSubview:yourActivityIndicator];
Put the activity indicator in the tableview's parent instead of in the tableview itself, then it won't scroll with the table view

Setting up multiple UIImageView instances

I would like to create a 4 x 6 grid of UIImageViews that each contain a slightly different image. I would also like to be able to randomly select one of the instances and change it's image.
My question is what's the best way to set up the UIImageViews in a grid formation, perform a few actions between each setup, and randomly pick 1 of the 24 instances once setup is complete. Optimally, I wouldn't have to set up each one by one.
Thanks in advance.
There are different approaches you can take, depending on whether or not you want to use Interface Builder to layout your grid.
One option is to layout your 24 UIImageViews as subviews of a common parent view within IB. On the View Attributes tab you can set a "Tag" number from 1 to 24 to differentiate your UIImageViews. Then in your code you can use [parentView viewWithTag:tagNumber] to access each UIImageView.
If you prefer to do things more programmatically, you could create each of your UIImageViews in a loop in the loadView method of your UIViewController subclass. You could maintain an array (or an array of arrays corresponding to rows and columns) as a property of your controller, and store a reference to each of these image views as you create them. For each UIImageView you create, set its imageView.frame property to define its position, then call [view addSubview:imageView] to add it to the parent view.
I would do it programmatically for your sake.
NSArray *myViews = //I assume you can create an array of views
for (int i=0; i<rows; ++i) {
for (int j=0; j<columns; ++j) {
UIImageView *thisImageView = [myViews objectAtIndex:(i*columns+j)];
CGSize size = thisImageView.image.size;
[thisImageView setFrame:CGRectMake(j*size.width, i*size.height, size.width, size.height)];
[self.view addSubview:thisImageView];
}
}
//Later to pick one randomly
UIImageView *myRandomView = [myViews objectAtIndex:(arc4random()%[myViews count])];
[myRandomView setImage:myNewImage];

How do I push grouped tables down in the view on the Iphone?

Below shows the default position when you add a grouped table to a view? How do I push the entire grouped table down in the view?
(source: pessoal.org)
You can assign a transparent view with a fixed height to the tableHeaderView property of the tableView. This will push the table contents down by the height of the transparent view.
You can do this from your UITableViewController's viewDidLoad:
// force the table down 70 pixels
CGRect headerFrame = self.tableView.bounds;
headerFrame.size.height = 70;
UIView *header = [[UIView alloc] initWithFrame: headerFrame];
header.backgroundColor = [UIColor clearColor];
self.tableView.tableViewHeader = header;
[header release];
Look at the delagate to the UITableView.
You will find a property 'heightForHeaderInSection'.
For section 0 just make the header larger (default is 0) it will push the table down the view.
If you are moving the table down, you undoubtedly wish to use the space you gain to add UI elements.
At that point, consider building the page in IB. You can resize the table view to be where you like and put the UI elements above the table. You can use a UIViewController to manage the page and add the UITableViewDelegate/Datasource protocol methods so that you can wire the UITableView back to your view controller as a delegate... then you can also wire the other UI elements to the same view controller.
The simplest way to do it is probably just to modify the frame for the tableview. You'll need to get a reference to the tableview in your controller either through an IBOutlet or by finding the view in the view hierarchy OR you can change the frame in Interface Builder.
In code something like:
tableView.frame = CGRectMake(0.0, 200.0, 320.0, 280.0);
Would position the tableview down the screen and limit its height - the dimensions you use will be dependent on whether you had a tab bar on the view and things like that.
In interface build just select the tableview, then choose the Size inspector (the inspector tab with the ruler icon) and set the height and y offset to shift it down the view.