Bottom border is not added to view in StackView (ios) - ios

I am trying to add UIView with the bottom border programatically to stack view.But border is not getting added to UIView().
Code to add UIView to stack view:
func addOtpViews()
{
var otpLength=Int(otpLen as String)!
print("otpLength is\(otpLength)")
var i=0;
while(i<=otpLength)
{
var view=UIView(frame: .zero)
addBottomBorderTo(view: view)
otpStackView.addArrangedSubview(view)
i=i+1
}
otpStackView.translatesAutoresizingMaskIntoConstraints=false
}
on the above otpStackView is a stack view which I have already added in StoryBoard.
code to add bottom line:
func addBottomBorderTo(view:UIView) {
print("bottom is added")
let layer = CALayer()
layer.backgroundColor = UIColor.gray.cgColor
layer.frame = CGRect(x: 0.0, y: view.frame.size.height - 2.0, width: view.frame.size.width, height: 2.0)
view.layer.addSublayer(layer)
}
Why bottom line is not added to UIView()?Please help me.Thanks in advance.

have you checked the view frame here
layer.frame = CGRect(x: 0.0, y: view.frame.size.height - 2.0, width: view.frame.size.width, height: 2.0)
view.frame could be (0,0),then you will not see the bottom line.
always be careful when you work with view frame.
My suggestions:
1.Adding sub view instead of adding sub layer,then use snapkit to layout.
2.Build a seperate view class called bottomedView,then add sub view there with snapkit.
3.Build a seperate view class called bottomedView,and draw your bottom line in onDraw.
Always be aware view frame may not be determined when view is missing unexpectedly.

Related

only last added view is visible in UIScrollView iOS

I am facing an issue with scrollView. I have added scrollView in my storyboard as
View
- MainView
- ScrollView
- accountSavingSubView
Now I am trying to add views in accountSavingSubView as below
//MARK:- Create and add wallets on the UI
private func createAndAddWallets()
{
var yPosition : CGFloat = 0.0
//1. Create left hand side wallets with help of keys
for key in dictData.keys
{
let walletView:Wallet = Bundle.main.loadNibNamed("Wallet", owner: self, options: nil)?.first as! Wallet
walletView.translatesAutoresizingMaskIntoConstraints = false
walletView.frame = CGRect(x: 0.0, y: yPosition, width: accountSavingSubView.frame.width, height: accountSavingSubView.frame.height)
walletView.accountNameLabel.text = key
accountSavingSubView.addSubview(walletView)
yPosition += walletView.frame.maxY
walletView.isUserInteractionEnabled = true
print("walletView frame is :\(walletView.frame)")
}
//set continer scroll content size
self.contanerScrollView.contentSize = CGSize(width: self.accountSavingSubView.frame.width, height: CGFloat(80.0/320.0)*UIScreen.main.bounds.width*CGFloat(self.dictData.keys.count))
}
Where dictData is a dictionary of ([String: String]).
But in my view, I can see only last view is added on (x=0, y=0). ScrollView content size is correct & I can scroll without having views except last one at first place(x:0,y:0).
Please let me know what am I doing wrong here in my code while adding views.
You need to comment this
walletView.translatesAutoresizingMaskIntoConstraints = false
as it's used with setting constraints only ,and verify that the supplied frame values here are not 0
walletView.frame = CGRect(x: 0.0, y: yPosition, width: accountSavingSubView.frame.width, height: accountSavingSubView.frame.height)
btw you can also comment it as the frame will be captured as you set it in xib if you make it freedom size

Limited Area Pinchview in Swift

I have a label on a imageview and both of them are in one view. The label is pinch-able via below code. However, it is pinch-able also out of image view. I want the areas outside of the imageview not seen (like in whatsapp or snapchat. The texts outside of the screen is not seen, i want that for only imageview area). I'm not sure but i guess somehow it will be done with bring view to front function. Just i don't know how to do it
func handlePinch(recognizer: UIPinchGestureRecognizer) {
if let view = recognizer.view as? UILabel {
let pinchScale: CGFloat = recognizer.scale
view.transform = view.transform.scaledBy(x: pinchScale, y: pinchScale)
recognizer.scale = 1.0
}
}
I done it with creating views out of imageview (left, right upper and bottom side) and set all views to the front except the view which has imageview. I created the first three view in (left, right and the bottomside) in the storyboard and last one (the upper one) in the code because i needed to hide status bar first then create a view on top of it.
customView = UIView(frame: CGRect(x: 0, y: 0, width: 440, height: 20))
customView.backgroundColor = UIColor.white
self.view.addSubview(customView)
self.view.bringSubview(toFront: view_main)
self.view.bringSubview(toFront: view2)
self.view.bringSubview(toFront: view3)
self.view.bringSubview(toFront: customView)

getting highly confused by odd behaviour of viewController Method

I have overrided a method as
override func viewDidLayoutSubviews() {
// creating bottom line for textField
let border = CALayer()
let width = CGFloat(1.0)
border.borderColor = UIColor.whiteColor().CGColor
border.frame = CGRect(x: 0, y: emailTextField.frame.size.height - width, width: emailTextField.frame.size.width, height: emailTextField.frame.size.height)
border.borderWidth = width
emailTextField.layer.addSublayer(border)
emailTextField.layer.masksToBounds = true
}
Now whats happening is that when I run my app on Iphone 6, 6+ every thing works fine. But when I run the same code on iphone5 (Simulator + real Device ) viewDidLayoutSubViews is getting called infinite times and my app becoms unresponsive. I solved the problem by using a bool variable. But I do not understand why is this happening. So can someone please explain this to me.
Thanks :-)
As docs says that viewDidLayoutSubviews method need for change layout
Called to notify the view controller that its view has just laid out
its subviews. When the bounds change for a view controller's view,
the view adjusts the positions of its subviews and then the system
calls this method. However, this method being called does not indicate
that the individual layouts of the view's subviews have been
adjusted. Each subview is responsible for adjusting its own layout.
Move your code to viewDidLoad method or to loadView if you are not using xibs or Storyboards
override func viewDidLoad() {
// creating bottom line for textField
let border = CALayer()
let width = CGFloat(1.0)
border.borderColor = UIColor.whiteColor().CGColor
border.frame = CGRect(x: 0, y: emailTextField.frame.size.height - width, width: emailTextField.frame.size.width, height: emailTextField.frame.size.height)
border.borderWidth = width
emailTextField.layer.addSublayer(border)
emailTextField.layer.masksToBounds = true
}
If you would like to change border.frame you can set it to class variable and change it in viewDidLayoutSubviews method
override func viewDidLayoutSubviews() {
self.border.frame = CGRect(x: 0, y: emailTextField.frame.size.height - width, width: emailTextField.frame.size.width, height: emailTextField.frame.size.height)
self.border.borderWidth = width
}
Just replace
emailTextField.layer.addSublayer(border)
with this:
emailTextField.addSublayer(border)
-> you want to add sublayer to a view - as you want to apply masksToBounds property to it either.
Move your implementation inside viewDidLayoutSubviews. I got the same issue. Hope it will work.
override func viewDidLayoutSubviews()
{
//Your CODE
}

Frame on ViewController

I have this class:
extension UIViewController {
func waiting() -> UIView{
let strLabel = UILabel(frame: CGRect(x: 50, y: 0, width: 200, height: 50))
strLabel.text = "Aguarde..."
strLabel.textColor = UIColor.whiteColor()
let messageFrame = UIView(frame: CGRect(x: view.frame.midX - 90, y: view.frame.midY - 25 , width: 180, height: 50))
messageFrame.layer.cornerRadius = 15
messageFrame.backgroundColor = UIColor(white: 0, alpha: 0.40)
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White)
activityIndicator.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
activityIndicator.startAnimating()
messageFrame.addSubview(activityIndicator)
messageFrame.addSubview(strLabel)
view.addSubview(messageFrame)
return messageFrame
}
}
When I need use this class I use:
class MyController: UIViewController{
....
func x(){
let messageFrame = waiting()
//my code
messageFrame.removeFromSuperview()
}
}
The problem is when the frame is showed if I touch anywhere on my app this frame is hidden. I need that when this frame is showed other options staying disabled, when I finish the frame, the options of app is enabled again. How can I do it?
Change the view that you are returning a bit:
Make a "container" view that has the same frame as the view controller's view. Give this view a "clear" background.
Make a "background" view, same size as the "container" view and add it to the container. Give this view a black background and an alpha of, say, 0.4.
Now put the view that you are currently building in your "waiting" method, and add it to the "container" view (NOT to the background view, this should be a sibling of the background view, otherwise your alert will also be transparent).
Make sure all user interaction is disabled on your views (might only need it disabled on the "container" view).
This gives you a container view that covers the entire screen, and it has 2 children: a transparent background of the same size, and your current "waiting" alert thing.
Now if you add the "container" view to your view controller's view, the user can only touch on the container view which does nothing.
(Keep in mind that this doesn't handle screen rotation...you will have to do that yourself if needed.)

How to embed stack view in scroll view programmatically

I have tried embedding it, but my stack view is dynamic and my app is also changing orientations time to time. I have segment control at the end of the view.
I have also tried googling it but had no luck. thanks in advance.
So far I have done:
In view did load:
mainStackView.axis = UILayoutConstraintAxis.Vertical
mainStackView.spacing = 3
scrollView.frame = self.view.bounds
scrollView.addSubview(mainStackView)
view.addSubview(scrollView)
In view did layout:
override func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews()
let top = topLayoutGuide.length
let bottom = bottomLayoutGuide.length
self.mainStackView.frame = CGRect(x: 0, y: top, width: view.frame.width, height: view.frame.height - top - bottom).insetBy(dx: 10, dy: 10)
dispatch_async(dispatch_get_main_queue())
{
self.scrollView.frame = self.view.bounds
self.scrollView.contentSize = CGSize(width: self.view.bounds.width, height: self.segmentedControl.frame.origin.y + self.segmentedControl.frame.height + 50)
}
print(scrollView.contentSize)
}
You need to set the height constraint of segment control.
For Example:
segmentedControl.heightAnchor.constraintEqualToConstant(50).active = true
More over, you can Add Empty bottom view to avoid stack view's must fill mechanism. This will show you desired view output.
var bottomView = UIView(frame: CGRectZero)
stackView.addArrangedSubview(bottomView)

Resources