Post

Replies

Boosts

Views

Activity

Custom animated transition not working when using rootview
I am trying to create a custom transition, similar to the one that is on the App Store. I used these tutorials: https://eric-dockery283.medium.com/custom-view-transitions-like-the-new-app-store-a2a1181229b6 https://www.raywenderlich.com/2925473-ios-animation-tutorial-custom-view-controller-presentation-transitions I have also been experimenting with using the load view to have the root view to create the view. now what I am doing is that I am using a collectionview, which I want to keep, and when an item is pressed it animate transitions to a new view controller with a larger image, simple. the problem is that when I combine it with using the loadView with view = rootView() it did not work in some scenarios. For example: when I use the modalPresentationStyle = .fullScreen, when I press an item in the collection view the screen just goes black, and then when I press the view hierarchy it shows this: when I remove the modalPresentationStyle = .fullScreen it does animate but it is the popover transition, which I do not want. What I want is to have a full screen transition that is animated. here is the view controller: import UIKit class OtherViewController: UIViewController, UIViewControllerTransitioningDelegate {   var data: DogArr?   var rootView = testView1()   override func viewDidLoad() {     super.viewDidLoad()     self.view.backgroundColor = .systemBackground   }   override func loadView() {     view = rootView     rootView.animalImg.image = UIImage(named: data?.image ?? "")     rootView.dismissBtn.addTarget(self, action: #selector(dismissingBtn), for: .touchUpInside)   }   @objc func dismissingBtn() {     self.dismiss(animated: true)   } } class testView1: UIView {   var animalImg: UIImageView = {     let img = UIImageView()     img.contentMode = .scaleAspectFit     img.translatesAutoresizingMaskIntoConstraints = false     return img   }()   var dismissBtn: UIButton = {     let btn = UIButton()     btn.translatesAutoresizingMaskIntoConstraints = false     btn.setTitle("Done", for: .normal)     btn.titleLabel?.font = UIFont.systemFont(ofSize: 25)     btn.titleLabel?.textAlignment = .center     btn.setTitleColor(.label, for: .normal)     btn.contentMode = .scaleAspectFill     return btn   }()   init() {     super.init(frame: .zero)     self.addSubview(animalImg)     self.addSubview(dismissBtn)     animalImg.translatesAutoresizingMaskIntoConstraints = false     self.backgroundColor = .systemBackground     NSLayoutConstraint.activate([       animalImg.topAnchor.constraint(equalTo: self.topAnchor),       animalImg.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 0.5),       animalImg.widthAnchor.constraint(equalTo: animalImg.heightAnchor),       dismissBtn.topAnchor.constraint(equalTo: self.animalImg.bottomAnchor, constant: 20),       dismissBtn.centerXAnchor.constraint(equalTo: self.dismissBtn.centerXAnchor),       dismissBtn.widthAnchor.constraint(equalToConstant: 150),       dismissBtn.heightAnchor.constraint(equalToConstant: 75)     ])   }   required init?(coder: NSCoder) {     fatalError("init(coder:) has not been implemented")   } } I noticed that when I remove the root view and just created everything in the view controller, it seems to work, the thing is that this is just a test for now. The root view in a future project may be very large so I think keeping to a rootview may be a good idea. If there are any other methods similar, please share. If there is anything I can answer please ask, Thank you
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
622
Jun ’22
how to know when a scrollview in SwiftUI is being scrolled?
I am trying to add arrows to a scrollView in SwiftUI. When the app is open or all the way to the left side there is an arrow pointing to the right: and the opposite when it reaches the right side: What I am struggling with is how to have both arrows to appear when the person is scrolling. I am able to get the arrows to appear when I am between point A and B, but when I reach either end the double arrows remains, instead of the single arrow I want when it reaches either end of the scrollView. So what I want is and arrow showing which direction the scroll can do, so when it can't scroll to anyone side anymore, like when it reaches the far left or right, there is only one arrow, but when the scrolling can be either direction there are two arrows, that disappear when it reaches either end. I am able to get the arrows working when they reach either side, but I was hoping for the double arrows when it is needed. I think there must be something to determine when scrolling is being done. I have looked at a few sources to get to where I am now, and things I have tried before, to no avail: Video: https://www.youtube.com/watch?v=h47UkS8pLA8 https://developer.apple.com/forums/thread/650312 Interaction of DragGesture and ScrollView in SwiftUI In SwiftUI, where are the control events, i.e. scrollViewDidScroll to detect the bottom of list data This is the main View: This is the view for the arrows: If there is anything else I can answer please ask, thank you.
2
0
4.6k
Oct ’22
Why are the constraints not working when orientation changes and navigation to new view
I am making a collection view that when one of the cells is pressed it navigates to a second view, however I am experiencing a bug. When in Landscape orientation when I navigate to the second view the constraints change for the first view. This is what it looks like as vertical and landscape when the app is first open, Now when ever any of these cells are pressed while in LANDSCAPE orientation it takes me to a new view (which is fine), but before the transition finishes, I can see the constraints of the collection view change (which is not) so I go back to the first view and it looks different, it now looks like this: I am not sure what I am doing wrong. I tried to not use safeAreaLayoutGuide but it makes no difference to this problem. Here is the code for the ViewController: var profiles: [Profile] = [] private let collectionView: UICollectionView = { let viewLayout = UICollectionViewFlowLayout() let collectionView = UICollectionView(frame: .zero, collectionViewLayout: viewLayout) collectionView.backgroundColor = .white return collectionView }() private enum LayoutConstant { static let spacing: CGFloat = 16.0 static let itemHeight: CGFloat = 300.0 } override func viewDidLoad() { super.viewDidLoad() setupViews() setupLayouts() populateProfiles() collectionView.reloadData() } private func setupViews() { view.backgroundColor = .white view.addSubview(collectionView) collectionView.dataSource = self collectionView.delegate = self collectionView.register(ProfileCell.self, forCellWithReuseIdentifier: ProfileCell.identifier) } private func setupLayouts() { collectionView.translatesAutoresizingMaskIntoConstraints = false // Layout constraints for `collectionView` NSLayoutConstraint.activate([ collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), collectionView.leftAnchor.constraint(equalTo: view.leftAnchor), collectionView.rightAnchor.constraint(equalTo: view.rightAnchor) ]) } private func populateProfiles() { profiles = [ Profile(name: "Thor", location: "Boston", imageName: "", profession: "astronomy"), Profile(name: "Mike", location: "Albequerque", imageName: "", profession: "basketball"), Profile(name: "Walter White", location: "New Mexico", imageName: "", profession: "chemistry"), Profile(name: "Sam Brothers", location: "California", imageName: "", profession: "geography"), Profile(name: "Chopin", location: "Norway", imageName: "", profession: "geometry"), Profile(name: "Castles", location: "UK", imageName: "", profession: "history"), Profile(name: "Dr. Johnson", location: "Australia", imageName: "", profession: "microscope"), Profile(name: "Tom Hanks", location: "Bel Air", imageName: "", profession: "theater"), Profile(name: "Roger Federer", location: "Switzerland", imageName: "", profession: "trophy"), Profile(name: "Elon Musk", location: "San Francisco", imageName: "", profession: "graduate") ] } init() { super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } extension ProfileViewController: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return profiles.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ProfileCell.identifier, for: indexPath) as! ProfileCell let profile = profiles[indexPath.row] cell.setup(with: profile) cell.contentView.backgroundColor = .red return cell } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let vc = LightViewController() vc.modalPresentationStyle = .fullScreen self.present(vc, animated: true) var pressedData = Data(id: 1, name: "Test", description: "Test") vc.viewModel.lightPublisher.send(pressedData) } } extension ProfileViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let width = itemWidth(for: view.frame.width, spacing: LayoutConstant.spacing) return CGSize(width: width, height: LayoutConstant.itemHeight) } func itemWidth(for width: CGFloat, spacing: CGFloat) -> CGFloat { let itemsInRow: CGFloat = 2 let totalSpacing: CGFloat = 2 * spacing + (itemsInRow - 1) * spacing let finalWidth = (width - totalSpacing) / itemsInRow return floor(finalWidth) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { return UIEdgeInsets(top: LayoutConstant.spacing, left: LayoutConstant.spacing, bottom: LayoutConstant.spacing, right: LayoutConstant.spacing) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return LayoutConstant.spacing } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return LayoutConstant.spacing } } I can include the cell code but there is not enough space, however if there is anything else I can answer please ask, Thank you
0
0
828
Dec ’22
Lock Screen shows skip buttons instead of next/previous when using MPRemoteCommandCenter with AVPlayer playlist
Hello, I’m building an iOS video player using AVPlayer and a custom playback queue. I implemented remote controls using MPRemoteCommandCenter and enabled: nextTrackCommand previousTrackCommand playCommand pauseCommand I disabled: skipForwardCommand skipBackwardCommand seekForwardCommand seekBackwardCommand I also set queue metadata in MPNowPlayingInfoCenter: MPNowPlayingInfoPropertyPlaybackQueueIndex MPNowPlayingInfoPropertyPlaybackQueueCount Even with these commands enabled and the queue count greater than 1, the iOS lock screen continues to display the 10-second skip buttons instead of the previous/next track buttons. The commands themselves work correctly when triggered externally (Control Center, headphones, etc.), but the UI still shows the skip controls. Is there a way to force the lock screen UI to display previous / next track buttons for a video playlist? Or is this behavior expected when using AVPlayer with video content? Thanks.
0
0
82
Mar ’26
Custom animated transition not working when using rootview
I am trying to create a custom transition, similar to the one that is on the App Store. I used these tutorials: https://eric-dockery283.medium.com/custom-view-transitions-like-the-new-app-store-a2a1181229b6 https://www.raywenderlich.com/2925473-ios-animation-tutorial-custom-view-controller-presentation-transitions I have also been experimenting with using the load view to have the root view to create the view. now what I am doing is that I am using a collectionview, which I want to keep, and when an item is pressed it animate transitions to a new view controller with a larger image, simple. the problem is that when I combine it with using the loadView with view = rootView() it did not work in some scenarios. For example: when I use the modalPresentationStyle = .fullScreen, when I press an item in the collection view the screen just goes black, and then when I press the view hierarchy it shows this: when I remove the modalPresentationStyle = .fullScreen it does animate but it is the popover transition, which I do not want. What I want is to have a full screen transition that is animated. here is the view controller: import UIKit class OtherViewController: UIViewController, UIViewControllerTransitioningDelegate {   var data: DogArr?   var rootView = testView1()   override func viewDidLoad() {     super.viewDidLoad()     self.view.backgroundColor = .systemBackground   }   override func loadView() {     view = rootView     rootView.animalImg.image = UIImage(named: data?.image ?? "")     rootView.dismissBtn.addTarget(self, action: #selector(dismissingBtn), for: .touchUpInside)   }   @objc func dismissingBtn() {     self.dismiss(animated: true)   } } class testView1: UIView {   var animalImg: UIImageView = {     let img = UIImageView()     img.contentMode = .scaleAspectFit     img.translatesAutoresizingMaskIntoConstraints = false     return img   }()   var dismissBtn: UIButton = {     let btn = UIButton()     btn.translatesAutoresizingMaskIntoConstraints = false     btn.setTitle("Done", for: .normal)     btn.titleLabel?.font = UIFont.systemFont(ofSize: 25)     btn.titleLabel?.textAlignment = .center     btn.setTitleColor(.label, for: .normal)     btn.contentMode = .scaleAspectFill     return btn   }()   init() {     super.init(frame: .zero)     self.addSubview(animalImg)     self.addSubview(dismissBtn)     animalImg.translatesAutoresizingMaskIntoConstraints = false     self.backgroundColor = .systemBackground     NSLayoutConstraint.activate([       animalImg.topAnchor.constraint(equalTo: self.topAnchor),       animalImg.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 0.5),       animalImg.widthAnchor.constraint(equalTo: animalImg.heightAnchor),       dismissBtn.topAnchor.constraint(equalTo: self.animalImg.bottomAnchor, constant: 20),       dismissBtn.centerXAnchor.constraint(equalTo: self.dismissBtn.centerXAnchor),       dismissBtn.widthAnchor.constraint(equalToConstant: 150),       dismissBtn.heightAnchor.constraint(equalToConstant: 75)     ])   }   required init?(coder: NSCoder) {     fatalError("init(coder:) has not been implemented")   } } I noticed that when I remove the root view and just created everything in the view controller, it seems to work, the thing is that this is just a test for now. The root view in a future project may be very large so I think keeping to a rootview may be a good idea. If there are any other methods similar, please share. If there is anything I can answer please ask, Thank you
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
0
Boosts
0
Views
622
Activity
Jun ’22
how to know when a scrollview in SwiftUI is being scrolled?
I am trying to add arrows to a scrollView in SwiftUI. When the app is open or all the way to the left side there is an arrow pointing to the right: and the opposite when it reaches the right side: What I am struggling with is how to have both arrows to appear when the person is scrolling. I am able to get the arrows to appear when I am between point A and B, but when I reach either end the double arrows remains, instead of the single arrow I want when it reaches either end of the scrollView. So what I want is and arrow showing which direction the scroll can do, so when it can't scroll to anyone side anymore, like when it reaches the far left or right, there is only one arrow, but when the scrolling can be either direction there are two arrows, that disappear when it reaches either end. I am able to get the arrows working when they reach either side, but I was hoping for the double arrows when it is needed. I think there must be something to determine when scrolling is being done. I have looked at a few sources to get to where I am now, and things I have tried before, to no avail: Video: https://www.youtube.com/watch?v=h47UkS8pLA8 https://developer.apple.com/forums/thread/650312 Interaction of DragGesture and ScrollView in SwiftUI In SwiftUI, where are the control events, i.e. scrollViewDidScroll to detect the bottom of list data This is the main View: This is the view for the arrows: If there is anything else I can answer please ask, thank you.
Replies
2
Boosts
0
Views
4.6k
Activity
Oct ’22
Why are the constraints not working when orientation changes and navigation to new view
I am making a collection view that when one of the cells is pressed it navigates to a second view, however I am experiencing a bug. When in Landscape orientation when I navigate to the second view the constraints change for the first view. This is what it looks like as vertical and landscape when the app is first open, Now when ever any of these cells are pressed while in LANDSCAPE orientation it takes me to a new view (which is fine), but before the transition finishes, I can see the constraints of the collection view change (which is not) so I go back to the first view and it looks different, it now looks like this: I am not sure what I am doing wrong. I tried to not use safeAreaLayoutGuide but it makes no difference to this problem. Here is the code for the ViewController: var profiles: [Profile] = [] private let collectionView: UICollectionView = { let viewLayout = UICollectionViewFlowLayout() let collectionView = UICollectionView(frame: .zero, collectionViewLayout: viewLayout) collectionView.backgroundColor = .white return collectionView }() private enum LayoutConstant { static let spacing: CGFloat = 16.0 static let itemHeight: CGFloat = 300.0 } override func viewDidLoad() { super.viewDidLoad() setupViews() setupLayouts() populateProfiles() collectionView.reloadData() } private func setupViews() { view.backgroundColor = .white view.addSubview(collectionView) collectionView.dataSource = self collectionView.delegate = self collectionView.register(ProfileCell.self, forCellWithReuseIdentifier: ProfileCell.identifier) } private func setupLayouts() { collectionView.translatesAutoresizingMaskIntoConstraints = false // Layout constraints for `collectionView` NSLayoutConstraint.activate([ collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), collectionView.leftAnchor.constraint(equalTo: view.leftAnchor), collectionView.rightAnchor.constraint(equalTo: view.rightAnchor) ]) } private func populateProfiles() { profiles = [ Profile(name: "Thor", location: "Boston", imageName: "", profession: "astronomy"), Profile(name: "Mike", location: "Albequerque", imageName: "", profession: "basketball"), Profile(name: "Walter White", location: "New Mexico", imageName: "", profession: "chemistry"), Profile(name: "Sam Brothers", location: "California", imageName: "", profession: "geography"), Profile(name: "Chopin", location: "Norway", imageName: "", profession: "geometry"), Profile(name: "Castles", location: "UK", imageName: "", profession: "history"), Profile(name: "Dr. Johnson", location: "Australia", imageName: "", profession: "microscope"), Profile(name: "Tom Hanks", location: "Bel Air", imageName: "", profession: "theater"), Profile(name: "Roger Federer", location: "Switzerland", imageName: "", profession: "trophy"), Profile(name: "Elon Musk", location: "San Francisco", imageName: "", profession: "graduate") ] } init() { super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } extension ProfileViewController: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return profiles.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ProfileCell.identifier, for: indexPath) as! ProfileCell let profile = profiles[indexPath.row] cell.setup(with: profile) cell.contentView.backgroundColor = .red return cell } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let vc = LightViewController() vc.modalPresentationStyle = .fullScreen self.present(vc, animated: true) var pressedData = Data(id: 1, name: "Test", description: "Test") vc.viewModel.lightPublisher.send(pressedData) } } extension ProfileViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let width = itemWidth(for: view.frame.width, spacing: LayoutConstant.spacing) return CGSize(width: width, height: LayoutConstant.itemHeight) } func itemWidth(for width: CGFloat, spacing: CGFloat) -> CGFloat { let itemsInRow: CGFloat = 2 let totalSpacing: CGFloat = 2 * spacing + (itemsInRow - 1) * spacing let finalWidth = (width - totalSpacing) / itemsInRow return floor(finalWidth) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { return UIEdgeInsets(top: LayoutConstant.spacing, left: LayoutConstant.spacing, bottom: LayoutConstant.spacing, right: LayoutConstant.spacing) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return LayoutConstant.spacing } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return LayoutConstant.spacing } } I can include the cell code but there is not enough space, however if there is anything else I can answer please ask, Thank you
Replies
0
Boosts
0
Views
828
Activity
Dec ’22
Lock Screen shows skip buttons instead of next/previous when using MPRemoteCommandCenter with AVPlayer playlist
Hello, I’m building an iOS video player using AVPlayer and a custom playback queue. I implemented remote controls using MPRemoteCommandCenter and enabled: nextTrackCommand previousTrackCommand playCommand pauseCommand I disabled: skipForwardCommand skipBackwardCommand seekForwardCommand seekBackwardCommand I also set queue metadata in MPNowPlayingInfoCenter: MPNowPlayingInfoPropertyPlaybackQueueIndex MPNowPlayingInfoPropertyPlaybackQueueCount Even with these commands enabled and the queue count greater than 1, the iOS lock screen continues to display the 10-second skip buttons instead of the previous/next track buttons. The commands themselves work correctly when triggered externally (Control Center, headphones, etc.), but the UI still shows the skip controls. Is there a way to force the lock screen UI to display previous / next track buttons for a video playlist? Or is this behavior expected when using AVPlayer with video content? Thanks.
Replies
0
Boosts
0
Views
82
Activity
Mar ’26