Hi am curious how I would go about implementing a view like (See below) Similar to the one used for the iPhone photo application. My initial idea was a table view with each cell holding 4 images, can anyone point me in the right direction. I am particularly interesting in using APIs from Apple so not too bothered about 3rd party APIs / Controllers at this stage.
Yup, as you say, a table view would work, with each of the 4 things (/row) being an UIButton with a custom image. You have to make sure that the table row itself isn't selectable though. (UITableView Setting some cells as "unselectable") Make sure to use table view cell caching if you're going to have a lot of rows.
The actual table view cell could be a UITableViewCell subclass or just the normal one, with some subviews added to its contentView.
I would suggest Three20 API. This is the API used to build the Facebook iPhone app and has a very very large collection of UI elements, including many photo management UIs.
The thumbnail viewer looks like (from their site):
On the iOS, this work is mostly done for you. Check Apple's docs for MPMediaPickerController.
AQGridView is FOSS and is used in many high profile applications like the Kobo reader and Netflix Actors.
You need to use UIScrollView and with a bunch of UIImageViews or UIButtons(with image as background image). this code uses Buttons on scroll view. Also u wud need a function to generate thumbnails, unless ur using the asset library in which case the function is already there.
[scrollview setContentSize:CGSizeMake(320, (items*itemWidth)];
for (int i = 0; i < [items count]; i++) {
if (i % 4 == 0) {
y+=1;
x = 0;
}
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setBackgroundImage:[UIImage imageWithCGImage:[items objectAtIndex:i]] forState:UIControlStateNormal];
CGRect rect2 = myButton.frame;
rect2.size.height = kScrollObjHeight2;
rect2.size.width = kScrollObjWidth2;
rect2.origin.y = 10 + (y * 70) + (y *5);
rect2.origin.x = 8 + (x * kScrollObjWidth2) + (x *8);
myButton.frame = rect2;
myButton.tag = i; // tag our images for later use when we place them in serial fashion
x = x + 1;
[myButton addTarget:self action:#selector(clickFunction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:myButton];
[scrollview addSubview:myButton];
}
};
[scrollview setBackgroundColor:[UIColor blackColor]];
[scrollview setCanCancelContentTouches:NO];
scrollview.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollview.clipsToBounds = YES; // default is NO, we want to restrict drawing within our scrollview
scrollview.scrollEnabled = YES;
scrollview.pagingEnabled = YES;
Related
I am new to iPhone programming.
Using below code I can able to download and displaying all images form server. But in server I have more than some 1000s of images are there. so Using below code I can able to download and displaying in scrollview as 3*3 thumbnail.
But what I want means first I have to download and display 15 images in scrollview as 3*3 thumbnail.
If I scroll down means i have to show activity indicator then download next form 16 to 30 images, similarly again if I scroll means I want to download and display 31 to 45 images in thumbnail.
I dont want to download all images form server.
Can any tell me please how can I do this.
- (void)viewDidLoad
{
URLs = [[NSMutableArray alloc]init];
for (NSString *path in latestiamge)
{
NSURL *URL = [NSURL URLWithString:path];
if (URL)
{
[URLs addObject:URL];
}
else
{
NSLog(#"'%#' is not a valid URL", path);
}
}
self.imageURLs = URLs;
myScrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0.0, 84.0, 320.0, 840.0)];
myScrollView.delegate = self;
myScrollView.contentSize = CGSizeMake(320.0, 840.0);
myScrollView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:myScrollView];
float horizontal = 2.0;
float vertical = 2.0;
for(int i=0; i<[imageURLs count]; i++)
{
if((i%3) == 0 && i!=0)
{
horizontal = 5.0;
vertical = vertical + 100.0 + 5.0;
}
CGRect frame;
frame.size.width=100.0;
frame.size.height=100.0;
frame.origin.x=0;
frame.origin.y=0;
AsyncImageView *imageView = [[AsyncImageView alloc] initWithFrame:frame];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
imageView.tag = i;
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(actionHandleTapOnImageView:)];
imageView.userInteractionEnabled = YES;
[imageView addGestureRecognizer:singleTap];
[myScrollView addSubview:imageView];
[myScrollView addSubview:imageView];
horizontal = horizontal + 100.0 + 5.0;
}
[myScrollView setContentSize:CGSizeMake(320.0, vertical + 3900.0)];
[super viewDidLoad];
}
Well there is a good and basic class you can use for downloading and displaying images asynchronously .
SDWebImage
Doing everything yourself as you currently are is more effort than is required and not good for memory management. Consider using a table or collection view to manage the scrolling so you don't have so many views loaded at the same time and so you don't need code for the full layout of everything.
You're already using AsyncImageView, it will work if you add a number of them to the cells you're going to display and configure them as requested by the delegate/dataSource methods.
You should also think about acting as the scroll view delegate and monitoring the scroll completion. If the user has scrolled to the current bottom, you could add a footer view with an activity indicator, start a load of the next page from the server and then reload the view and remove the footer when the new page is downloaded.
From what I can understand from your question, you want to create a image grid with three images in a row. But your approach is wrong...!
Do not use scrollView but use a UITableView. I think you can use UICollectionView if you are targeting iOS 6.0 or above.
Here is what you need to do :
Create custom UITableViewCell with number of images you need in a row. You can make this dynamic too by passing number of grid items you need while creating the cell and creating the and positioning those views in the cell as subviews.
Reuse the cells in the table to populate the grid.
You can cache images for better performance, I would suggest you to use SDWebImage
In cellForRowAtIndexPath you can configure all the gridItems.
Do you need more help...??
I have create a labels with in the scroll view. The for loop count is more than 1000. At the time the scroll is very slow. If the data is less amount (200, 300, ...) at the time its scroll smoothly. I am using the below code for create label.
UILabel *modelLabel;
UIButton *modelButton;
for (int i = 0; i < [modelArray count]; i++)
{
modelButton = [UIButton buttonWithType:UIButtonTypeCustom];
modelButton.frame = CGRectMake(0.0, (i * LABEL_HEIGHT), LABEL_WIDTH, LABEL_HEIGHT);
modelButton.tag = i+100;
[modelButton addTarget:nil action:#selector(modelButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[modelScrollView addSubview:modelButton];
modelLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, (i * LABEL_HEIGHT), LABEL_WIDTH, LABEL_HEIGHT)];
modelLabel.text = [NSString stringWithFormat:#"%#", [[modelArray objectAtIndex:i] valueForKey:#"Model"]];
modelLabel.tag = i+1000;
modelLabel.backgroundColor = [UIColor clearColor];
modelLabel.textColor = [UIColor grayColor];
modelLabel.alpha = 0.5;
modelLabel.textAlignment = UITextAlignmentCenter;
modelLabel.font = EUROSLITE_FONT(14);
[modelScrollView addSubview:modelLabel];
}
[modelScrollView setContentSize:CGSizeMake(280.0, ([modelArray count] * LABEL_HEIGHT))];
How can I fix this issue?
Thanks in advance.
This happens to you because you load to many things to the memory
As the comment above said, It will be very easy to achieve using UITableView.
Although if you want more control, and you decide using scroll view you have to implement lazy loding. This is being done be allocating and placing the labels when it actually needed to be showen and not during the initialization. You will be able to know that by setting you view controller as the delegate and get the contentOffset from the scrollViewDidScroll: method. Also after recognizing you'll need te remove the subview in order to clear the memory
You can see good example for it here
I feel its because ios is trying to create and keep alot of these views in memory rather then create them dynamically(am I using that word right?) as they scroll on. It would be alot faster to use a UITableView that has a reuse identifier. This will stop iOs from creating a new allocation of memory for each view you make. Create a custom UTTableViewCell, with the labels and buttons you need that is created via a reuse identifier.
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
You should be able to find alot of resource on the web for creating a UITableView with a custom style. If you need a horizontal scrolling UITableView take a look at EasyTableView.
I want to create a small horizontal scrollview with few buttons as shown in image. User can select any one of them and details will be shown accordingly. I am not sure how to code it programmatically. Please help.
Image:- http://i.stack.imgur.com/uDqkn.jpg
ok follow steps to implement the same.
step 1 : take UITableview and apply affin transform for 90 degree.
step 2 : take a button on each cell also apply affinetransform of 90 degree.
step 3 : for each table cell height (now you can say width) will be calculated with the help of stringwidth function of NSString. so please type code in call back method (heightforRowatIndexPath).
step 4 : take layer of tableview and apply round corner property with value 10.0f
step 5 : same you can do for the button their color.
step 6: for outer arrow yo need to implement some UIScrollview module.
here all memory will be managed by tableview for n number of buttons in horizontal scrolling.
Thanks,
Please let me know for any issue
In an ARC view controller ...
#define kHEIGHT 35.0
- (void)createButtonScrollViewWithButtonTitles:(NSArray *)titles {
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0,100.0,320.0,kHEIGHT)];
CGFloat buttonPositionX = 0.0;
for (NSString *title in titles) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:#selector(pressedButton:) forControlEvents:UIControlEventTouchDown];
[button setTitle:title forState:UIControlStateNormal];
button.frame = CGRectMake(buttonPositionX, 0.0, 90.0, kHEIGHT);
buttonPositionX += 90.0;
[scrollView addSubview:button];
}
scrollView.contentSize = CGSizeMake(buttonPositionX, kHEIGHT);
[self.view addSubview:scrollView];
}
After you get this working, you can create a version that takes an array of images. For that, the button type will change to UIButtonTypeCustom. You'll use setImage: rather than setTitle: and you'll have the chance to vary the width by advancing buttonPositionX by the image.size.width, rather than a constant.
Not sure how to interpret the little scroll-arrow-looking things on each side of the image you posted. Another subsequent enhancement would be to overlay each end with a little image view (with userInteractionEnabled = NO) that matches those arrow things.
I want to create a custom calendar application using an array of buttons,so I want to know how to start with this..please help me out.w.r.t this,I want to know if any libraries are present which uses buttons and not a grid layout,because I dont want to use a grid layout
Hello friends,I tried to solve this issue with comments below and wrote this code
for (int columnIndex = 0; columnIndex < 6; columnIndex++)
{
// now loop over the rows
for (int rowIndex = 0; rowIndex < 7; rowIndex++)
{
NSString *buttonTitle = [NSString stringWithFormat:#"%d",columnIndex,rowIndex];
CGRect newFrame = CGRectMake(10 + rowIndex * 40, 60 + columnIndex * 40, 35, 35);
UIButton *newButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
newButton.frame = newFrame;
newButton.backgroundColor = [UIColor grayColor];
[newButton setTitle:buttonTitle forState:UIControlStateNormal];
[newButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
// tag the button, so we know how to handle each one
//newButton.tag = (columnIndex << 8) + rowIndex;
//newButton =[m_buttonArray objectAtIndex:rowIndex];
NSLog(#"%d",[m_buttonArray count]);
[newButton addTarget:self action:#selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:newButton];
}
and when I run the project i see 6*7 grid of buttons..
but I am confused how shall I add these buttons to an array so that I can access w.r.t array,I think it requires a 2D array..so firends please help me out how shall I do this
Thanks&Regards
Ranjit
There's no grid layout in iOS, afaik.
One of your options is to lay out your interface in the interface builder:
Create a new file using UIViewController subclass. Tap the .xib file in the XCode 4.x
Tap the right panel button on the top left, then select "library". Drag a UIButton over to your view and position it. Then you can copy/paste buttons.
I recommend you to find an iOS interface builder tutorial and proceed with that if you want to take this approach.
This is the simplest, yet tedious path. You would be able to visually see how your calendar looks. The downside is that this approach would require you to define 42 buttons and 42 outlets. On the plus side, you would be able to alter your .XIB file
Another way would be to create the interface programmatically an NSMutableArray and add 42 buttons there. You would add each button to your subview using a custom frame for each. This is a very error prone solution, and you will have to manually edit frame offsets/widths if you need to make changes.
I hope this helps!
I have about 50 images of 50 x 50 pixel size each. I want the user to pick one of them. So first I thought about an UITableView, but that's just not the right thing. It wastes a lot of screen space. Rather than putting all images one below the other, it would be better to show a grid of lets say 6 columns and n rows.
I would use an UIScrollView and fill it up with UIView objects which I automatically arrange so that they appear like a grid. Is that the way to go? Or any other suggestions?
I'm doing something very similar in my app- an NxN grid with an image underneath, and another subview on top to draw the "lines", all owned by a UIScrollView. I recommend having a separate view to draw the images, something like:
-(void) drawRect(CGRect rect) {
CGRect smallerRect = CGRectMake(x, y, width, height);
[yourImage drawRect: smallerRect];
// repeat as needed to draw the grid
}
Another poster mentioned that you won't be able to get touch events if your view is owned by a UIScrollView- this is simply not true. I have it working. You might need to set the following though:
[yourScrollView setUserInteractionEnabled: YES]
[yourGridView setUserInteractionEnabled: YES]
The three20 library has a class that does this.
A table view doesn't necessarily imply showing one image per row, as you suggest. Table cells can be customized, and a cell subclass with six 50x50 UIImageViews would be pretty simple. It's maybe less flexible than a scroll view but if six images per row is your goal then a table view is the quickest way to get it.
three20 is horrible,ive used it, i dont recommend it... displaying a grid is easy...
- (void) reloadGridView
{
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(5, 54, scrollViewWidth, scrollViewHeight8)];
scrollView.delegate = self;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.userInteractionEnabled = YES;
scrollView.scrollEnabled = YES;
[self.view addSubview:scrollView];
int x = 10;
int y = 10;
divisor = 1;
for (int i = 0; i < [self.photosArray count]; i++) {
int buttonTag = divisor;
UIImage *thumb = [UIImage imageWithContentsOfFile:[self thumbPathAtIndex:i]];
//********* CREATE A BUTTON HERE **********
//********* use the thumb as its backgroundImage *******
if(divisor%4==0){
y+=70;
x = 10;
}else{
x += 70;
}
divisor++;
}
[scrollView setContentSize:CGSizeMake(scrollViewWidth, ([self.photosArray count]%4 == 0) ? y : y+100)];
}
and if you want 6 images when in landscape - setup a BOOL for isLandscape
if (isLandscape) {
//change the divisor to change # 6 instead of 4
}
if you need a more advanced gridView check out AQGridView (Google it)