Due to some purposes(like pull to refresh), I need a UICollectionView can bounce or scroll when there is no cells -- means numberOfItemsInSection: return 0
I have my code like this:
...
UICollectionViewFlowLayout *flowLayout =[[UICollectionViewFlowLayout alloc] init];
flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
flowLayout.minimumInteritemSpacing = SPLIT_SPACE;
flowLayout.minimumLineSpacing = SPLIT_SPACE;
targetCollection = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - TABBAR_HEIGHT)
collectionViewLayout:flowLayout];
[targetCollection registerNib:[UINib nibWithNibName:#"DashboardCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:#"DashboardCell"];
targetCollection.autoresizingMask = UIViewAutoresizingFlexibleHeight;
targetCollection.backgroundColor = [UIColor colorWithHex:#"#EAEAEA"];
targetCollection.contentInset = UIEdgeInsetsMake(0, 0, 20, 0);
targetCollection.alwaysBounceVertical = YES;
...
#pragma mark - UICollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;
{
return 0;
}
However, when testing, this empty UICollectionView cannot bounce nor scroll. I suspect it is related to empty cell, but I do need to enable the bounce or scroll when no cell.
This is similar to another of my problem:SVPullToRefresh cannot pull on an empty UICollectionView
Do it like this:
self.collectionView.alwaysBounceVertical = YES;
answer by #VNJ at here
Change this setting in your storyboard:
Swift Solution
collectionView.alwaysBounceVertical = true
You can try this:
collectionView.isScrollEnabled = false
- (void)_edgeInsetsToFit {
UIEdgeInsets edgeInsets = self.collectionView.contentInset;
CGSize contentSize = self.collectionView.contentSize;
CGSize size = self.collectionView.bounds.size;
CGFloat heightOffset = (contentSize.height + edgeInsets.top) - size.height;
if (heightOffset < 0) {
edgeInsets.bottom = size.height - (contentSize.height + edgeInsets.top) + 1;
self.collectionView.contentInset = edgeInsets;
} else {
edgeInsets.bottom = 0;
self.collectionView.contentInset = edgeInsets;
}
}
I called that method after layoutSubviews
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
_STAssetViewController *weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[weakSelf _edgeInsetsToFit];
});
}
You can try that way
Related
I am currently working on making a layout like a calendar. The basic idea is to add an UILabel and UICollectionView inside an UIScrollView, I am using just an UIViewController for layout(but with UICollectionViewDataSource and UICollectionViewFlowLayout delegate).
The scenario is: everytime a user searches data for a particular month(by clicking a button), the corresponding data would be given from the server and the UICollectionView frame would be set.
However, after I tried to update the frame of my UICollectionView, it happens that the collectionview will shift down in the UIScrollView, and I have no idea why this is happening. Have tried to set automaticallyAdjustsScrollViewInsets to 0 and used the [collectionView setContentInset] method, but it seems like not working out. Couldn't be more appreciate if anyone can give me some hint about this problem !
Below is some part of my code.
// viewDidLoad
self.weekLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.view.frame.origin.x, self.scrollView.frame.origin.y, self.calendarWidth, 20)];
self.calendarWidth = self.view.frame.size.width * 7 / 4;
self.flowLayout = [[UICollectionViewFlowLayout alloc] init];
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(self.view.frame.origin.x, self.scrollView.frame.origin.y + 20, self.calendarWidth, self.scrollView.frame.size.height - self.weekLabel.frame.size.height * 7) collectionViewLayout:self.flowLayout];
[self.collectionView setDataSource:self];
[self.collectionView setDelegate:self];
[self.collectionView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"collectionCell"];
[self.collectionView setBackgroundColor:[UIColor colorWithRed:241/255.0f green:239/255.0f blue:228/255.0f alpha:1.0f]];
// setup scrollView
[self.scrollView setContentSize:self.collectionView.bounds.size];
[self.scrollView addSubview:self.collectionView];
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(self.calendarWidth/7, (self.scrollView.frame.size.height - 40)/5);
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
if (self.currentMonthRange == 28 && self.selectedMonth == 2) {
return 28;
} else if ((self.currentMonthRange + self.currentWeekDay) > 35) {
return 42;
} else {
return 35;
}
}
// method that is called after getting data from server, update the frame
-(void) checkSpecialDay {
if (self.currentMonthRange == 28 && self.selectedMonth == 2) {
[self.collectionView setFrame:CGRectMake(self.view.frame.origin.x, self.scrollView.frame.origin.y + 20, self.calendarWidth, self.scrollView.frame.size.height - self.weekLabel.frame.size.height * 3)];
} else if ((self.currentMonthRange + self.currentWeekDay) > 35) {
[self.collectionView setFrame:CGRectMake(self.view.frame.origin.x, self.scrollView.frame.origin.y + 20, self.calendarWidth, self.scrollView.frame.size.height - self.weekLabel.frame.size.height * 3)];
} else {
[self.collectionView setFrame:CGRectMake(self.view.frame.origin.x, self.scrollView.frame.origin.y + 20, self.calendarWidth, self.scrollView.frame.size.height - self.weekLabel.frame.size.height * 7)];
}
[self.collectionView.collectionViewLayout invalidateLayout];
}
[Update] - Solved.
Thanks to #Adeel that the real problem is assigning the frame of my collectionview to the "frame" of the uiscrollview, instead the bug is solved after I set it to the "bounds" of the uiscrollview. But WHY is the UIScrollView's frame changed after getting any data ?
I'm trying to implements this library without using storyBoard (first step for implementing this library) , because I'm creating my UIcollectionView programmatically.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
//self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.collectionView];
[_collectionView registerNib:[UINib nibWithNibName:#"myCell" bundle:nil] forCellWithReuseIdentifier:#"cell3"];
[_collectionView setBackgroundColor:[UIColor colorWithRed:0.945 green:0.945 blue:0.945 alpha:1] ];
[_collectionView setTransform:CGAffineTransformMakeScale(-1, 1)];
RFQuiltLayout* layout = (id)[_collectionView collectionViewLayout];
layout.direction = UICollectionViewScrollDirectionVertical;
layout.blockPixels = CGSizeMake(100, 100);
}
- (UICollectionView *)collectionView {
if (!_collectionView) {
CGRect collectionViewFrame = self.view.bounds;
collectionViewFrame.size.height -= (self.navigationController.viewControllers.count > 1 ? 0 : (CGRectGetHeight(self.tabBarController.tabBar.bounds))) + 0;
// FMMosaicLayout *mosaicLayout = [[FMMosaicLayout alloc] init];
//// _collectionView = [[UICollectionView alloc] initWithFrame:collectionViewFrame collectionViewLayout:mosaicLayout];
// RFQuiltLayout* layout = (id)[_collectionView collectionViewLayout];
// layout.direction = UICollectionViewScrollDirectionVertical;
// layout.blockPixels = CGSizeMake(100, 100);
_collectionView = [[UICollectionView alloc] initWithFrame:collectionViewFrame collectionViewLayout:[[RFQuiltLayout alloc] init]];
_collectionView.delegate = self;
_collectionView.dataSource = self;
}
return _collectionView;
}
But this didn't worked and nothing is shown in my view (no error and empty view that's all) Also using debugger I've notified that the UICollectionView Method are never called
First of all, your collectionView method is not called because you are using _collectionView instead self.collectionView in your viewDidLoad method. You need to write self for every property to call their setter and getter methods.
Second, if you want to add custom layout without Storyboard of XIB, then you need to set it programmatically:
RFQuiltLayout* layout = [[RFQuiltLayout alloc] init];
layout.direction = UICollectionViewScrollDirectionVertical;
layout.blockPixels = CGSizeMake(100, 100);
self.collectionView.collectionViewLayout = layout;
This question already has answers here:
UIScrollView not scrolling
(27 answers)
Closed 7 years ago.
I'm adding subViews to a programmatically added UIScrollView, yet when the subViews go off the screen the scrollview isn't scrolling. Any Ideas?
I need to update the content size of the scrollview more than once.
First I add the scrollView itself as subView of the view, like so:
[super viewDidLoad];
[self addScrollView];
[self APISimpleDemo];
}
#pragma mark Add Scroll View
-(void)addScrollView {
//Add Scroll View
CGFloat navHeight = self.navigationController.navigationBar.frame.size.height; //get height of nav bar
CGRect scrollFrame;
scrollFrame.size.height = self.view.frame.size.height - (navHeight - 150); //set height minus nav bar and top section
scrollFrame.size.width = self.view.frame.size.width;
scrollFrame.origin.y = 180;
scrollFrame.origin.x = 0;
self.scrollView = [[UIScrollView alloc] initWithFrame:scrollFrame];
NSLog(#"TableView Frame %#", NSStringFromCGRect(scrollFrame));
self.scrollView.delegate = self;
[self.view addSubview:self.scrollView];
}
The NSLog output is: {{0, 180}, {375, 773}}
Next the code runs through and the end of each test (in this example 2) a tableView is added to the newly added scrollView. Like so...
-(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.scrollView addSubview:self.tableView];
tablesDisplayed++;
}
As I needed the content size of the scrollView to increase as TableViews were added to the ScrollView I created a method that updates the scrollView content size every time a table is added:
The code now looks like:
-(void)addScrollView {
//Add Scroll View
CGFloat navHeight = self.navigationController.navigationBar.frame.size.height; //get height of nav bar
CGRect scrollFrame;
scrollFrame.size.height = self.view.frame.size.height - navHeight - 150; //set height minus nav bar and top section
scrollFrame.size.width = self.view.frame.size.width;
scrollFrame.origin.y = 180;
scrollFrame.origin.x = 0;
self.scrollView = [[UIScrollView alloc] initWithFrame:scrollFrame];
self.scrollView.delegate = self;
[self.view addSubview:self.scrollView];
}
#pragma mark Update Scroll View Content Size
-(void)updateScrollSize {
//View height is set in the add table method depending on the size of the table
CGFloat scrollHeight = 400 + viewHeight;
self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width, scrollHeight);
}
-(void)addSpeedTable {
CGRect frame = self.tableView.frame;
frame.size.height = (40 * resultHeadings.count)+50;
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 updateScrollSize]; //Update scrollView contentSize when adding new table to view
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.scrollView addSubview:self.tableView];
tablesDisplayed++;
}
You are not setting scrollView.contentSize.
I am having some strange uitableview behavior- my customs cells have a little extra space around them that I cannot fix. I can also move the cells in that space. I have attached a couple of pictures as my English is not letting me to explain better. Any ideas on what might the issue be? I can post my code for my custom cell but it even happens with admob add cell, so I am not sure it is related to the custom cell.
EDIT: Added code for heights
EDIT2: I changed the scroll view alloc to
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width,self.bounds.size.height)];
And it fixed the moving of the cell. But that white line is still there.
Table View
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// return (self.tableViewHome.bounds.size.height-49-6-self.tableViewHome.tableHeaderView.bounds.size.height-self.tableViewHome.tableFooterView.bounds.size.height-GAD_SIZE_320x50.height)/3;
float height = self.tableViewHome.frame.size.height-self.tableViewHome.tableHeaderView.bounds.size.height-30.0;
if (indexPath.item==5)
{
height=kGADAdSizeBanner.size.height;
}
else
{
if (indexPath.item==1 || indexPath.item==3)
{
height=15.0;
}
else
{
if (indexPath.item==0 || indexPath.item==2 || indexPath.item==4)
{
height=(height-kGADAdSizeBanner.size.height)/3;
}
}
}
NSLog(#"Height:%f",height);
return height;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 0.1;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 0.1;
}
Custom Cell
-(id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[scrollView setShowsHorizontalScrollIndicator:NO];
[scrollView setShowsVerticalScrollIndicator:NO];
// NSInteger viewcount= 3;
// for(int i = 0; i< viewcount; i++) {
// CGFloat x = 2 * self.bounds.size.width;
todayView = [HomeTodayView homeTodayView];
todayView.frame = CGRectMake(0, 0,self.bounds.size.width, self.bounds.size.height);
todayView.backgroundColor = [UIColor redColor];
avgView = [HomeAvgView homeAvgView];
avgView.frame = CGRectMake(self.bounds.size.width, 0, self.bounds.size.width, self.bounds.size.height);
// [[HomeTodayView alloc] initWithFrame:
todayView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
avgView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[scrollView addSubview:todayView];
[scrollView addSubview:avgView];
scrollView.contentSize = CGSizeMake(self.bounds.size.width *2, self.bounds.size.height+100);
scrollView.pagingEnabled = YES;
scrollView.bounces = NO;
[self addSubview:scrollView];
}
return self;
}
Try This:
[table setSeparatorStyle:UITableViewCellSeparatorStyleNone];
NOTE:- table = your tableview name.
If this does not work then please check that your custom cell height and the row height of tableView are same?
I have a UIScrollView that loads three different pages.When i zoom in on a page, and zoom back out to the original size, the application stops letting me scroll between the pages, as if paging is disabled. What can i do to re-enable paging when zoomed out to the original size (Scale == 1)?
This is my code
- (void)viewDidLoad
{
[ScView setMaximumZoomScale : 2.0f];
[ScView setMinimumZoomScale : 1.0f];
ScView.contentSize = CGSizeMake(1024*3, 1.0);
ScView.pagingEnabled = YES;
ScView.clipsToBounds = YES;
ScView.delegate = self;
ScView.showsHorizontalScrollIndicator = NO;
ScView.showsVerticalScrollIndicator = NO;
[super viewDidLoad];
[self returnImages];
}
-(void)returnImages{
for (pageNumber = 1; pageNumber <= 3; pageNumber++) {
imagen = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:#"%d.png",pageNumber]]];
imagen.frame = CGRectMake((pageNumber-1)*1024, 0, 1024, 768);
[ScView addSubview:imagen];
}
}
//
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return ScView;
// return [imagen initWithImage:[UIImage imageNamed:[NSString stringWithFormat:#"%d.png",pageNumber]]];
}
- (void)scrollViewWillBeginZooming:(UIScrollView *)myScrollView withView:(UIView *)view
{
NSLog(#"Scroll Will Begin");
ScView.scrollEnabled = YES;
}
- (void)scrollViewDidEndZooming:(UIScrollView *)myScrollView withView:(UIView *)view atScale:(float)scale
{
if(scale == 1)
{
ScView.scrollEnabled = YES;
ScView.pagingEnabled = YES;
[self returnImages];
NSLog(#"Scrolol will end");
//ScView.maximumZoomScale = 2.0f;
// [super viewDidLoad];
[self returnImages];
}
}
Any ideas will be highly appreciated..
To get proper paging and zooming you have to embed UIScrollView for each page into your parent UIScrollView. This combination will allow you to use simultaneously paging and internal scrolling.
Here is the example of UIViewController with parent scroll view and three embedded zoomable pages.
#define VIEW_FOR_ZOOM_TAG (1)
#implementation SVViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIScrollView *mainScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
mainScrollView.pagingEnabled = YES;
mainScrollView.showsHorizontalScrollIndicator = NO;
mainScrollView.showsVerticalScrollIndicator = NO;
CGRect innerScrollFrame = mainScrollView.bounds;
for (NSInteger i = 0; i < 3; i++) {
UIImageView *imageForZooming = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:#"page%d", i + 1]]];
imageForZooming.tag = VIEW_FOR_ZOOM_TAG;
UIScrollView *pageScrollView = [[UIScrollView alloc] initWithFrame:innerScrollFrame];
pageScrollView.minimumZoomScale = 1.0f;
pageScrollView.maximumZoomScale = 2.0f;
pageScrollView.zoomScale = 1.0f;
pageScrollView.contentSize = imageForZooming.bounds.size;
pageScrollView.delegate = self;
pageScrollView.showsHorizontalScrollIndicator = NO;
pageScrollView.showsVerticalScrollIndicator = NO;
[pageScrollView addSubview:imageForZooming];
[mainScrollView addSubview:pageScrollView];
if (i < 2) {
innerScrollFrame.origin.x += innerScrollFrame.size.width;
}
}
mainScrollView.contentSize = CGSizeMake(innerScrollFrame.origin.x + innerScrollFrame.size.width, mainScrollView.bounds.size.height);
[self.view addSubview:mainScrollView];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return [scrollView viewWithTag:VIEW_FOR_ZOOM_TAG];
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotate {
return NO;
}
#end
I follow #NikNarmo 's solution, write a small swift xcode project to demo the zooming and paging function.
Hope to help anyone who want to do the same task.
Some code is from UIScrollView Tutorial: Getting Started http://www.raywenderlich.com/76436/use-uiscrollview-scroll-zoom-content-swift,
and some from A Beginner’s Guide to UIScrollView http://www.appcoda.com/uiscrollview-introduction/.
Using Xcode 7.0 and Swift 2.0
override func viewDidLoad() {
super.viewDidLoad()
mainScrollView = UIScrollView(frame: self.view.bounds)
mainScrollView.pagingEnabled = true
mainScrollView.showsHorizontalScrollIndicator = false
mainScrollView.showsVerticalScrollIndicator = false
pageScrollViews = [UIScrollView?](count: photos.count, repeatedValue: nil)
let innerScrollFrame = mainScrollView.bounds
mainScrollView.contentSize =
CGSizeMake(innerScrollFrame.origin.x + innerScrollFrame.size.width,
mainScrollView.bounds.size.height)
mainScrollView.backgroundColor = UIColor.redColor()
mainScrollView.delegate = self
self.view.addSubview(mainScrollView)
configScrollView()
addPageControlOnScrollView()
}
and the magic is in the func scrollViewWillEndDragging, when the contentSize is equal to the mainScrollViewContentSize or not, if it is mainScrollViewController, then do paging, otherwise do nothing.
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let targetOffset = targetContentOffset.memory.x
let zoomRatio = scrollView.contentSize.height / mainScrollViewContentSize.height
if zoomRatio == 1 {
// mainScrollViewController
let mainScrollViewWidthPerPage = mainScrollViewContentSize.width / CGFloat(pageControl.numberOfPages)
let currentPage = targetOffset / (mainScrollViewWidthPerPage * zoomRatio)
pageControl.currentPage = Int(currentPage)
loadVisiblePages()
}
else {
// pageScorllViewController
}
}
And here is the project code https://github.com/Charles-Hsu/ScrollViewDemo