Make View visible outside TableViewCell - ios

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.

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() }
}

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.

Dynamic auto-layout

I'm a new in the programming and I know that there are a lot of staff about auto-layout or manipulation with constraints in the internet/stackoverflow and I searched everywhere however was unable to find answer on my question, so please advise if you can.
For example here is
UI example
So I have a tableView which is top constaints to top of ViewController and textView which is top constraints to bottom of tableView. So the question is, how can I dynamically change constraints based on the size of array in TableView. If TableView is empty, so then assign textView to ViewController, if array of tableView > 0, then assign to bottom of TableView. I tried something like this
#IBOutlet weak var textViewTopConstraints: NSLayoutConstraint! {
didSet {
if array.isEmpty {
textViewTopConstraints.isActive = false
textView.topAnchor.constraint(equalTo: ViewController.top, constant: 8).isActive = true
} else if imageURL.count > 0 {
textViewTopConstraints.isActive = false
textView.topAnchor.constraint(equalTo: tableView.bottomAnchor, constant: 8).isActive = true
}
}
}
However it's only working when app is loaded and then didn't call if array is changed. So basically, I can't understand how to call function or something that will track and change my constraints based on the size of my array. If this is a duplicate, could you please guide me to the right link where I can check this information.
Change table view frame and connect constraints between textfield and table view. Link to set table view frame is :- Change UITableView height dynamically

pageviewcontroller inside navigation controller causing layout problems

I have a UIViewController (using Swift)
It is just a simple list of Items. It is implemented as a UIViewController to which I have added a UITableView. This 'Items' view is invoked via this code in my slide menu implementation, and the initial view of the slide menu is embeded in a NavigationController - so all the views in the slide menu take on the navigation controller. Items is one of those slide menu views invoked like this
self.openViewControllerBasedOnIdentifier("Items")
This works fine and I get....
I then have an add button in the top right that you can push to add new Items. The add button brings up a PageViewController. I use page view because there are multiple pages of details associated with the Item being added. This also works so far in that I get the pageviewcontroller launched and I can flip between pages.
The problem is that the placement of elements on the page shifts under some circumstances (it is not consistent).
When I initially show the 1st page of the PageViewController I see the layout that I designed (on the left below). If I simply tab out of the Text field OR if I swipe to the 2nd page and then swipe back to the 1st page then I see the right image. The whole view jumps up!
I tried flipping all the different settings in the storyboard regarding . I even moved the majority of the drawing in to the code and out of storyboard in order to manually set constraints. These are the settings I played with. tried lots of combinations but they are mostly all off now.
Here is Before and After. How do I stop the view from jumping up and down. Also, interesting is that if i swipe from page-3 to page-2 then page-2 is shifted up. If I keep going back to page-1 and then swipe back to page-2 then page-2 is back down to correct position. So deepening on which way I enter page-2 it is different layout. From 1 to 2, page 2 is correct. From 3 to 2, page 2 is shifted up.
I can not get the layout to stay in one spot.
The other option, is to just shut off NavigationController when in the page view controller and deal without having it.
So...
1) how can I stop the jumping - best case
2) how can I shut off navigation controller when pageviewcontroller is up - second option
The pages of my pageviewcontroller are invoked via this code
instantiateViewController(withIdentifier: "itemDetail\(num)ViewController")
Where 'num' is 1,2, or 3. Using an indexed array and viewControllerBefore along with viewControllerAfter methods. The paging itself works fine.
Thanks
This does not answer the question of how to make storyboard work. That remains a mystery. HOWEVER, I was able to fix the strange behavior of shifting layout by doing the following.
I removed ALL of the drawing from Storyboard and put everything in the code. For example, I have defined a container view ...
// The container
let containerView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.white
view.translatesAutoresizingMaskIntoConstraints = false
view.layer.masksToBounds = true
return view
}()
Then later I place the container relative to the UIViewController's view
view.addSubview(containerView)
containerView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
containerView.topAnchor.constraint(equalTo: view.topAnchor, constant: 155).isActive = true
containerView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: 0).isActive = true
containerView.heightAnchor.constraint(equalTo: view.heightAnchor, constant: -155).isActive = true
Similarly, I have defined all of the other controls in the code and then added them to the containerView subView and made then all relative to the containerView.
This keeps everything in place as I swipe between pages of the PageViewController
I had the same problem, and found the solution. You just need to disable automaticallyAdjustsScrollViewInsets in your viewDidLoad. Here's my code:
override func viewDidLoad()
{
super.viewDidLoad()
self.dataSource = self
self.automaticallyAdjustsScrollViewInsets = false
if let detailsVC = viewControllersList.first as? DetailsViewController
{
detailsVC.delegate = self
self.setViewControllers([detailsVC], direction: .forward, animated: true, completion: nil)
}
}
Credits to this answer.

Resources