Comments (40)
Actually, that didn't solved it after all. It still happens sometimes.
I think that this issue might not be caused only by auto-layout, but by the tableView/collectionView it self.
I found another fix, instead of setting edgesForExtendedLayout
to UIRectEdgeNone
:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (self.collectionView.contentOffset.y < 0 && self.collectionView.emptyDataSetVisible) {
self.collectionView.contentOffset = CGPointZero;
}
}
What happens is that the scrollview has a contentOffset of {0,-3} at viewWillAppear
if no content is insert inside of it. And then changes drastically to {0,-67}. So setting the contentSize to zero should help out, but it's not the most decent solution either!
from dznemptydataset.
Some more things I found out:
- When using a
UITableViewController
, in some casesreloadData
will be triggered inviewWillAppear:
. - During
viewWillAppear
, thetopLayoutGuide
, and thus thecontentInset
is not yet set. - If you have an empty data set in this situation, and you add it to the
UITableView
it will have the wrong offset once thecontentInset
is set to match thetopLayoutGuide
. - The earliest point at which
topLayoutGuide
is set is after the first invocation ofviewDidLayoutSubviews
. - This allows us to do something like this:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if (!self.tableView.emptyDataSetSource) {
self.tableView.emptyDataSetSource = self;
self.tableView.emptyDataSetDelegate = self;
[self.tableView reloadEmptyDataSet];
}
}
This, together with the pull request I referenced above is giving me consistent behaviour so far.
from dznemptydataset.
Yup, I have this issue as well. FWIW, I have a toolbar underneath the navbar, and I am using a vertical offset to try to fix this problem, but it only works sometimes. If all items disappear from a table view and the emptydataset view appears, it's in the middle (good). But if I create a new table view and it's empty right away, it's low (low = bad, I use the offset to move it up, which messes up the middle case and makes it too high).
I haven't tried the solution in #11 yet (don't have access to that computer here).
from dznemptydataset.
you need just to set this in the delegate:
func emptyDataSetWillAppear(_ scrollView: UIScrollView!) {
scrollView.bounds.origin.y = 0
}
from dznemptydataset.
Hey,
Are you displaying a tableview header or footer? Or a section header view?
from dznemptydataset.
I'm only using section headers and section footers (viewForHeader, viewForFooter + height methods).
from dznemptydataset.
Have you tried returning 0 for height methods?
The library uses auto-layout, so it should be vertically centered all the time unless the rect of the tableView is smaller.
Are you using - (CGPoint)offsetForEmptyDataSet:
by any chance?
from dznemptydataset.
Are you installing it with pods? If so, which version are you using?
from dznemptydataset.
Returning height == 0 (or 0.01) doesn't change anything.
I'm not using -(CGPoint)offsetForEmptyDataSet: .
I have the latest version (1.3.1) from Cocoapods.
I did try to reinstall cocoapods and cleaned the build.
No cigar.
from dznemptydataset.
I'll need to see your setup. Can you share your project, or is it client sensible?
If not, just send me over a gist of your complete view controller implementation, over email to [email protected]
I'll be happy to help on this. It doesn't seem like a bug tho.
from dznemptydataset.
I just sent you the .m of the VC. Thanks for your support!
from dznemptydataset.
I saw your gist, and the setup is perfect. That's not it then.
What data are you removing? Can you please explain step by step what's going on until you get that bad alignment? Are you getting auto-layout error logs?
Can you try adding self.edgesForExtendedLayout = UIRectEdgeNone;
in your viewDidLoad
?
from dznemptydataset.
Steps to reproduce the problem are as follows:
- Show the empty vc. EmptyDataSet shows up nicely.
- Add some data. The vc shows data properly.
- Delete the data by swiping left and tapping red "delete" button.
- Since _dataSource is empty, the EmptyDataSet shows up, but it's misaligned.
After adding self.edgesForExtendedLayout = UIRectEdgeNone the EDS seems to appear properly in the center. The tabbar is greyed, though.
from dznemptydataset.
I re-did part of the Colors sample project, trying to reproduce your setup, by using a UITabBarController, external data source and swip gesture for cell deletion, and I couldn't find any issue. I even didn't have to call self.edgesForExtendedLayout = UIRectEdgeNone
.
Please take a look at the updated sample project, and compare it with your View hierarchy and setup.
from dznemptydataset.
Were you able to fix this? Did you take a look into the new sample project?
from dznemptydataset.
I just managed to reproduce this bug. It's an auto-layout bug.
For some reason, the navigation bar and status bar's height combined (64px) are not being considered when updating the tableView's constraints when there is no content be be displayed the first time loaded.
Setting edgesForExtendedLayout
to UIRectEdgeNone
fixes this issue on the sample project, but this means the content will not be shown under the navigation and tab bars. This might not be the optimal solution.
The reason why your tab bar greyed out it's because the navigation controller's view containing your view controller has a black background color (by default). Changing it to white might look better.
Here's an illustration of the issue, combining the render of the collectionView and the tableView:
And here's the log of the constraints of the tableView when first displayed:
(
"<NSAutoresizingMaskLayoutConstraint:0x8c28cc0 h=-&- v=-&- DZNEmptyDataSetView:0x8e36ae0.midX == UICollectionView:0x984e400.midX>",
"<NSAutoresizingMaskLayoutConstraint:0x8c28a80 h=-&- v=-&- DZNEmptyDataSetView:0x8e36ae0.width == UICollectionView:0x984e400.width>",
"<NSAutoresizingMaskLayoutConstraint:0x8c28ab0 h=-&- v=-&- DZNEmptyDataSetView:0x8e36ae0.midY == UICollectionView:0x984e400.midY>",
"<NSAutoresizingMaskLayoutConstraint:0x8c28ae0 h=-&- v=-&- DZNEmptyDataSetView:0x8e36ae0.height == UICollectionView:0x984e400.height>"
)
And after loading content on the tableview, and removing it all and calling reloadData
again:
(
"<NSAutoresizingMaskLayoutConstraint:0x8c164a0 h=--& v=--& DZNEmptyDataSetView:0x8d19f90.midX == + 160>",
"<NSAutoresizingMaskLayoutConstraint:0x8c0cb40 h=--& v=--& H:[DZNEmptyDataSetView:0x8d19f90(320)]>",
"<NSAutoresizingMaskLayoutConstraint:0x8c216a0 h=--& v=--& DZNEmptyDataSetView:0x8d19f90.midY == + 284>",
"<NSAutoresizingMaskLayoutConstraint:0x8c216d0 h=--& v=--& V:[DZNEmptyDataSetView:0x8d19f90(568)]>"
)
Looks like the constant factor is being modified...but, who!?
from dznemptydataset.
It was indeed an auto-layout issue on my side!
I was centering the contentView to its superview with string formats:
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[self]-(<=0)-[_contentView]"
options:NSLayoutFormatAlignAllCenterY metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[self]-(<=0)-[_contentView]"
options:NSLayoutFormatAlignAllCenterX metrics:nil views:views]];
Instead, it should have been done with NSLayoutConstraint objects, related between the two provided views:
[self addConstraint:[NSLayoutConstraint constraintWithItem:_contentView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:_contentView.superview
attribute:NSLayoutAttributeCenterX
multiplier:1.f constant:0.f]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:_contentView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:_contentView.superview
attribute:NSLayoutAttributeCenterY
multiplier:1.f constant:0.f]];
Please test it and see if it solves your issue.
from dznemptydataset.
I'm sorry for not responding sooner. Setting self.tableview(or collection view).contentOffset is a very nice quick fix for the issue. It's strange the view is not positioned correctly the first time it shows up but is on the second time, though.
from dznemptydataset.
Closing this, since the only possible solution for now is to manually set the tableView's offset on the view controller's viewDidAppear:
from dznemptydataset.
This is an issue for me too. I would love to see a fix rather than manually setting the tableView's offset in the viewDidAppear:
method. Let me know if I can help at all.
from dznemptydataset.
This is actually caused by UIViewController's property edgesForExtendedLayout
set to UIRectEdgeAll
by default, which moves automatically the tableview offset to -66 (if the status bar and navigation bar are present).
The other work around is to set edgesForExtendedLayout
to UIRectEdgeNone
or a bitmask not including UIRectEdgeTop
Any other suggestions?
from dznemptydataset.
The app I've included this on has UIRectEdgeAll
for edgesForExtendedLayout
. I'll do some testing and see if I can find the cause and a solution.
from dznemptydataset.
Try setting UIRectEdgeNone
. It should fix it, but you will loose the nice blur effect under the navigation bar (if you have any).
from dznemptydataset.
@carsonperrotti @pawelkata can you please try out with the latest in master, and tell me if the issue is still present? Thanks!
from dznemptydataset.
I'm experiencing a few issues with incorrect vertical centering as well.
I don't think we should fiddle too much with edgesForExtendedLayout
but look at the UIScrollView
contentInset
instead.
I'm using this as a workaround for now:
- (CGPoint)offsetForEmptyDataSet:(UIScrollView *)scrollView {
CGFloat top = scrollView.contentInset.top / 2;
CGFloat bottom = scrollView.contentInset.bottom / 2;
return CGPointMake(0, top-bottom);
}
Edit:
Thinking out loud here, but it might be possible to use KVO on the contentInset
and adjust the top, left, right, bottom constraint constants based on it. Haven't tried though.
Edit 2:
Of course it would also be possible to have a dynamic 'base offset' that applies the workaround I posted above by default.
Overriding offsetForEmptyDataSet
would then apply the user provided offset to the 'base offset'.
Edit 3:
Leaning to heavily on the contentInset
might not be the right thing to do either, since a refreshControl
also changes the contentInset
. The value from which the initial contentInset
is derived is the UIViewController
's topLayoutGuide
.
from dznemptydataset.
@dzenbot Sorry for not responding sooner. The thing is, I've converted all projects to Auto Layout and there were zero problems with DZNEmptyDataSet since then, so I can't really reliable test whether it works under previous conditions or not :-( Thanks for updating the library, though. It's been a blast to use and simplifies an important UI case.
from dznemptydataset.
@pawelkata When you show the empty data set in a UITableViewController, is it perfectly centred on the screen, or in the "area underneath the navigation bar" ?
I ask because for fullscreen UITableView
's it looks good when the content isn't perfectly centred (it's offset to the top slightly), but it might still be off-center.
from dznemptydataset.
@bartvandendriessche It seems cenetered in the area underneath the navbar on the iPad, but it's centered on the screen on the iPhone (same app, universal binary).
from dznemptydataset.
Interesting! The order of how things are setup when using UITableViewController
is a bit confusing, and the fact we cannot access topLayoutGuide
at the right time made this fix really hard.
I'll try that technique, but what's sad is that we cannot really make it part of the library...
from dznemptydataset.
BW, I've just merged you PR @bartvandendriessche. Thanks!
from dznemptydataset.
Just wanted to say I've implemented DZNEmptyDataSet in one of my new apps (should be released in early Janurary) and it works AWESOMELY! No problems whatsoever. Thanks a bunch Ignacio! :D
from dznemptydataset.
That's great to know! Please post your renders in #4.
from dznemptydataset.
I am still facing this misalignment problem:
I included the library via CocoaPods: pod 'DZNEmptyDataSet', '~> 1.5.2'
I am only using the data source and implementing the following method:
- (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView {
NSString *text = NSLocalizedString(@"Carregando...", @"Loading...");
NSDictionary *attributes = @{NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue-Light" size:16.0],
NSForegroundColorAttributeName: [UIColor darkGrayColor]};
return [[NSAttributedString alloc] initWithString:text attributes:attributes];
}
from dznemptydataset.
I noticed that the label appears in the correct position at first, but if I call reloadEmptyDataSet
it changes. I am calling that method to update the string from "Loading" to a message saying there is no content to be show. I suppose that is the correct way to refresh the text, right?
from dznemptydataset.
Using code
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if collectionView?.emptyDataSetSource == nil {
collectionView?.emptyDataSetSource = self
collectionView?.reloadEmptyDataSet()
}
}
correctly places empty view in the vertical centre, however when I add a pull to refresh control MJRefresh, the refreshing header isn't visible while the empty view scrolls down as suggested in the second problem of issue #43.
I just set collectionView's header to refresh header and invoke collectionView?.header.beginRefreshing()
in viewDidLoad()
method for initial data fetching.
By the way, any other views that do not override viewDidLayoutSubviews()
all shows refreshing header normally.
Any suggestions for this problem? @dzenbot
from dznemptydataset.
Created the view with snapkit. But it is terribly misplaced. How to resolve this.
func offsetForEmptyDataSet(scrollView: UIScrollView!) -> CGPoint {
let top = scrollView.contentInset.top/2
let bottom = scrollView.contentInset.bottom/2
return CGPoint(x: 0, y: top-bottom)
}
func customViewForEmptyDataSet(scrollView: UIScrollView!) -> UIView! {
let view = TNYEmptyStateView(stateType: .NoOrder)
return view
}
from dznemptydataset.
I'm also having this problem still. Using the latest version on Pods.
I'm perplexed as to how something seemingly so simple is still unaddressed?
using this solution (below) has seemed to solve it though
- (CGPoint)offsetForEmptyDataSet:(UIScrollView *)scrollView {
CGFloat top = scrollView.contentInset.top / 2;
CGFloat bottom = scrollView.contentInset.bottom / 2;
return CGPointMake(0, top-bottom);
}
from dznemptydataset.
I'm facing the same problem.
My app has a collection view under a navigation bar with a search bar.
I tried this solution: #11 (comment)
It works but shows misplaced views for a second.
Maybe a too primitive solution but the following works fine.
func verticalOffset(forEmptyDataset scrollView: UIScrollView!) -> CGFloat {
return -64
}
from dznemptydataset.
@henning-jh I'm having the exact same issue. Were you able to figure it out?
from dznemptydataset.
You can use my fork https://github.com/MojtabaHs/DZNEmptyDataSet
from dznemptydataset.
Related Issues (20)
- Crash DZNEmptyDataSet HOT 1
- emptyView beyond current window
- Blank page display error on TableView or CollectionView
- SwiftPM Support / swift package init HOT 1
- 自定义空白占位图不显示 HOT 1
- Create a new release to make SPM take effect HOT 4
- customer HOT 1
- 刷新导致奔溃的问题 -[UIScrollView(DZNEmptyDataSet) dzn_reloadEmptyDataSet] HOT 6
- Wrong offset of empty data view position. HOT 3
- About the custom view cannot respond to the click event HOT 2
- support swift 5 ? HOT 1
- UITapGestureRecognizer cannot work in customView HOT 2
- 滚动一段距离y,再刷新,刚好数据为空,这时占位图也会偏移y,解决方法如下: HOT 2
- EmptyDataSetView fadeIn Animation is not working (fadeInOnDisplay should be set before the view is added into his superview so that the fade in animation can be applied.) HOT 1
- App crashed with unrecognized selector setClaCustomViewVisible
- tableViewHeader may be covered
- Is there a swift version
- SPM defaults to v1.8.1, but that version has no Package.swift HOT 5
- DetailLabel and TitleLabel layout is NOT set well HOT 1
- offset
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dznemptydataset.