Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Content makes the View show Nothing #10

Open
btrzupek opened this issue Jul 12, 2016 · 10 comments
Open

Adding Content makes the View show Nothing #10

btrzupek opened this issue Jul 12, 2016 · 10 comments

Comments

@btrzupek
Copy link

Hey, we love this library!

We are having a bit of difficulty right now though. We have a horizontal scrollview in our view controller. When we add test views, simply UIButtons, to the view they add properly and scroll as expected.

When we wired in our function to show the actual UIView content we desire to be displayed, it gets weird. If we provide only a single view to the horizontal scroll view, all displays as expected. If we provide two or more views, then NO views display at all.

We have stepped through and seen our actual views being created and returned, but the HorizontalScrollView is just not displaying 2 or more.

Any ideas on how we can debug this further?

Thanks!

@btrzupek
Copy link
Author

Hey, just an update here. This particular HorizontalScrollView is intended to show a single item (screen width) at a time. In the calculateMarginBetweenItems() function, is where things get weird, man.

For the other HorizontalScrollViews on the page where were have 3+ items showing, this margin gets calculated reasonably. For this particular HorizontalScrollView that shows one item at a time, it returns a gigantic margin number (approx 1/3 the screen width) and that seems to be where things fall apart.

So, are we going down a dead end trying to display a single item per swipe in the HorizontalScrollView?

@terenceLuffy
Copy link
Owner

terenceLuffy commented Jul 12, 2016

Would you post your code of view setup here?

Here is just my guessing, correct me if I am wrong.

You want to show one item with screen width (no margin) at a time, and scroll to next item when user scroll. In such case, I don't think you really need to use this control. For the reason that it is quite easy to implement yourself instead of setup a lot to achieve your purpose (this control is not for this purpose at all). For all the steps you need, is to add all items(no margin) one by one to a scroll view, and get the functions scrollViewWillEndDragging and getClosestItemByX from my control, the first one is to detect where will be the scrolling stop and the second is to get the closest item for the stopping point from first function. They would not exactly what you want, but the idea is almost the same.

If you still decide to use this control, here is the setting:

horizontalScrollView.leftMarginPx = 0
horizontalScrollView.miniAppearPxOfLastItem = 0
horizontalScrollView.uniformItemSize = CGSizeMake(screenWidth, screenHeight)
horizontalScrollView.setItemsMarginOnce()
for _ in 1...5{
     let button = UIButton(frame: CGRectZero)
     button.backgroundColor = UIColor.blueColor()
     horizontalScrollView.addItem(button)
}

And change a little bit

public func calculateMarginBetweenItems() -> CGFloat
    {
        //calculate how many items listed on current screen except the last half appearance one
        var numberOfItemForCurrentWidth = floorf(Float((self.frame.size.width-self.leftMarginPx-self.miniAppearPxOfLastItem)/(self.uniformItemSize.width+self.miniMarginPxBetweenItems)))
        numberOfItemForCurrentWidth = numberOfItemForCurrentWidth == 0 ? 1 : numberOfItemForCurrentWidth
        //round func is not compatible in 32bit devices but only in 64bit(5s and iPad Air), so I use this stupid way :)
        return CGFloat(Int((self.frame.size.width-self.leftMarginPx-self.miniAppearPxOfLastItem)/CGFloat(numberOfItemForCurrentWidth) - self.uniformItemSize.width));
    }

@btrzupek
Copy link
Author

Thanks for the reply, I tried what you suggested and still got the same results :(

Here is the code that we are using (albeit almost exactly what you posted). The primary difference is that we are building a UIView with mixed content instead of returning a UIButton as you are in your example code. When I return a UIButton, it performs as expected - however when I return more than 1 UIView, then I get the behavior described above.

 let rowHeight = self.tableView(self.tableView, heightForRowAtIndexPath: indexPath)
        var itemWidth = rowHeight
        var miniMarginPxBetweenItems:CGFloat = 2.0
        var miniAppearPxOfLastItem:CGFloat = 30.0
        var leftMarginPx:CGFloat = 5.0

        if indexPath.section == 0 {
            itemWidth = self.view.frame.width //-6.0
            miniMarginPxBetweenItems = 0.0
            miniAppearPxOfLastItem = 0.0
            leftMarginPx = 0.0
        }

        // set cells content here
        let horizontalScrollView:ASHorizontalScrollView = ASHorizontalScrollView(frame:CGRectMake(0, 0, tableView.frame.size.width, rowHeight))
        // we only allow a single row
        if indexPath.row == 0{
            var aView:UIView = horizontalScrollView
            horizontalScrollView.backgroundColor = UIColor.blackColor()
            horizontalScrollView.layer.borderColor = UIColor.blackColor().CGColor
            horizontalScrollView.layer.borderWidth = 2
            horizontalScrollView.leftMarginPx = leftMarginPx
            //horizontalScrollView.miniMarginPxBetweenItems = miniMarginPxBetweenItems
            horizontalScrollView.miniAppearPxOfLastItem = miniAppearPxOfLastItem
            horizontalScrollView.uniformItemSize = CGSizeMake(itemWidth, rowHeight)
            //this must be called after changing any size or margin property of this class to get accurate margin
            horizontalScrollView.setItemsMarginOnce()
            // dynamically build the content
            let addedContent = self.buildContentForSection(indexPath.section, horizontalScrollView: horizontalScrollView, cell: cell)
            // did we add any content?
            if !addedContent {
                // create the missing content view for the category of items
                aView = UIView(frame: CGRectMake(0,0, tableView.frame.size.width, rowHeight))
                self.buildContentForEmptySection(indexPath.section, view: aView)
            }
            // add the subview
            cell.contentView.addSubview(aView)
            // setup autolayout and constraints
            aView.translatesAutoresizingMaskIntoConstraints = false
            cell.contentView.addConstraint(NSLayoutConstraint(item: aView,
                attribute: NSLayoutAttribute.Height,
                relatedBy: NSLayoutRelation.Equal, toItem: nil,
                attribute: NSLayoutAttribute.NotAnAttribute,
                multiplier: 1,
                constant: rowHeight))
            cell.contentView.addConstraint(NSLayoutConstraint(item: aView,
                attribute: NSLayoutAttribute.Width,
                relatedBy: NSLayoutRelation.Equal,
                toItem: cell.contentView,
                attribute: NSLayoutAttribute.Width,
                multiplier: 1,
                constant: 0))
        }

@btrzupek
Copy link
Author

Another update:

So, when i return a (Temporary, not the real view I want to return) UIView with some content it all works as expected. However, when I return the real view, things get crazy.

I began looking at what is going on in the real view, and as I was systematically commenting out code, I discovered that the moment that I setup the view constraints with SnapKit for subviews in that UIView that I return, the contents do not display.

For example, if I have a background UIimageView in the UIView that I add to the HorizontalScrollView and I add dynamic constraints to it with SnapKit, it breaks everything.

backgroundImageView.snp_makeConstraints { (make) in
            make.edges.equalTo(contentView.snp_edges)
        }

So it seems that adding constraints to the subviews of the view I add to the HorizontalScrollView is the problem. Do you have any thoughts into why this would be an issue?

Again, If I have a single view that I return (with constraints), it all displays properly. More than 1 and things don't go well.

@btrzupek
Copy link
Author

I figured out the issue. So SnapKit was not playing well with the constraints I added at the root level of the view (in the code above). When I removed the following, it all works (beautifully) as expected. Thanks so much for your comments and help, it got me to the right spot and got this working!

// setup autolayout and constraints
            aView.translatesAutoresizingMaskIntoConstraints = false
            cell.contentView.addConstraint(NSLayoutConstraint(item: aView,
                attribute: NSLayoutAttribute.Height,
                relatedBy: NSLayoutRelation.Equal, toItem: nil,
                attribute: NSLayoutAttribute.NotAnAttribute,
                multiplier: 1,
                constant: rowHeight))
            cell.contentView.addConstraint(NSLayoutConstraint(item: aView,
                attribute: NSLayoutAttribute.Width,
                relatedBy: NSLayoutRelation.Equal,
                toItem: cell.contentView,
                attribute: NSLayoutAttribute.Width,
                multiplier: 1,
                constant: 0))

@terenceLuffy
Copy link
Owner

I'm grad to hear that! It is always a good thing to solve the problem by yourself.

@armaanbindra
Copy link

armaanbindra commented Dec 13, 2016

Hi @terenceLuffy ,
I am having an issue where I am trying to create a UIView the containerView that contains an ImageView and UILabel and that take that first UIView and add many like that to the ASHorizontalScroll view, but when I try that it seems like all my subviews disappear and are not showing up(only the first view shows up in the horizontal scroll view. So in this case only the container view shows up(without the image and label) now if instead of the container view I first just start with an image view and add a label as a subview, again the label disappears and I only see the image. I would really like each item in the horizontal view to be more complex than just one view, to achieve what I want kind of like friend suggestions in Instagram(see the attached screenshot) and was hoping your library could help me achieve that.
Thanks,
Armaan

Here is my exact code:

          let cell = tableView.dequeueReusableCell(withIdentifier: "SuggestionCell",
                                                     for: indexPath)
            let horizontalScrollView:ASHorizontalScrollView = ASHorizontalScrollView(frame:CGRect(x: kMargin, y: 0, width: tableView.frame.size.width - kMargin, height: suggestionHeight))
            horizontalScrollView.backgroundColor = ColorHelper.whiteBackgroundColor
            horizontalScrollView.uniformItemSize = CGSize(width: kCellWidth, height: kCellHeight!)
            
            //for iPhone 5s and lower versions in portrait
            horizontalScrollView.marginSettings_320 = MarginSettings(leftMargin: kMargin , miniMarginBetweenItems: kMargin * 0.5, miniAppearWidthOfLastItem: 0)
            // for iPhone 6 plus and 6s plus in portrait
            horizontalScrollView.marginSettings_414 = MarginSettings(leftMargin: kMargin , miniMarginBetweenItems: kMargin * 0.5, miniAppearWidthOfLastItem: 0)
            // for iPhone 6 plus and 6s plus in landscape
            horizontalScrollView.marginSettings_736 = MarginSettings(leftMargin: kMargin , miniMarginBetweenItems: kMargin * 0.5, miniAppearWidthOfLastItem: 0)
            //for all other screen sizes that doesn't set here, it would use defaultMarginSettings instead
            
            //this must be called after changing any size or margin property of this class to get acurrate margin
            horizontalScrollView.setItemsMarginOnce()
            for _ in 1...13{
                let singleSuggestionView = UIView(frame: CGRect.zero)
                singleSuggestionView.backgroundColor = ColorHelper.blackColor
                singleSuggestionView.layer.cornerRadius = 5.0
                let imageView = UIImageView(frame: CGRect(x: 0.0, y: 0.0, width: singleSuggestionView.frame.width, height: singleSuggestionView.frame.width * 0.75))
                imageView.contentMode = .scaleAspectFill
                Utility.setImage(singleSuggestionView, imageURL: "https://projects.liovinci.com/p_54607433ed54a6637989d08d0d2069622b09b35c.jpg", defaultPic: UIImage(named: "placeholder")!)
                imageView.clipsToBounds = true
                imageView.backgroundColor = ColorHelper.redColor
                singleSuggestionView.addSubview(imageView)
                horizontalScrollView.addItem(singleSuggestionView)
            }

            cell.contentView.addSubview(horizontalScrollView)
            horizontalScrollView.translatesAutoresizingMaskIntoConstraints = false
            cell.contentView.addConstraint(NSLayoutConstraint(item: horizontalScrollView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: suggestionHeight))
            cell.contentView.addConstraint(NSLayoutConstraint(item: horizontalScrollView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: cell.contentView, attribute: NSLayoutAttribute.width, multiplier: 1, constant: 0))
            return cell

Here is the Instagram view:
fullsizerender jpg

@terenceLuffy
Copy link
Owner

terenceLuffy commented Dec 13, 2016

@armaanbindra I don't think your problem is related to this control. I can see you firstly setup your container frame zero, and then you set the frame of image view with the container's size, that would be 0 totally since the container is not loaded yet, that's why it doesn't show, try to add constraints or design it in storyboard to get your custom view instead, that might be more straight forward to you.

@armaanbindra
Copy link

armaanbindra commented Dec 13, 2016

Aha, Oh I see, thanks @terenceLuffy , I was trying to follow your swift example where it set it to CGRect.zero, yet the eventual view that showed up was not zero but the size specified by uniformItemSize, so even though the first value of the frame is CGRect.zero the library uses the uniform size and constraints to reset the first view's frame. I simply changed the height and width of the container frame manually to the fixed height and width of each item that I needed and now it works perfectly, thanks so much for your help and pardon my misunderstanding.

          let cell = tableView.dequeueReusableCell(withIdentifier: "SuggestionCell",
                                                     for: indexPath)
            let horizontalScrollView:ASHorizontalScrollView = ASHorizontalScrollView(frame:CGRect(x: kMargin, y: 0, width: tableView.frame.size.width - kMargin, height: suggestionHeight))
            horizontalScrollView.backgroundColor = ColorHelper.whiteBackgroundColor
            horizontalScrollView.uniformItemSize = CGSize(width: kCellWidth, height: kCellHeight!)
            
            //for iPhone 5s and lower versions in portrait
            horizontalScrollView.marginSettings_320 = MarginSettings(leftMargin: kMargin , miniMarginBetweenItems: kMargin * 0.5, miniAppearWidthOfLastItem: 0)
            // for iPhone 6 plus and 6s plus in portrait
            horizontalScrollView.marginSettings_414 = MarginSettings(leftMargin: kMargin , miniMarginBetweenItems: kMargin * 0.5, miniAppearWidthOfLastItem: 0)
            // for iPhone 6 plus and 6s plus in landscape
            horizontalScrollView.marginSettings_736 = MarginSettings(leftMargin: kMargin , miniMarginBetweenItems: kMargin * 0.5, miniAppearWidthOfLastItem: 0)
            //for all other screen sizes that doesn't set here, it would use defaultMarginSettings instead
            
            //this must be called after changing any size or margin property of this class to get acurrate margin
            horizontalScrollView.setItemsMarginOnce()
            for _ in 1...13{
                let singleSuggestionView = UIView(frame: CGRect.zero)
                singleSuggestionView.backgroundColor = ColorHelper.blackColor
                singleSuggestionView.layer.cornerRadius = 5.0
                let imageView = UIImageView(frame: CGRect(x: 0.0, y: 0.0, width: kCellWidth, height: kCellHeight * 0.75))
                imageView.contentMode = .scaleAspectFill
                Utility.setImage(singleSuggestionView, imageURL: "https://projects.liovinci.com/p_54607433ed54a6637989d08d0d2069622b09b35c.jpg", defaultPic: UIImage(named: "placeholder")!)
                imageView.clipsToBounds = true
                imageView.backgroundColor = ColorHelper.redColor
                singleSuggestionView.addSubview(imageView)
                horizontalScrollView.addItem(singleSuggestionView)
            }

            cell.contentView.addSubview(horizontalScrollView)
            horizontalScrollView.translatesAutoresizingMaskIntoConstraints = false
            cell.contentView.addConstraint(NSLayoutConstraint(item: horizontalScrollView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: suggestionHeight))
            cell.contentView.addConstraint(NSLayoutConstraint(item: horizontalScrollView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: cell.contentView, attribute: NSLayoutAttribute.width, multiplier: 1, constant: 0))
            return cell

@indrac
Copy link

indrac commented Apr 12, 2017

@btrzupek Hi, I use SnapKit as well and the result is quite same like you it only shows one view. What are you doing exactly to fix this issue? Are you remove your SnapKit code?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants