How to keep the first cell of a table at the top of its table in scroll view
This is how you create a title view for your UITableView
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger) section {
UIView *sectionHeaderView = [[UIView alloc] initWithFrame:
CGRectMake(0, 0,tableView.frame.size.width, 40.0)];
// Customize it as per your design
return sectionHeaderView;
}
Now return the height
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
//return the desirable height
return 40;
}
Hope this helps you.
source to share
Here is a table view class that you can inherit to provide a header that is attached to the top of the visible area. It has the following key features:
- You have the option to provide a masked image, these are cases where the header has transparency and therefore you need to hide the scrolled table cells.
- You can adjust the height of the visible header area using the view controller.
FixedHeaderTableView.h
/ **
* Table with a fixed header. The header does not scroll off the top of the visible area, and it does not
* scroll down off the top of the header area. The scroll indicator insets are adjusted to go to the top of
* the table, below the header view.
*
* Instructions for use:
*
* 1) Create a table view that inherits from FixedHeaderTableView, and configure it:
* - set the delegate to your view controller
* - this allows you to implement UITableViewDelegate methods, and UIScrollViewDelegate method,
* scrollViewDidScroll:
* 2) Create a separate UIView with the same width as the table view, to be used as the fixed table header.
* 3) Implement scrollViewDidScroll: in your UITableViewDelegate, to simply delegate to your FixedHeaderTableView.
* 4) In viewDidLoad of your view controller, do the following:
* - Set the containerView property to the view controller main view.
* - Create or get a masking view, if the table header is not fully opaque. This prevents the table cells
* from being shown behind the header view, when they are scrolled up.
* - Call setFixedTableHeaderView: visibleHeaderHeight: withMaskingImageView: maskingImageFrame: on your
* FixedHeaderTableView.
* /
@interface FixedHeaderTableView: UITableView {
UIView * _containerView;
UIView * _fixedTableHeaderView;
int _hiddenHeight;
// Used to mask cells behind a transparent header
UIImageView * _maskingImageView;
}
@property (strong, nonatomic) UIView * containerView;
/ **
* To be called from the UITableViewDelegate, to delegate header view positioning and masking.
* /
- (void) scrollViewDidScroll: (UIScrollView *) scrollView;
/ **
* Should be called from viewDidLoad of the view controller.
*
* This sets and configures the fixed table head view. * * @param fixedTableHeaderView UIView that is used as the sticky header * * @param visibleHeaderHeight The bottom portion of the header that will stay visible. This can * be the same height as the header view, or lower. If it is out of * this range, it is clamped to the closest value (0 or the height). * * @param maskingImage This is optional, and it only needed if your header view has * transparent areas. Using a masking image provides much better * performance than adjusting the masks of each cell, in the * scrollViewDidScroll: delegate method. * * @param maskingImageFrame If the masking image is provided, this should be set to position * the background image, so that it is equal to any other image position * used in the background. * / - (void) setFixedTableHeaderView:(UIView *) fixedTableHeaderView visibleHeaderHeight: (int) visibleHeaderHeight withMaskingImage: (UIImage *) maskingImage maskingImageFrame: (CGRect) maskingImageFrame; @end
FixedHeaderTableView.m
#import "FixedHeaderTableView.h"
@interface FixedHeaderTableView ()
@property (assign, nonatomic) int hiddenHeight;
@property (strong, nonatomic) UIView * fixedTableHeaderView;
@property (strong, nonatomic) UIImageView * maskingImageView;
@end
@implementation FixedHeaderTableView
- (void) scrollViewDidScroll: (UIScrollView *) scrollView
{
CGRect tableHeaderRect = _fixedTableHeaderView.frame;
// Prevent table header from being dragging down from the top
tableHeaderRect.origin.y = MIN (0, -scrollView.contentOffset.y);
tableHeaderRect.origin.y + = self.frame.origin.y;
// Prevent table header from scrolling completely off the top
if (scrollView.contentOffset.y> _hiddenHeight) {
tableHeaderRect.origin.y = -_hiddenHeight;
_maskingImageView.hidden = FALSE;
} else {
_maskingImageView.hidden = TRUE;
}
self.fixedTableHeaderView.frame = tableHeaderRect;
}
- (void) setFixedTableHeaderView: (UIView *) fixedTableHeaderView
visibleHeaderHeight: (int) visibleHeaderHeight
withMaskingImage: (UIImage *) maskingImage
maskingImageFrame: (CGRect) maskingImageFrame
{
self.fixedTableHeaderView = fixedTableHeaderView;
// Quietly ensure the value is not out of acceptable range
if (visibleHeaderHeight> _fixedTableHeaderView.frame.size.height) {
visibleHeaderHeight = _fixedTableHeaderView.frame.size.height;
} else if (visibleHeaderHeight <0) {
visibleHeaderHeight = 0;
}
self.hiddenHeight = _fixedTableHeaderView.frame.size.height - visibleHeaderHeight;
// Shift the scrolling insets to span the height of the table rows
self.scrollIndicatorInsets = UIEdgeInsetsMake (_fixedTableHeaderView.frame.size.height, 0, 0, 0);
CGRect tableHeaderFrame = _fixedTableHeaderView.frame;
tableHeaderFrame.origin.x = self.frame.origin.x;
tableHeaderFrame.origin.y = self.frame.origin.y;
_fixedTableHeaderView.frame = tableHeaderFrame;
[self.superview addSubview: _fixedTableHeaderView];
self.tableHeaderView = [[UIView alloc] initWithFrame: CGRectMake (0, 0, self.frame.size.width, _fixedTableHeaderView.frame.size.height)];
// Table header view sits behind the fixed header view
if (maskingImage) {
maskingImageFrame.origin.y + = _hiddenHeight;
UIImageView * maskingImageView = [[UIImageView alloc] initWithFrame: maskingImageFrame];
maskingImageView.image = maskingImage.copy;
[_fixedTableHeaderView addSubview: maskingImageView];
[_fixedTableHeaderView sendSubviewToBack: maskingImageView];
_fixedTableHeaderView.clipsToBounds = TRUE;
self.maskingImageView = maskingImageView;
_maskingImageView.hidden = TRUE;
}
}
@end
source to share