I'm wondering if I could put a page view within a table view cell. Basically I'm trying to get each table view cell to be able to scroll left/right for more content.
Can I do it by putting a page view within a table view cell? Or is there another way to be able to swipe left/right in a table view cell?
It's possible to load another view controller and add its view as a subview of another controller's view.
Although it's not recommended by Apple's guidelines:
Each custom view controller object you create is responsible for
managing all of the views in a single view hierarchy. [...] The
one-to-one correspondence between a view controller and the views in
its view hierarchy is the key design consideration. You should not use
multiple custom view controllers to manage different portions of the
same view hierarchy.
More info on the guidelines click here
A better way to do it is using a UIScrollView and a UIPageControl like this…
cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSArray *photo = [NSArray arrayWithObjects:[UIImage imageNamed:#"image1.png"], [UIImage imageNamed:#"image2.png"], [UIImage imageNamed:#"image3.png"], nil];
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 150)];
self.scrollView.backgroundColor = [UIColor clearColor];
self.scrollView.indicatorStyle = UIScrollViewIndicatorStyleBlack; //Scroll bar style
self.scrollView.showsHorizontalScrollIndicator = NO;
[self.scrollView setDelegate:self];
//Show horizontal scroll bar
self.scrollView.showsVerticalScrollIndicator = YES; //Close vertical scroll bar
self.scrollView.bounces = YES; //Cancel rebound effect
self.scrollView.pagingEnabled = YES; //Flat screen
self.scrollView.contentSize = CGSizeMake(640, 30);
NSLog(#"LOG");
self.pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 155, 320, 40)];
self.pageControl.numberOfPages = photo.count;
self.pageControl.currentPage = 0;
self.pageControl.backgroundColor = [UIColor redColor];
[self.pageControl setTintColor:[UIColor whiteColor]];
[cell.contentView addSubview:self.pageControl];
for(int i = 0; i < photo.count; i++)
{
CGRect frame;
frame.origin.x = (self.scrollView.frame.size.width *i) + 10;
frame.origin.y = 0;
frame.size = CGSizeMake(self.scrollView.frame.size.width - 20, self.scrollView.frame.size.height);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
[imageView setImage:[photo objectAtIndex:i]];
[self.scrollView addSubview:imageView];
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width*photo.count, self.scrollView.frame.size.height);
}
[cell.contentView addSubview:self.scrollView];
return cell;
}
update PageControl
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGFloat pageWidth = scrollView.frame.size.width;
//int page = floor((scrollView.contentOffset.x - pageWidth*0.3) / pageWidth) + 1);
self.pageControl.currentPage = (int)scrollView.contentOffset.x / (int)pageWidth;
NSLog(#"CURRENT PAGE %d", self.pageControl.currentPage);
}
Yes, you can.
However, be aware that you can't get rid of the black background to the page control in it if you choose to go that route. I did this a couple days ago but ended up getting rid of the page view controller in favor of using a UIScrollView that has paging enabled and a UIPageControl. I use the -scrollViewWillEndDragging:withVelocity:targetContentOffset: scroll view delegate method to determine when to determine the currentPage in the page control.
If you're going to have quite a few views in the scroll view, it would be more memory efficient to use a collection view instead of a normal scroll view.
Instead of using a UIPageview, try to put another UITableview (rotated by 90 degrees in anticlockwise direction)inside a cell. This will give you more control over touch events and more customization too.
1) Have a class for UITableViewCell and an xib file too, say PageViewTableCell
2) Xib file should have a UITableView inside the cell
3) Rotate the table when awakeFromNib is called
- (void)awakeFromNib
{
horizontalTable.transform = CGAffineTransformMakeRotation(-M_PI_2);
horizontalTable.frame = CGRectMake(0,0,horizontalTable.frame.size.width,horizontalTable.frame.size.height);
}
4) Have the delegate and datasource for horizontalTable according to your design.
5) Load the main table which has the above customized cell
- (void)viewDidLoad
{
[self.mainTable registerNib:[UINib nibWithNibName:#"PageViewTableCell"
bundle:[NSBundle mainBundle]]
forCellReuseIdentifier:#"samplecell"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
PageViewTableCell* cell = [tableView dequeueReusableCellWithIdentifier:#"samplecell"];
return cell;
}
Related
I have a static cell that stores an information form which user can input fields. One of the static cell is for attachments. I would like to append some UIView into this cell when the user chose an image from the UIImagePickerController. I have already handled the UIImagePickerController part. And I have find the cell by reuseIdentifier:
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"AttachmentCell"];
And I tried to append views in my cell:
CGRect attachmentFrame = CGRectMake(0, 0, 50, 50);
UIView * attachmentRow = [[UIView alloc]initWithFrame: attachmentFrame];
CGFloat ratio = 50 / image.size.width;
CGRect imageFrame = CGRectMake(10, 0, image.size.width * ratio, 50);
CGRect imageNameLabelFrame = CGRectMake(10 + imageFrame.size.width + 10, 22, 300, 6);
UIImageView *imageView = [[UIImageView alloc]initWithFrame: imageFrame];
imageView.image = image;
UILabel *imageNameLabel = [[UILabel alloc]initWithFrame:imageNameLabelFrame];
imageNameLabel.text = [NSString stringWithFormat:#"Attachment %d", attachmentCounter++];
[attachmentRow addSubview: imageView];
[attachmentRow addSubview: imageNameLabel];
attachmentRow.backgroundColor = [UIColor lightGrayColor];
[cell.contentView addSubview: attachmentRow];
NSLog(#"Row appended");
Notice that the above code is just to try adding one single view in the static cell but it seems failed. Nothing shows in my static cell after I add the view. I have logged that my attachment data can successfully brings to this page.
Maybe this is just the wording in the question, but it seems that what you do after the user has selected the image, is that you create a new cell.
This line :
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"AttachmentCell"];
Creates a brand new cell, and your table view has no way to know about it.
What you should rather do is to reload your table view after the user has selected the image and setup it in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
In order to reload the data you can use either reloadData method of UITableView which will reload all data or - (void)reloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *) withRowAnimation:(UITableViewRowAnimation)animation which will reload only cells at specifed indexes.
firstly add this line
[cell.contentView addSubview: attachmentRow];
then
[attachmentRow addSubview: imageView];
[attachmentRow addSubview: imageNameLabel];
may be it will help
You will have to use custom cell instead of using default tableview cell.
For that first you need to create one with identifier.
I have 6 images in my database.
I have created UIScrollView *scroll;, after that, I had created UICollectionView and added UICollectionView to UIScrollView
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(screenWidth*i,5,screenWidth ,self.scroll.frame.size.height-5) collectionViewLayout:layout];
[collectionView setDataSource:self];
[collectionView setDelegate:self];
[collectionView setPagingEnabled:YES];
collectionView.showsHorizontalScrollIndicator = NO;
collectionView.showsVerticalScrollIndicator = NO;
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[collectionView setBackgroundColor:[UIColor purpleColor]];
[self.scroll addSubview:collectionView];
And now, when scroll I want reload data of UICollectionView on below this code:
- (void)scrollViewDidScroll:(UIScrollView *)sender {
if (!pageControlBeingUsed) {
[getAllEmoji removeAllObjects];
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.scroll.frame.size.width;
int page = floor((self.scroll.contentOffset.x - pageWidth / 3) / pageWidth) + 1;
self.pageControl.currentPage = page;
//Change Emoji when scroll
NSString *str = [getAllCategory objectAtIndex:page];
NSArray *arr = [Emoji MR_findByAttribute:#"category" withValue:str];
if (arr.count > 0) {
for (int i = 0; i < arr.count; i++) {
Emoji *emoji = [arr objectAtIndex:i];
[getAllEmoji addObject:emoji.name_emoji];
}
[collectionView reloadData];
}
}
}
first pageControl is 2 images.
When I scroll to second pageControl is 2 images(But, it's don't load new image).
When I scroll to third pageControl is 2 images(it's load new image).
You can see some images in my project on below link:
http://imgur.com/a/nIMic
And my project demo.
https://github.com/VMTrinh/Sticker
Please help me!
I guess your problem is that you don't need to embed collection view in a scroll view.
The scroll mechanism is managed by the collection view.
You can scroll your collection with the scrollToItemAtIndexPath: method.
I have two tableviews in one view controller.
One is there in the interface builder and the other i have created dynamically using the below code in the viewDidLoad() method.
// Creating the view for placing the dynamic tableview
-(UIView *) createAndAddMenuView :(float) viewHeight
{
UIView *myView = [[UIView alloc] init];
myView.backgroundColor = [UIColor blueColor];
CGRect coord = myView.frame;
coord.origin.x = -255;
coord.origin.y = 0;
coord.size.width = 255;
coord.size.height = viewHeight;
[myView setFrame:coord];
return myView;
}
-(void) addMenuItemsTable{
UITableView *dynamicTable=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, 255, self.navigationController.view.frame.size.height) style:UITableViewStylePlain];
dynamicTable.delegate=self;
dynamicTable.dataSource=self;
dynamicTable.tag = 20;
//[dynamicTable reloadData];
[menuView addSubview:dynamicTable];
}
Both these two tableviews have delegate and datasource set to self. The second dynamic tableview is added to a view and placed on the left hidden side with x = -255.
When I click on the button in the navigation bar i am moving "menuView" view to the screen and the other static tableview out of the screen just like the Facebook app.
I am using this code for moving the menuView back and forth.
-(void) toggleMainView :(UITableView *) mytableView withMenuView : (UIView * )menuView{
NSLog(#"TAG %d",mytableView.tag);
CGRect destination = mytableView.frame;
NSLog(#"XX %f",destination.origin.x);
if (destination.origin.x > 0) {
destination.origin.x = 0;
} else {
destination.origin.x += 255;
}
NSLog(#"ORG X = %f", destination.origin.x );
[UIView animateWithDuration:0.25 animations:^{
[self showMenu:menuView];
mytableView.frame = destination;
} completion:^(BOOL finished) {
mytableView.userInteractionEnabled = !(destination.origin.x > 0);
}];
}
-(void)showMenu :(UIView *)menuView{
CGRect coord = menuView.frame;
NSLog(#"Width = %f, x = %f",coord.size.width, coord.origin.x);
if(coord.origin.x < 0){
coord.origin.x = 0;
}else{
coord.origin.x = -255;
}
[menuView setFrame:coord];
}
But when I am NOT setting the second tableview Datasource then only this code is working.
I have no idea why this is happening.
ie. When I comment out this line
dynamicTable.dataSource=self;
Then only when I click the button the first tableview is moving out of the screen.
All these times the dynamic one will move back and forth in the screen.
When the DS is not commented the first (static tableview) will not move and Second (dynamic one) will move.
This is my first iPhone application.
if you are using 2 tableview or 1 tableview try to set tag values for it with two different values suppose for table1 tag is 50 and for table2 tag is 60 then the code in tableview delegates and datasource should be like below.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(tableView.tag==50) // if you have 2 different objects for tableviews then you can also use like this if(tableView == tableviewObjc1)
{
// tableview1 info
}
else
{
// tableview2 info
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
}
for (UIView *view in cell.contentView.subviews) {
[view removeFromSuperview];
}
if(tableView.tag==50)
{
// tableview1 info
}
else
{
// tableview2 info
}
return cell;
}
You can use any custom control that suits your requirement
from cocoacontrols one of them is
MVYSideMenu
You don't require to add two tableview in one ViewController
You should try below approach:
STEPS:
Add two Prototype cells to storybaord
Make two custom cell class subclassing UITableViewCell and design your cell storyboard or via code
cellForRowAtIndexPath: initialize cell according to requirement and set it datasource and delegate methods accordingly
I want to make a Table View Controller that hold a table view and an image view in table view header view. When I scroll down the table view I want to zoom in the image (like in CNN app for iOS). I tried a lot of things but none of them to this as I want. Maybe someone can help me. Thanks!
All screen will look like this image like in this image:
(source: mzstatic.com)
I tried to do this by making the image at the top the header view of the table, but couldn't get that to work.
The way that did work, was to add a scroll view to the top of a UIViewController's view with a image view inside it. I then added a table view, and made it the same size as the controller's view so that it is over top the small scroll view that holds the image (this was done in a storyboard with auto layout turned off). In code, I add a table header view that's transparent and has a label that acts as the caption for the picture. It has the same height as the small scroll view. When you scroll the content of the table view up, I also scroll the small scroll view but at half the rate. If you pull the content down, I change the frame of the small scroll view so that it expands and stays centered. Here's the code:
#interface ViewController ()
#property (strong,nonatomic) NSArray *theData;
#property (weak,nonatomic) IBOutlet UITableView *tableView;
#property (weak,nonatomic) IBOutlet UIScrollView *imageScrollView;
#property (nonatomic) CGRect svFrame;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.imageScrollView.delegate = self;
self.imageScrollView.contentSize = CGSizeMake(500, 500);
self.svFrame = self.imageScrollView.frame;
self.theData = #[#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight",#"Nine"];
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 135)];
headerView.backgroundColor = [UIColor clearColor];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, headerView.frame.size.width, 24)];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor whiteColor];
label.text = #"This is a Picture Caption";
[headerView addSubview:label];
self.tableView.tableHeaderView = headerView;
[self.tableView reloadData];
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
UIView *bgView = [[UIView alloc] init];
bgView.backgroundColor = [UIColor whiteColor];
cell.backgroundView = bgView;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.theData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = self.theData[indexPath.row];
return cell;
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (! [scrollView isEqual:self.imageScrollView]) {
if (scrollView.contentOffset.y > 0) {
self.imageScrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y/2);
}else{
self.imageScrollView.frame = CGRectMake(scrollView.contentOffset.y, scrollView.contentOffset.y, self.svFrame.size.width - (scrollView.contentOffset.y * 2), self.svFrame.size.height - (scrollView.contentOffset.y * 2));
}
}
}
I have a scrollview inside each cell in my tableview, although the pictures embed in my scrollview don't show up until i scroll the tableview up and down...
I have a custom class with a #property for the scrollview and the cell. I have my code for setting the scrollview in the cellForRowAtIndexPath: method. This should be called upon initial creation of the cells as well? Im confused.
How can I get rid of the problem and make the images appear at first when I start the app?
Related code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"CustomID";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
for (int i = 0; i < [imageArray count]; i++) {
CGRect frame;
frame.origin.x = cell.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = cell.scrollView.frame.size;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
imageView.image = [UIImage imageNamed:[imageArray objectAtIndex:i]];
[cell.scrollView addSubview:imageView];
}
cell.scrollView.contentSize = CGSizeMake(cell.scrollView.frame.size.width * [imageArray count], cell.scrollView.frame.size.height);
return cell;
}
This is not exactly related to your question but you will run into this issue too:
Don't forget that your cells will be reused. Upon reusage (lets say the user scrolls down, a cell is moved upwards off the screen and the next that appears on the bottom will be physically the instance of CustomCell that just disappeard and was reused.)
Therefore add:
for (UIView *aView in [NSArray arrayWithArray:cell.subviews]) {
[aView removeFromSuperview];
// if you don't arc then release them and take care of their subviews - if any.
}
before adding any new UIImageView.
(I thought there was a method for removing all subviews in one go but did not find it)