Changing content view insets in collection view messes up UI - swift

For the messaging part of my app, I have a collection view to display the messages. When the keyboard shows, I change the content and scroll bottom insets to be above the keyboard. When I dismiss the keyboard, and the insets go back to their original position, the text bubbles that are the messages reappear in a very distorted manner
This is my code in the setCollectionViewInstets() function
messagesCollectionView.scrollIndicatorInsets = UIEdgeInsets(top: 0 , left: 0, bottom: insetFromBottom, right: 0)//setting scroll indicator b4 content inset is much less glitchy
messagesCollectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: insetFromBottom, right: 0)
messagesCollectionView.layoutIfNeeded()
In the keyboard notification selector function, I have this functionality:
if isKeyboardShowing{
print("keyboard showing")
textViewBottomConstraint.constant = keyboardHeight + initialGapBetweenBottomOfScreenAndTextView!
setCollectionViewInsets(insetFromBottom: keyboardHeight)
scrollToBottomOfCollectionView(animated: true)
}else{
print("keyboard hiding")
textViewBottomConstraint.constant = initialGapBetweenBottomOfScreenAndTextView!
setCollectionViewInsets(insetFromBottom: 0)
}
view.layoutIfNeeded()
I expect the chat bubbles to smoothly scroll back in. Due to keyboard animation, the insets change with the same animation as the keyboard. Could this be why, and is there a way around it?

Related

UITableView ContentInset and ContentOffset

I'm having trouble with the contentInset property. I have a UITableView, with dynamic cell sizes (AutoLayout). I'm setting the contentInset property to leave some space above the top of the content. But I'm getting the following result:
The content is in blue, the content inset in purple. When the table view first appears, it is in the left situation. I can scroll to get to the right situation, that is working, but I would like the table view to appears directly as in the right illustration — which I thought would be the default behavior.
How can I achieve that?
Not sure if it's the best way but I fixed it by adding:
tableView.contentOffset.y = -70
after the line:
tableView.contentInset = UIEdgeInsets(top: 70, left: 0, bottom: 50, right: 0)
you can scroll programmatically when the view loads.
tableView.setContentOffset(CGPoint(x: 0, y: -70), animated: false)
This is how it can be fixed easily from the Storyboard:
Table View > Size Inspector > Content Insets: Never
You provide an UIEdgeInset object,
UIEdgeInsets(top: 50, left: 0, bottom: 0, right: 0)
The top property shows the distance from top of content to top border of the area.

CollectonView "readjusts" origin after loaded into view

I am making a custom sticker pack. It is an iMessage Extension app. I am subclassing UICollectionView rather than using the basic MSMessagesViewController. So this happens only when I select the chevron icon in the expanded view to change back to the compact view. What's going on(you can see in the gif below) is the stickers are place in the view and appear to be set in their location, but after a split second, they seem to readjust their positions...Is there something in CollectionView that I should be doing to prevent this?
I'm starting to think it could be a bug, because the header bar that contains the text field, iMessage app drawer icon, heart icon and camera icon seem to be cut-off about the same amount as the shift.
here is the code from github
The problem with your code is that the contentInset for your collectionView in your layout() call is 6 pixel off from the original position. That's why the animation adjusts the 6 pixel after the animation has finished.
Just change the UIEdgeInsets() in your layout() call inside the StickerCollectionVC to:
self.collectionView?.contentInset = UIEdgeInsets( top: screenW * 0.1 - 6,
left: screenW * 0.1,
bottom: 20 + (screenW * 0.1),
right: screenW * 0.1)

Header View behind NavigationBar [duplicate]

I have a UICollectionView that is the entire view but it lives inside "view" (it is not UICollectionViewController). Adding a cell to this collection view shows it in the following order in storyboard:
This is how it looks in the emulator:
I don't understand how to get rid of that view. All the insets are at zero in Storyboard Size Inspector for collection view. Just to be sure, I also have the following code:
override func viewWillLayoutSubviews() {
let layout = self.collectionViewProducts.collectionViewLayout as! UICollectionViewFlowLayout
let containerWidth = UIScreen.main.bounds.size.width - 40.0
let itemWidth = (containerWidth / 3.0)
let itemHeight = (itemWidth / 0.75) + 30
layout.sectionInset = UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)
layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
}
How can I get rid of that top padding?
You can fix top padding issue by considering one of the following method.
Method 1: Natural way to fix your problem by setting up your collectionView dimensions properly from StoryBoard.
Method 2: **Updated**
You can validate collection frame in viewDidLayoutSubviews or viewWillLayoutSubviews
override func viewDidLayoutSubviews() {
collectionView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
}
Method 3: You can Adjust Scroll View Insets from your StoryBoard Attributes Inspector.
Method 4: You can fix this issue programatically by adjusting CollectionView contentInset.
collectionView.contentInset = UIEdgeInsets(top: **Any Value**, left: 0, bottom: 0, right: 0)
Output with top padding 5:
Output with top padding 44:
Output with top padding 64:
I think because this viewController is embedded in a navigationController. Let select this viewController in the storyboard and uncheck Adjust Scroll View Insets:
There is one more way to resolve this issue and that is selecting collectionView -> scrollView Content Insets -> "Automatic" to "Never".
By default scrollView Content Insets value is Automatic. Please check the below image.
For more details check: UIScrollView.ContentInsetAdjustmentBehavior
https://developer.apple.com/documentation/uikit/uiscrollview/2902261-contentinsetadjustmentbehavior
Make your Navigation Controller > NavigationBar translucent by unchecking the Translucent check box in IB > Attribute Inspector, and it will work.
I also had the same problem, and i fixed it with a way totally ridiculous solution.
My collectionView contained several sections which had no title & no item cells.
The top, bottom inset values of the section insets were 10 respectively.
so each empty section charged height of 20 pixels.
I had 4 empty sections, and therefore, 80 top margins in the collection view.
Hope you check this as well if none of the above solutions works.

Translucent Status Bar with No Navigation Bar

Goal: To have a table view scroll so that it shows semitransparent under the status bar while not displaying a navigation bar.
Right now, I have my tableView set to the top anchor (so technically underneath the status bar). This sets the status bar to a solid looking color as you scroll up on the table view. I've set the navigationAppearance's barTintColor and translucent to YES with no luck.
Any ideas? The view is instantiated in a storyboard
Your question is hard to guess without any code.I believe you trying to achieve a translucent status bar when tableview content scroll like you mentioned in Apple Music app.
Try below code inside your viewdidLoad method.
Step 1: To hide navigation bar. If your controller embedded with navigationController.
navigationController?.navigationBar.isHidden = true
Step 2: Place a statusBar size UIView to your controller to act as a translucent status Bar with adjusting alpha value.
let statusBarView = UIView(frame: CGRect(x:0, y:0, width:view.frame.size.width, height: UIApplication.shared.statusBarFrame.height))
statusBarView.backgroundColor=UIColor.white
statusBarView.alpha = 0.8 // set any value between 0 to 1
view.addSubview(statusBarView)
Above code will produce the following output.Let me know the code works for you.
For more information how to set tableView frame and contentView take a look at my answer in the following link.
Update:
Improved Answer:
You can use UIBlurEffectView to achieve better translucent effect.
let statusBarView = UIView(frame: CGRect(x:0, y:0, width:view.frame.size.width, height: UIApplication.shared.statusBarFrame.height))
let blurEffect = UIBlurEffect(style: .extraLight) // Set any style you want(.light or .dark) to achieve different effect.
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = statusBarView.bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
statusBarView.addSubview(blurEffectView)
view.addSubview(statusBarView)
Output:
As you described, your UITableView is right underneath the status bar. When you scroll down, the tableView's frame remains the same size and origin and won't go underneath the status bar. What you want to do is to set the constraint for your tableView to the top of the superview (not the Top Layout Guide) which means it would sit right under the status bar.
Because the status bar now hides the top 20px of your tableView you want to make a content offset:
tableView.contentInset = UIEdgeInsetsMake(top: 20, left: 0, bottom: 0, right: 0)
To make the scroll indicator start right under the status bar you also want to set an offset for it:
tableView.scrollIndicatorInsets = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)

how to make scrollView behind navigation bar

How to make scrollView work behind navigation bar in swift?
In default setting, when I tap action to hide navigation bar, scrollView slide to up. I want the scrollView keep stay when hiding navigation bar.
thanks
Try adding the scrollView content inset, when you're hiding the bar:
scrollView.contentInset = UIEdgeInsets(top: 100, left: 0, bottom: 0, right: 0)