How to lock the scroll view in place? - ios

I want to lock the scrollView when my segmented Control comes to top of the screen. How can I do this in swift? What's the code of this? How to compute the distance between the top of the segmented control and top of the view controller? It means how can I find the true place for locking scrollView?

After Swift 4.0 it has changed to
scrollView.isScrollEnabled = false
and
scrollView?.isScrollEnabled = true

Just flip the scrollEnabled boolean:
yourScrollView.scrollEnabled = false
To make it scroll again:
yourScrollView.scrollEnabled = true

Related

UISplitViewController - Expand & Collapse Master View in iPad Portrait

My universal app displays both master and detail views in iPad with preferredDisplayMode = .allVisible. I need to expand the master view into full screen and hide the detail view on a button click. I know there is functionality to expand detail into full screen hiding master. But couldn't find how to expand and collapse master view.
I tried in expand function as below.
self.splitViewController.preferredPrimaryColumnWidthFraction = 1.0
self.splitViewController.maximumPrimaryColumnWidth = self.splitViewController.view.bounds.size.width as! CGFloat
And collapse function as below.
self.splitViewController.preferredDisplayMode = .allVisible
self.splitViewController.preferredPrimaryColumnWidthFraction = 0.6
self.splitViewController.maximumPrimaryColumnWidth = self.splitViewController.view.bounds.size.width as! CGFloat
But they don't work. Any ideas on how to achieve this?
My setup uses a navigation bar, but the show/hide functionality would probably work without it. What I wanted to achieve is to have the user decide whether to show the "primary" view and have it shown no matter the orientation - something a UISplitViewController doesn't natively do.
I achieved this through activating/deactivating two arrays of constraints, pinning the secondary" view's leading anchor to the "primary's" trailing anchor. From there, all the constraint changes are with the "primary" view.
(I'm using quotation marks because these view's actually have much more logic that a UIView should have, so they are each UIViewControllers with one being a child of the other, but the constraints are view-related.)
Let's start with the static constraints:
primary.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
primary.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
primary.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
secondary.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
secondary.leadingAnchor.constraint(equalTo: toolBar.trailingAnchor).isActive = true
secondaary.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
secondary.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
Next, define/populate the two arrays that will show/hide the primary:
var isShowingPrimary = false
var showPrimary = [NSLayoutConstraint]()
var hidePrimary = [NSLayoutConstraint]()
showPrimary.append(primary.widthAnchor.constraint(equalToConstant: 300))
hidePrimary.append(primary.widthAnchor.constraint(equalToConstant: 0))
NSLayoutConstraint.activate(hidePrimary)
Notice that isActive is true for the static constraints, and I activated the hidePrimary constraints only.
Now all you need to do is wire up a UIBarButtonItem or UIButton to execute a toggle function that will show/hide the primary view, along with animating it:
func togglePrimary() {
if isShowingPrimary {
// hide primary view
NSLayoutConstraint.deactivate(showPrimary)
NSLayoutConstraint.activate(hidePrimary)
} else {
// show primary view
NSLayoutConstraint.deactivate(hidePrimary)
NSLayoutConstraint.activate(showPrimary)
}
// toggle flag and animate changes
isShowingPrimary.toggle()
UIView.animate(withDuration: 0.3) { self.view.layoutIfNeeded() }
}

Make View visible outside TableViewCell

Is it possible to have a view inside a tableViewCell and make it visible even outside the tableView-frame?
I would need this for an animation. I tried setting clipsToBounde = false but that didn't solve the issue. The view is still cut outside the tableViewFrame.
My view inside tableViewCell:
func setupLoadingAnimation(){
successAnimation.translatesAutoresizingMaskIntoConstraints = false
successAnimation.clipsToBounds = false
self.contentView.addSubview(successAnimation)
successAnimation.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: -60).isActive = true
successAnimation.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
successAnimation.widthAnchor.constraint(equalToConstant: 160).isActive = true
successAnimation.heightAnchor.constraint(equalToConstant: 160).isActive = true
successAnimation.isHidden = true
successAnimation.loopMode = .playOnce
}
You'll need to make sure all views in the hierarchy have their clipping set to false. Start with the superview of successAnimation and go up through the hierarchy, this will include the cell's contentView and the table view itself.
Another thing you'll have to look for is that views that are added to the hierarchy later will show on top of others if they are at the same level, and since a table view manages its cells it's hard to know which cells are going to overlap your animation.
To fix this you could call bringSubviewToFront() on your table view and pass the cell, I would do this right before executing the success animation.
Another alternative would be to place the table and success views in a shared parent, that way you only have to make sure that the success view is above the table view once, when you add the views.

How do I limit the size of a UIView in a storyboard designer and the runtime view overall?

I have a custom UIView that's my little component lets call it PlaceholderView.
My UITableViewCell prototype has a Label and a PlaceholderView that sits inside a UIStackView that's vertically axis.
The PlaceholderView, is supposed to call some custom code that goes to a cache to retrieve a specific view then it adds it to the SubView of the PlaceholderView.
I want this subview to take up the whole surface of the entire PlaceholderView. How do I go about doing that? I tried this but not sure if it does the job
if (view != null)
{
AddSubview(view);
view.SizeToFit();
}
Second question. These view's that I am adding, when I create them during design time, I make a new storyboard, drag and drop a ViewController then proceed to place other controls like Labels and Button's on it.
How do I restrict this ViewController's overall height so it's completely fixed size? I know I can set the simulated metrics, and I am also setting the View. Frame's size to restrict the height.
Are there better ways to make these views constrained easier?
Currently, when I am setting these fixed height values, it does cause some weird issues with overlaps if I set UITableView.RowHeigh to AutomaticDimension.
// attaches all sides of the child to its parent view
extension UIView {
func layoutToSuperview() {
guard let view = self.superview else {return}
self.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
self.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
self.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
self.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
}
}
Usage:
Instead of view.SizeToFit() use view.layoutToSuperview()
I want this subview to take up the whole surface of the entire
PlaceholderView
You can try autolayout:
if (view != null)
{
view.TranslatesAutoresizingMaskIntoConstraints = false;
AddSubview(view);
view.LeadingAnchor.ConstraintEqualTo(this.LeadingAnchor).Active = true;
view.TopAnchor.ConstraintEqualTo(this.TopAnchor).Active = true;
view.TrailingAnchor.ConstraintEqualTo(this.TrailingAnchor).Active = true;
view.BottomAnchor.ConstraintEqualTo(this.BottomAnchor).Active = true;
}
Are there better ways to make these views constrained easier?
The answer is also auto layout. Set a control's height constraint to claim how much space it wants to take. See this thread for more details: Using Auto Layout in UITableView for dynamic cell layouts & variable row heights.
Though it is native oc, you can see its concept.

View doesn't appear after changing the view property 'isHidden = false'

I'm developing an iOS application and then the issue that I have faced now is showing a view using the view property isHidden.
I initialized a custom view including a CAAnimation and then set the default isHidden property true to hide. After a certain condition meets I changed the isHidden property to false to show it. But in this case the view doesn't appear.
private func setupButtonEffectView() {
self.buttonEffectView = ButtonEffectView()
self.buttonEffectView!.translatesAutoresizingMaskIntoConstraints = false
// self.view.addSubview(self.buttonEffectView!)
self.view.insertSubview(self.buttonEffectView!, belowSubview: self.button!)
NSLayoutConstraint.activate([
self.buttonEffectView!.centerXAnchor.constraint(equalTo: self.button!.centerXAnchor),
self.buttonEffectView!.centerYAnchor.constraint(equalTo: self.button!.centerYAnchor),
self.buttonEffectView!.widthAnchor.constraint(equalToConstant: 100),
self.buttonEffectView!.heightAnchor.constraint(equalToConstant: 100)
])
self.buttonEffectView!.isHidden = true
}
I created the button effect using the method above.
Try instead of hiding the view, setting the alpha to 0.0. self.buttonEffectView.alpha = 0.0. Then when you want to show it set the alpha to 1.0.

Manually bounce UIScrollView

With UIScrollView, it's possible to programmatically move to an offset, with setContentOffset:animated: for exemple.
I'm trying to add a bounce effect when the offset is set programmatically. I think I should use a UIAttachmentBehavior, but I don't really know how to use it.
When should it be declared ? When the user finish dragging, in the scrollViewDidEndDragging function ? Or when the offset is the same than the final offset ?
For exemple, I'm at offset 10 and I want to go to offset 50. Maybe I should go to offset 60 and set a UIAttachmentBehavior at offset 50 ? Or maybe there's an other way ?
Thanks for your help
From my understanding, you want to enable bouncing when you get to the edge of a scroll view.
If you want the default of the scrollview to be that it doesn't bounce, then use this code:
override func viewDidLoad() {
super.viewDidLoad()
self.scrollview.bounces = false
}
Then, if you want to enable bouncing at any point, just add the line:
self.scrollview.bounces = true
If you know that you always want to scrollview to bounce you can set the following properties:
self.scrollview.alwaysBounceVertical = true
self.scrollview.alwaysBounceHorizontal = true
See this link for more information.

Resources