I'm working with a UITableView.
The table view has a HeaderView with a UIImageView that changes its height when the user scroll the table view.
In addition to this I also have a custom uiview for the section of the tableview .. My problem is that after setting the content Inset for the tableview, the section does not follow the scrolling of the table ..
Before Scroll
After Scroll
Surely it is a problem of content Inset, I did various tests but I could not find a solution ...
I would like the section of the tableView to follow the scroll and stop when it gets under the status bar (about 25 points of self.view.frame.origin.y)
Which path should I follow to solve my problem?
This is the code I am using
Register Xib for section header
- (void)viewDidLoad {
[super viewDidLoad];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellID];
[_tableView registerNib:[UINib nibWithNibName:#"DashboardTopHeader" bundle:nil] forHeaderFooterViewReuseIdentifier:dashboardTopHeader];
[self setupHeaderView];
}
Generate Section Header
#pragma mark - Dashboard Top Header
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
DashboardTopHeader *header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:dashboardTopHeader];
return header;
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 100;
}
Setup the Header View of TableView With Photo
-(void)setupHeaderView {
_headerView = [[UIView alloc] init];
_headerView = self.tableView.tableHeaderView;
_tableView.tableHeaderView = nil;
[_tableView addSubview:_headerView];
// 130 is Height of headerView
CGFloat newHeight = 130 - 50 /2;
_tableView.contentOffset = CGPointMake(0, -newHeight);
_tableView.contentInset = UIEdgeInsetsMake(newHeight, 0, 0, 0 );
[self updateHeaderView];
}
-(void)updateHeaderView {
CGFloat newHeight = 130 - 50 /2;
CGRect headerFrame = CGRectMake(0, -newHeight, self.tableView.frame.size.width, 130);
if (self.tableView.contentOffset.y < newHeight) {
headerFrame.origin.y = self.tableView.contentOffset.y;
headerFrame.size.height = - self.tableView.contentOffset.y + 50/2;
}
_headerView.frame = headerFrame;
}
Use TableView Delegate for scroll Content
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self updateHeaderView];
}
Related
I have a tableview with a header view on it and paging enabled:
[super viewDidLoad];
CGRect headerFrame = [UIScreen mainScreen].bounds;
UIView *header = [[UIView alloc] initWithFrame:headerFrame];
header.backgroundColor = [UIColor flatWhiteColor];
self.tableView.tableHeaderView = header;
self.tableView.pagingEnabled = YES;
The Cells are the height of the screen:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [UIScreen mainScreen].bounds.size.height;
}
however, when I run it on my iPhone 6, the first table cell is never highlighted properly:
when its not highlighted
when I select the cell
help anyone?
The problem is because the height of headerView it's not actually equal with the size of the tableView and on the next page(the first table cell) you are seeing a part from the headerView.
Try this code:
CGRect headerFrame = CGRectMake(0, 0, self.tableView.frame.size.width, self.tableView.frame.size.height);
and
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return self.tableView.frame.size.height;
}
I found out the answer. It turns out a UIView inside my header was a bit too long and overlapped into my table cell. Thanks for your answers!
The code in questions is below:
-(void)addSpeedTable {
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"newCell"];
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
self.tableView.rowHeight = 45;
self.tableView.sectionFooterHeight = 22;
self.tableView.sectionHeaderHeight = 22;
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView = _tableView;
NSLog(#"TableView Frame %#", NSStringFromCGRect(self.tableView.frame));
[self.view addSubview:self.tableView];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)theTableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"newCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"newCell"];
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.textLabel.text = #"Test";
return cell;
}
As you can see if I have a section set to 1 and row set to 1, yet when the view is added the table takes up the entire screen, which I assume is because I initiate with a frame of the view bounds.
Is there any way to force the table to only be the size of the rows required?
My plan is to add more than one table to this single view and I want them appearing one after the other along with title labels and a scrollview. I want the height to be decided by the number of rows.
Thanks
UPDATED CODE THANKS TO THE CORRECT ANSWER:
-(void)addSpeedTable {
CGRect frame = self.tableView.frame;
frame.size.height = (40 * resultHeadings.count)+35;
frame.size.width = self.view.frame.size.width;
//If more than one table has been shown increase Y axis height for view
if(tablesDisplayed > 0) {
NSLog(#"Tables displayed greater than zero");
viewHeight = viewHeight + frame.size.height;
}
frame.origin.y = viewHeight;
frame.origin.x = 0;
self.tableView = [[UITableView alloc] initWithFrame:frame];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"newCell"];
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
self.tableView.rowHeight = 40;
self.tableView.sectionFooterHeight = 0;
self.tableView.sectionHeaderHeight = 22;
self.tableView.scrollEnabled = NO; // Disable ScrollView
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView = _tableView;
NSLog(#"TableView Frame %#", NSStringFromCGRect(frame));
[self.view addSubview:self.tableView];
tablesDisplayed++;
}
As I'm adding more than one table in the long run I calculate the height based on a calculation. This works great.
Here are two things you could try. Without knowing where addSpeedTable is called from, I'd err on putting this in your cellForRowAtIndexPath method.
Set the height to the self.tableView.contentHeight
CGRect frame = self.tableView.frame;
frame.size.height = self.tableView.contentSize.height;
self.tableView.frame = frame;
Call [self.tableView sizeToFit]
Hi friends is it possible to add a cover flow effect in uicollection view in horizontal layout.if possible means kindly tell me how to implement the effect.
Yes it is possible, You need to Implement your custom UICollectionViewFlowLayout.
Make a custom class which inherits UICollectionViewFlowLayout
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
return YES; }
- (UICollectionViewScrollDirection)scrollDirection {
return UICollectionViewScrollDirectionVertical; }
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
UICollectionView *collectionView = [self collectionView];
UIEdgeInsets insets = [collectionView contentInset];
CGPoint offset = [collectionView contentOffset];
CGFloat minY = -insets.top;
NSArray *attributes = [super layoutAttributesForElementsInRect:rect];
// minY is Point where we implement this cover flow.
if (offset.y < minY) {
// Figure out how much we've pulled down
CGFloat deltaY = fabsf(offset.y - minY);
for (UICollectionViewLayoutAttributes *attrs in attributes) {
// Locate the header attributes
NSString *kind = [attrs representedElementKind];
if (kind == UICollectionElementKindSectionHeader) {
// This is header's height and y based on how much the user has scrolled down.
CGSize headerSize = [self headerReferenceSize];
CGRect headerRect = [attrs frame];
headerRect.size.height = MAX(minY, headerSize.height + deltaY);
headerRect.origin.y = headerRect.origin.y - deltaY;
[attrs setFrame:headerRect];
break;
}
}
}
return attributes; }
Now in your class where you allocate UICollectionView
CustomCoverFlowHeaderCollectionViewLayout *flow; flow = [[CustomCoverFlowHeaderCollectionViewLayout alloc] init]; [stretchyLayout setHeaderReferenceSize:CGSizeMake(320.0, 160.0)]; // Set our custom layout [collectionView setCollectionViewLayout: flow]; [collectionView setAlwaysBounceVertical:YES]; [collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader
withReuseIdentifier:#"myCoverCollectionView"];
You are almost done
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
viewForSupplementaryElementOfKind:(NSString *)kind
atIndexPath:(NSIndexPath *)indexPath {
if (!header) {
header = [collectionView dequeueReusableSupplementaryViewOfKind:kind
withReuseIdentifier:#"myCoverCollectionView" forIndexPath:indexPath];
CGRect bounds;
bounds = [header bounds];
UIImageView *imageView;
imageView = [[UIImageView alloc] initWithFrame:bounds];
[imageView setImage:[UIImage imageNamed:#"background"]];
[imageView setContentMode:UIViewContentModeScaleAspectFill];
[imageView setClipsToBounds:YES];
[imageView setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
[header addSubview:imageView];
}
return header; }
Here is a good project based on UICollectionView for you.
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;
}
I have one class ViewController that I to create TableView in it with code not nib file and I want custom cell with UITableViewCell that has nib file.
I create TableView with code that has 320px width and I want create custom cell with UITableViewCell that my cells had 300px width and put in my TableView.
notice: I want these cells put center my table and these cells have 10px distance from two side!!!
this is my code:
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
table = [self makeTableView];
[self.view addSubview:table];
[self.view setBackgroundColor: RGB(193,60,46)]; //will give a UIColor objct
name = [[NSArray alloc]initWithObjects:#"1",#"2",#"3",#"4",#"5", nil];
// Do any additional setup after loading the view from its nib.
}
- (BOOL)prefersStatusBarHidden
{
return YES;
}
-(UITableView *)makeTableView
{
CGFloat x = 0;
CGFloat y = 0;
CGFloat width = self.view.frame.size.width;
CGFloat height = self.view.frame.size.height;
CGRect tableFrame = CGRectMake(x, y, width, height);
UITableView *tableView = [[UITableView alloc]initWithFrame:tableFrame style:UITableViewStyleGrouped];
tableView.rowHeight = 60;
tableView.sectionFooterHeight = 22;
tableView.sectionHeaderHeight = 22;
tableView.scrollEnabled = YES;
tableView.showsVerticalScrollIndicator = YES;
tableView.userInteractionEnabled = YES;
tableView.bounces = YES;
tableView.backgroundColor = [UIColor clearColor];
tableView.delegate = self;
tableView.dataSource = self;
return tableView;
}
#pragma mark Table View Data Source Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CustomCell *cell = (CustomCell *)[self.table dequeueReusableCellWithIdentifier:#"myCell"];
if (cell == nil)
{
NSArray *topLevelObject = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:nil options:nil];
for (id currentObject in topLevelObject) {
if ([currentObject isKindOfClass:[CustomCell class]]) {
cell = (CustomCell *)currentObject;
break;
}
}
}
// Configure the cell...
cell.titleLable.text = [name objectAtIndex:indexPath.row];
return cell;
}
this is my code : TableCode
I have a UITableView with a width of 685.
I created Custom UITableViewCell with a width of 685 also.
I have added two labels.
I aligned a label in such a way, the spacing for left and right are the same.
afaik, cells are always the width of the table and you cant change that, you can fake it by making the content view of the cell transparent, then place another view with all your content in it that is a smaller width than the table