I'm trying to implement a Chat screen using UICollectionView in Swift 4.2. I've done it.
I want to improve it by making the cells grow from bottom to top instead of top to bottom (while keeping the order of messages too). Any help? I've tried searching for it, still unsuccessful.
The easiest way would be to flip the collection view and its cells:-
cv.transform = CGAffineTransform(scaleX: 1, y: -1)
cell.contentView.transform = CGAffineTransform(scaleX: 1, y: -1)
Doing this will just flip your CollectionView's content and won't require you to handle anything, I guess
EDIT:-
For your requirement, you shouldn't be appending elements to your array. You should insert new objects as the first element of the array(the data source):-
myArray.insert(element, at: 0)
In order to get the right order, you can just reverse the array
You have to make collection view height constraint outlet for it and calculate your cells height after that you can set height of collectionView. and one case will come of maximum height, your collection height will equal from screen height with calculate space your navigation and input textview.
Have you tried
let diff = collectionView.frame.height - collectionView.contentSize.height
if diff > 0 {
collectionView.contentInset = UIEdgeInsets(top: diff, left: 0, bottom: 0, right: 0)
}
You can modify the top inset of the collection view as the collectionView reloads.
Call this after calling reloadData():
func updateCollectionContentInset() {
let contentSize = yourCollectionView.collectionViewLayout.collectionViewContentSize
var contentInsetTop = yourCollectionView.bounds.size.height
contentInsetTop -= contentSize.height
if contentInsetTop <= 0 {
contentInsetTop = 0
}
yourCollectionView.contentInset = UIEdgeInsets(top: contentInsetTop,left: 0,bottom: 0,right: 0)
}
Related
I created a list by using collection view compositional layout and implemented a default style cell ( please see the picture UICollectionViewListCell
There is a space of 20pt on the left side of the text. The space might be different on different screen sizes.
I tried to set its leading inset to 0, but the space won't reflect the value unless the value is bigger than 20
section.contentInsets = .init(top: 0, leading: 0, bottom: 0, trailing: 0)
Is there any way to remove the space? or how can I get the space value?
UICollectionViewListCell has a property called indentationWidth which is used to configure the indentation width. You might also want to look at indentationLevel property as well.
let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Item> { cell, indexPath, item in
cell.indentationWidth = 0
}
I want to create layout for following layout inside collection view.
Align one cell in centre and two cell outside with scale down using transform.
I have used third party library DXScaleFlowLayout and implemented following code to make like same.
let scaleLayout = DXScaleFlowLayout()
scaleLayout.transformScale = 0
scaleLayout.isPagingEnabled = true
scaleLayout.minimumAlpha = 0.8
scaleLayout.minimumLineSpacing = 0
scaleLayout.minimumInteritemSpacing = 0
let width = self.cvBusinessPlans.bounds.width
let height = self.cvBusinessPlans.bounds.height
scaleLayout.itemSize = CGSize(width: width, height: height)
scaleLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
self.cvBusinessPlans.collectionViewLayout = scaleLayout
But it didn't work for me. If anyone know how to make this then please help. I have search of SOF, but I can't find exact or similar solution.
I am creating an application with a user interface similar to Tinder's. To recreate this user interface, I've had to employ a UIPageViewController embedded in a container view with UIButtons laid over the container view. Recreating this UI is expensive and causes my app to drop in frame rate.
Note the drop in frame rates when swiping to the right page.
Whenever the user scrolls between pages, the overlaid UIButtons adjust in size and color based on how much the user has scrolled between pages. This is done by subclassing the UIPageViewController as a UIScrollViewDelegate and passing the UIPageViewController's UIScrollView's contentOffset.x as a percent of the superview's width to a function that adjusts the overlaid buttons accordingly.
extension PageViewController: UIScrollViewDelegate {
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
let point = scrollView.contentOffset
var percentComplete: CGFloat
percentComplete = abs(point.x - view.frame.size.width)/view.frame.size.width
if !(point.x > view.frame.width && currentPage == 2) && !(point.x < view.frame.width && currentPage == 0) {
if point.x < view.frame.width {
containerVC.adjustButtons(for: percentComplete, direction: 1)
} else {
containerVC.adjustButtons(for: percentComplete, direction: 0)
}
}
}
}
The function that adjusts the size and color of my buttons is called every time scrollViewDidScroll is called. This is done by referencing how much the UIPageViewController has scrolled and adjusting button constraints, image insets, and images accordingly. This function is likely extremely expensive as it is called each time scrollViewDidScroll is called, but I am unsure how else to approach the issue.
The end-result is the behavior that I expected, but there is a considerable drop in frame rate at times when a scroll in the UIPageViewController is begun.
func adjustButtons(for percentage: CGFloat, direction: Int) {
buttonWrapperLeading.constant = (view.frame.width/2 - 38) * percentage
buttonWrapperTrailing.constant = (view.frame.width/2 - 38) * percentage
self.profileButton.imageEdgeInsets = UIEdgeInsets(top: 8 * (1-percentage), left: 8 * (1-percentage), bottom: 8 * (1-percentage), right: 8 * (1-percentage))
self.meetButton.imageEdgeInsets = UIEdgeInsets(top: 8 * percentage, left: 8 * percentage, bottom: 8 * percentage, right: 8 * percentage)
self.chatButton.imageEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
let newProfileButtonImage = UIImage(named: "profileSilhouette")!.withRenderingMode(.alwaysTemplate).image(withTintColor: UIColor.interpolate(from: .darkGray, to: .secondaryColor, with: percentage))
profileButton.setImage(newProfileButtonImage, for: .normal)
let newMeetButtonImage = UIImage(named: "meet")!.withRenderingMode(.alwaysTemplate).image(withTintColor: UIColor.interpolate(from: .secondaryColor, to: .darkGray, with: percentage))
meetButton.setImage(newMeetButtonImage, for: .normal)
}
I am wondering how I could go about this to minimize frame rate dropping. I imagine that the adjustment of constraint constants, as well as setting of button images with a different shade and a different imageInset each time the function is called is likely causing the issue, but I am unsure. I have no clue how else I could recreate this UI without dropping the frame rate.
Here is what Tinder's UI looks like for reference:
I would use profiling (Instruments) to get more details about what is causing the frame drop.
I trying to create a stretchy table view header and I saw this code on a post online:
override func viewDidLoad() {
tableView.contentInset = UIEdgeInsets(top: kTableHeaderHeight, left: 0, bottom: 0, right: 0)
tableView.contentOffset = CGPoint(x: 0, , y: -kTableHeaderHeight)
updateHeaderView()
}
I am having a little trouble understanding this code.
So essentially what it is doing is (Assuming the screen is 0 to 500 in height and kTableHeaderHeight = 200):
1) It is first adding padding to the top of the tableView by moving it up by kTableHeaderHeight in the contentInset property (this move is with respect to the frame of the tableView). So now does the tableView exists from -200 to 500?
2) Then it moves its bounds up by -kTableHeaderHeight. So does the contentOffset just make it scrollable in the -200 to 500 region? So is that why we are using contentOffset by -kTableHeaderHeight in this case?
1) No, if inset is positive then it makes table view area smaller, like 200,500
2) contentOffset is state of tableview. so when you set offset to -200 it moves content zero point to 200 from table view zero point, regardless content inset. basically it put current table view content to place where it should be regarding inset
So what that code does is reserves 200point place for custom header, that never overlaps with table view cells content (as table view API headers or footers do)
I have a UITableView with several sections. I am trying to add a view to the table header view, and I want this view to be hidden by default. I accomplish this with this line of code:
tableView.contentInset = UIEdgeInsets(top: -headerView.frame.size.height, left: 0, bottom: 0, right: 0)
I also want this to be hidden when the user scrolls to the top, unless the user intentionally scroll a bit higher to see it (kind of like the behavior of a search bar). I do that with this function:
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
let offset = controller.tableView.contentOffset
let barHeight = controller.headerView.frame.size.height
if (offset.y < barHeight / 2.0 ) {
controller.tableView.contentInset = UIEdgeInsetsZero
}
else {
controller.tableView.contentInset = UIEdgeInsetsMake(-barHeight, 0, 0, 0)
}
controller.tableView.contentOffset = offset
}
The problem here is that when I scroll down and my inset is -barHeight, the section headers of my table view also use that content inset. Meaning that they disappear behind the navigation bar instead of sticking underneath it like normal.
My question is, how can achieve this "hidden" table header view while also maintaining the sticky section headers in the simplest way possible?
Thanks in advance!