i have a scrollview with some subviews. Inside this subviews i have other subviews.
i want to present a popover that is anchored to one of this "nested" subviews.
I correctly show the popover, and it is anchored to the corrected subview, but whenever i scroll the scrollview, the popover doesn't move with the scrollview.
I would like my popover to move and to adjust its "x" origin every time i scroll the scrollview horizontally.
This is the code i use to present the popover.
func showAlarmViewController(notification: NSNotification){
troubleViewController = TroubleshootViewController()
troubleViewController!.modalPresentationStyle = .Popover
troubleViewController!.preferredContentSize = CGSizeMake(300.0, 150.0)
popoverMenuViewController = troubleViewController!.popoverPresentationController
popoverMenuViewController!.permittedArrowDirections = .Down
popoverMenuViewController!.delegate = self
popoverMenuViewController!.passthroughViews = [self.detailScrollView]
popoverMenuViewController!.sourceView = (notification.object as! UIView).superview
popoverMenuViewController!.sourceRect = CGRect(x: -100, y: 100, width: 300, height: 150)
presentViewController(
troubleViewController!,
animated: true,
completion: nil)
}
any help please?
thanks!
You have to add your popoverMenuViewController in one of the nested subviews of scrollview or in scrollview by
scrollview.addsubview(popoverMenuViewController)
If popoverMenuViewController controller is UIViewController, then add container view in scrollview and link that container view to popoverMenuViewController. later you can add container view as a subview of scrollview.
here, is the link how container view can be implemented. How to use a 'Container View' in iOS?
And
http://spin.atomicobject.com/2015/07/21/ios-container-views/
or add popoverMenuViewController in one of the nested subview of scrollview
subviewofscrollview.addsubview(popoverMenuViewController)
Set your popoverMenuViewController anchor according to the subview content size, where you added this popoverMenuViewController.
Related
I have been trying this for quite sometime now and went through a lot of posts on SO and some video tutorials. What I want to create is a horizontal scroll view with some buttons in it, like this:
My view hierarchy is as follows:
View Controller
View
Scroll View
View
Buttons
I have set top, leading, trailing, bottom constraints to the scroll view. I have set it's width equal to it's superview, and have set it's height to 200. So far so good, for the view inside the scroll view, I have set it's constraints leading, trailing, top and bottom to zero with respect to it's superview i.e. scroll view. I have made it's width equals to the View controllers view, since that was the solution here on SO to the ambiguous width issue. It solved the issue. Now I added all the buttons and set up their constraints to their parent view. Now when I run the app, a screen like the above added screenshot appears, however I cant scroll to the last element.Any help is greatly appretiated.
It's so simple.
Take a scrollView(Draw top left bottom right and hight constraint)
Take a UIView which will act like as a container View.(Draw top left bottom right constraint with scrollView).
Make your View Controller 1000px so that you can make your scrollView bigger and easy to watch.later on you can minimize it.
Now keep your button inside of it. keep in mind that, Every button will have top leading width , height and trailing if necessary. Width & height is important for scrollView because how big it will be depends on it.
Pictures worth a thousand word.
here is my hierarchy
And here is the Storyboard layout design.White background is basically containerView.
And here is the output.I have given some color for better understanding.
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var btnBack: UIButton!
#IBOutlet weak var btnForward: UIButton!
let headerView = UIView()
headerView.backgroundColor = UIColor.white
for i in 0..<selectedRestaurant.multipleImages.count {
let url = selectedRestaurant.multipleImages[i]
let imgView = UIImageView()
imgView.frame = CGRect(x: CGFloat(i) * self.view.frame.size.width, y: 0, width: self.view.frame.size.width, height: scrollView.frame.size.height)
let task = URLSession.shared.dataTask(with: URL(string: url as! String)!, completionHandler: { (data, response, error) in
if error == nil {
if data != nil {
imgView.contentMode = UIViewContentMode.scaleAspectFill
imgView.image = UIImage(data: data!)
}
}
})
scrollView.addSubview(imgView)
scrollView.contentSize = CGSize(width: self.view.frame.size.width * CGFloat(selectedRestaurant.multipleImages.count), height: scrollView.frame.size.height)
write code in btn back clicked <<<<
let index = Int(scrollView.contentOffset.x/self.view.frame.size.width) - 1
print("\(index)")
if index >= 0 {
scrollView.setContentOffset(CGPoint(x: CGFloat(index) * self.view.frame.size.width, y: 0), animated: true)
}
write code in btn next clicked >>>>>
let index = Int(scrollView.contentOffset.x/self.view.frame.size.width) + 1
print("\(index)")
if index < (selectedRestaurant.multipleImages.count) {
scrollView.setContentOffset(CGPoint(x: CGFloat(index) * self.view.frame.size.width, y: 0), animated: true)
}
For swift 5.1
firstly put scrollView give constraint to superView. Make them all what you desire.
Then put view on scroll view like I showed in pic. Give constraint shown below then to avoid error follow 3. step.
https://i.stack.imgur.com/MwzVN.png
Push control button and drag to the view then select Equal Height.
https://i.stack.imgur.com/91yzl.png
I give name to view over scrollview which name is ContentView . Be sure view size form is freeform and make width 1200 same as ContentView.
https://i.stack.imgur.com/jqo0v.png
https://i.stack.imgur.com/ntW4p.png
5)Then put TableView over the ContentView and give all the constraint zero.
https://i.stack.imgur.com/JPbXH.png
This is my TableviewCell
https://i.stack.imgur.com/4Fxwk.png
And this one is the result.
https://i.stack.imgur.com/zxBAT.gif
I have a UIViewController that acts as a Container View Controller. It has a UIScrollView that has the same width as the screen, but it's height is smaller than the height of the screen.
The UIScrollView contains the views of two other UIViewControllers and those views can be horizontally scrolled through.
I set my contentSize like this:
scrollView.contentSize.width = self.view.bounds.width * 2
This works and allows me to scroll through my UIViewController views horizontally.
The following is how I add the UIViewController views to my scrollView:
private func addPanel(viewController: UIViewController, panel: Panel) {
let xOffset: CGFloat!
switch panel {
case .left:
xOffset = 0.0
case .right:
xOffset = self.view.bounds.width
}
let panelView = UIView(frame: CGRect(x: xOffset, y: 0, width: self.view.bounds.width, height: self.scrollView.bounds.height))
scrollView.addSubview(panelView)
let panelViewController: UIViewController! = viewController
var viewBounds = view.bounds
viewBounds.height = panelView.bounds.height
panelViewController.view.frame = view.bounds
panelView.addSubview(panelViewController.view)
addChildViewController(panelViewController)
panelViewController.didMove(toParentViewController: self)
}
For some reason, the UIViewController views don't resize to fit the height of the UIScrollView.
Should I be doing it constraint based? How would I do this. I've been struggling with this for a few days and am at a loss.
Essentially, the UIViewController views will just like like full screen views offset and so you can't see the bottom of the views because the bottom of the screen cuts them off.
I'm just taking a guess without knowing all the code, but one reason could be if you're adding the child view controllers before the scrollview has been layouted.
After you add and set the child views sizes, the scrollview adjusts its size to the phone size but you never update the child views.
My suggestion here would be to add the child view controllers to the scrollview, but move the frame setting code into a layouting method where you know your views have the correct(visible) frames/bounds.
Given you are writing this in a view controller, one method could be -viewDidLayoutSubviews
Hope this makes sense, feel free to ask more questions if it doesn't.
I have just implemented a UISearchController in a regular UIViewController, and I have a kind of weird issue.
I have a UIView that is adapted exactly to the size I want my UISearchBar to take. On first launch of the view, I add my UISearchBar as a SubView to this UIView.
But when I launch it, the UISearchBar doesn't take the size of its parent UIView -- it just takes the width of the whole screen.
As you can see, it overlaps with the button on the right.
But once I click on the search bar and cancel it, it resizes to the exact size I want.
What could be the issue here? I've tried adding AutoLayout Constraints from the SearchBar to its parent view but it doesn't seem to change anything. Doesn't [UIView addSubview:] handle this?
UISearchController's view behaviour is weird indeed, but there is a simple workaround.
Use an additional container view
put UISearchController's view inside
set UISearchController's view autoresizing mask to UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight
set UISearchController's frame to container's view bounds
At this point UISearchController.view won't resize beyond container.bounds.
For me this didn't work, but I found a solution that I would like to share:
Instead of putting the searchBar in a containerView, put a navigationBar in the containerView, and put the searchBar in this navigationBar. For me, the problem still exists at this point.
But then I put a 1-pixel wide view as a navigationItem to the right of the navigationBar. From then it works all fine, the textfield of the searchBar didn't stretch anymore after the first selection.
It is more of a hack instead of a good solution to an annoying bug(?), but for me this hack is acceptable as I already needed some margins on both side of the searchBar. Here is some code:
//on init or viewDidLoad
navigationBar = UINavigationBar(frame: .zero)
let navigationItem = UINavigationItem()
navigationItem.titleView = searchController.searchBar
let leftView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: Design.margin, height: 1))
leftView.backgroundColor = .clear
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: leftView)
let rightView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: Design.margin, height: 1))
rightView.backgroundColor = .clear
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: rightView)
navigationBar.items = [navigationItem]
containerView.addSubview(navigationBar)
// setup frame sizes in your layout
Is it possible to set the viewController for an UIView programmatically? What I want to do is make a UIView that always covers 50% of the screen's height and add a ViewController on that view after initializing it. I can't seem to find a method. Pseudocode:
let view = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height UIScreen.main.bounds.height * 0.5)
//Can't seem to find a method that does exactly this:
view.setViewController(.......)
Insert yourAnotherVC.view as a subview to yourview
var MenuView: AnotherViewController? = (self.storyboard?.instantiateViewController(withIdentifier: "NewsView") as? AnotherViewController)
self.addChildViewController(MenuView)
MenuView?.didMove(toParentViewController: self)
MenuView?.view?.frame = CGRect(x: CGFloat(0.0), y: CGFloat(self.containerView.frame.size.height), width: CGFloat(self.containerView.frame.size.width), height: CGFloat(self.containerView.frame.size.height))
yourview.insertSubview(MenuView?.view, belowSubview: self.bottomMenuView)
//Show presentation logic here forward i mean show Anotherviewvc bottom to top or top to bottom
I'll hide and show views instead of switching out the whole UIViews so no more answers needed #close
// Add Child View Controller from your MainVC
addChildViewController(viewController) //your 2nd VC
// Add Child View as Subview
view.addSubview(viewController.view)
// Configure Child View
viewController.view.frame = view.bounds //here you make it 50% of height!
viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
// Notify Child View Controller
viewController.didMove(toParentViewController: self)
You can add a Container View, that uses its own UIViewController. Simply drag it from the object library and you are good to go.
I made more than one view without taking new Controller class , I used UIgestureRecognizer but it not look better.
I want to swipe same like ios device, when we start to swipe from left side corner.
You can implement this with scrollview.
Steps:
1)First place a scrollview that fills the full screen.
2)Next create a container view which is as big as to hold your two views.
let containerSize = CGSize(width: 640.0, height: 640.0)
containerView = UIView(frame: CGRect(origin: CGPoint(x: 0, y: 0),size:containerSize))
scrollView.addSubview(containerView)
3) Now you create your view 1 , view2 and add them to container view.
4) Set the scrollview content size to container size
scrollView.contentSize = containerSize;
5) Then set the scrollview delegate method
func viewForZoomingInScrollView(scrollView: UIScrollView!) -> UIView!{
return containerView
}