Giter Club home page Giter Club logo

Comments (40)

dzenbot avatar dzenbot commented on June 8, 2024 4

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.

bartvandendriessche avatar bartvandendriessche commented on June 8, 2024 1

Some more things I found out:

  • When using a UITableViewController, in some cases reloadData will be triggered in viewWillAppear:.
  • During viewWillAppear, the topLayoutGuide, and thus the contentInset 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 the contentInset is set to match the topLayoutGuide.
  • The earliest point at which topLayoutGuide is set is after the first invocation of viewDidLayoutSubviews.
  • 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.

henning-jh avatar henning-jh commented on June 8, 2024 1

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.

Fouda avatar Fouda commented on June 8, 2024 1

you need just to set this in the delegate:

func emptyDataSetWillAppear(_ scrollView: UIScrollView!) {
scrollView.bounds.origin.y = 0
}

from dznemptydataset.

dzenbot avatar dzenbot commented on June 8, 2024

Hey,
Are you displaying a tableview header or footer? Or a section header view?

from dznemptydataset.

pawelkata avatar pawelkata commented on June 8, 2024

I'm only using section headers and section footers (viewForHeader, viewForFooter + height methods).

from dznemptydataset.

dzenbot avatar dzenbot commented on June 8, 2024

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.

dzenbot avatar dzenbot commented on June 8, 2024

Are you installing it with pods? If so, which version are you using?

from dznemptydataset.

pawelkata avatar pawelkata commented on June 8, 2024

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.

dzenbot avatar dzenbot commented on June 8, 2024

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.

pawelkata avatar pawelkata commented on June 8, 2024

I just sent you the .m of the VC. Thanks for your support!

from dznemptydataset.

dzenbot avatar dzenbot commented on June 8, 2024

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.

pawelkata avatar pawelkata commented on June 8, 2024

Steps to reproduce the problem are as follows:

  1. Show the empty vc. EmptyDataSet shows up nicely.
  2. Add some data. The vc shows data properly.
  3. Delete the data by swiping left and tapping red "delete" button.
  4. 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.

Screenshot:
ios simulator screen shot 1 lip 2014 17 11 55

from dznemptydataset.

dzenbot avatar dzenbot commented on June 8, 2024

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.

dzenbot avatar dzenbot commented on June 8, 2024

Were you able to fix this? Did you take a look into the new sample project?

from dznemptydataset.

dzenbot avatar dzenbot commented on June 8, 2024

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:
image

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.

dzenbot avatar dzenbot commented on June 8, 2024

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.

pawelkata avatar pawelkata commented on June 8, 2024

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.

dzenbot avatar dzenbot commented on June 8, 2024

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.

carsonxyz avatar carsonxyz commented on June 8, 2024

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.

dzenbot avatar dzenbot commented on June 8, 2024

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.

carsonxyz avatar carsonxyz commented on June 8, 2024

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.

dzenbot avatar dzenbot commented on June 8, 2024

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.

dzenbot avatar dzenbot commented on June 8, 2024

@carsonperrotti @pawelkata can you please try out with the latest in master, and tell me if the issue is still present? Thanks!

from dznemptydataset.

bartvandendriessche avatar bartvandendriessche commented on June 8, 2024

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.

pawelkata avatar pawelkata commented on June 8, 2024

@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.

bartvandendriessche avatar bartvandendriessche commented on June 8, 2024

@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.

pawelkata avatar pawelkata commented on June 8, 2024

@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.

dzenbot avatar dzenbot commented on June 8, 2024

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.

dzenbot avatar dzenbot commented on June 8, 2024

BW, I've just merged you PR @bartvandendriessche. Thanks!

from dznemptydataset.

pawelkata avatar pawelkata commented on June 8, 2024

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.

dzenbot avatar dzenbot commented on June 8, 2024

That's great to know! Please post your renders in #4.

from dznemptydataset.

guilhermearaujo avatar guilhermearaujo commented on June 8, 2024

I am still facing this misalignment problem:

error

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.

guilhermearaujo avatar guilhermearaujo commented on June 8, 2024

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.

alex4814 avatar alex4814 commented on June 8, 2024

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.

vishal91 avatar vishal91 commented on June 8, 2024

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.

victorstewart avatar victorstewart commented on June 8, 2024

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.

manicmaniac avatar manicmaniac commented on June 8, 2024

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.

dispatchswift avatar dispatchswift commented on June 8, 2024

@henning-jh I'm having the exact same issue. Were you able to figure it out?

from dznemptydataset.

MojtabaHs avatar MojtabaHs commented on June 8, 2024

You can use my fork https://github.com/MojtabaHs/DZNEmptyDataSet

from dznemptydataset.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.