How to show a view in every screen at bottom - ios

I would like to add a bottom view in all view controllers which will show the progress of Audio or video play.I need Like this
i did in the following
let window = UIApplication.sharedApplication().keyWindow!
let v = UIView(frame: CGRect(x: window.frame.origin.x, y: window.frame.origin.y, width: window.frame.width, height: window.frame.height))
window.addSubview(v);
v.backgroundColor = UIColor.blackColor()
let v2 = UIView(frame: CGRect(x: 50, y: 50, width: 100, height: 50))
v2.backgroundColor = UIColor.whiteColor()
window.addSubview(v2)
But its not displaying in every screen.

I have an approach for you.
Firstly you have to manage this in global way.
You need to create an Object of AppDelegate. And make a function in that class in which you can code
Then on loading your main view, you need to call that function so it will be visible as you want.

Related

Blend UIView (Overlay) with app background

I would like to blend a UIView with my app's background, using a special blend mode (in my case, the Overlay mode). However, the view to blend is contained in a complex hierarchy of views.
Blending a view with its direct siblings can be achieved using view.layer.compositingFilter = "overlayBlendMode", but the view won't blend with non-siblings views, like the app background.
To recreate the problem, I made the following playground:
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
override func loadView() {
let parentView = UIView()
parentView.backgroundColor = .purple
// Child view
let childView = UIView(frame: CGRect(x: 50, y: 50, width: 200, height: 200))
childView.layer.borderColor = UIColor.orange.cgColor
childView.layer.borderWidth = 3
parentView.addSubview(childView)
// Child child view
let childChildView = UIView(frame: CGRect(x: 50, y: 50, width: 100, height: 50))
childChildView.backgroundColor = .white
childChildView.layer.compositingFilter = "overlayBlendMode"
childView.addSubview(childChildView)
self.view = parentView
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
We can see here that the child child view, in white, is not blended:
Whereas the view should appear blended like this (the border should not change color):
To create the second picture, I applied the compositing filter on the childView instead of the childChildView, which will blend all the other subviews — therefore it's not what I want. I just want this specific view to be blended.
Note: this view is supposed to move, because it's inside a UIScrollView.
EDIT: More complex example with image background and scrollviews
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
override func loadView() {
let parentView = UIView()
// Background image
let backgroundImageView = UIImageView(image: UIImage(named: "image.jpg")!)
backgroundImageView.frame = UIScreen.main.bounds
parentView.addSubview(backgroundImageView)
// Page view (horizontal scrollview)
let pageView = UIScrollView(frame: CGRect(x: 50, y: 50, width: 200, height: 200))
pageView.contentSize = CGSize(width: 600, height: 200)
pageView.flashScrollIndicators()
pageView.layer.borderColor = UIColor.orange.cgColor
pageView.layer.borderWidth = 3
parentView.addSubview(pageView)
// Child view (vertical scrollview)
let childView = UIScrollView(frame: CGRect(x: 20, y: 20, width: 100, height: 150))
childView.contentSize = CGSize(width: 100, height: 300)
childView.layer.borderColor = UIColor.green.cgColor
childView.layer.borderWidth = 3
pageView.addSubview(childView)
// Child child view
let childChildView = UIView(frame: CGRect(x: 50, y: 50, width: 100, height: 50))
childChildView.backgroundColor = .white
childChildView.layer.compositingFilter = "overlayBlendMode"
childView.addSubview(childChildView)
self.view = parentView
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
UPDATE 2:
I've tried several ways including adding layers or creating custom image filters that use the background image as input image but none of these solutions got the desired result. The main problem was always the view hierarchy.
I may have found a solution by using a generated image of the views or the actual background image as the content background of the childView once the childChildView is being created but before being displayed. I've changed your example code a bit to add a scroll view and background image in the parentView. See if this works for you / is your desired result:
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
override func loadView() {
let parentView = UIView()
parentView.backgroundColor = .purple
let imageName = "image.jpg"
let image = UIImage(named: imageName)
let imageWidth = Int((image?.size.width)!)
let imageheight = Int((image?.size.height)!)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: 50, y: 50, width: imageWidth , height: imageheight)
parentView.addSubview(imageView)
// Child view as UIScrollView
let childView = UIScrollView(frame: CGRect(x: 55, y: 55, width: imageWidth - 10, height: imageheight - 10 ))
childView.contentSize = CGSize(width: imageWidth - 10, height: 5000)
childView.layer.borderColor = UIColor.orange.cgColor
childView.flashScrollIndicators()
childView.layer.borderWidth = 10
parentView.addSubview(childView)
// ChildChild view
let childChildView = UIView(frame: CGRect(x: 15, y: 100, width: 85, height: imageheight - 180))
childChildView.layer.compositingFilter = "overlayBlendMode"
childChildView.backgroundColor = .white
//Creating a static image of the background views BEFORE adding the childChildView.
let format = UIGraphicsImageRendererFormat()
format.scale = 1
format.preferredRange = .standard ///color profile
///Change the imageView to the parentView size of the app. Not available if not set in the playground.
let renderer = UIGraphicsImageRenderer(size: imageView.bounds.size, format: format)
let imageBG = renderer.image { context in
///This draws all subviews of the parentView one after the other.
///Because the background image is not a parent of our current view, otherwise childView.drawHierachy would have been enough
for subview in parentView.subviews {
///Skip specific views or view classes you don't want to be added to the image. or if you only need the parentView itself rendered remove the for in loop.
subview.drawHierarchy(in: imageView.bounds, afterScreenUpdates: true)
}
}
//Adding the static background image. This could simply also be the actual image: UIImage if no other views are supposed to be used.
childView.layer.contents = imageBG.cgImage
childView.addSubview(childChildView)
self.view = parentView
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
It results in the following:
UPDATE:
The colors in the images are misleading, as you could assume a normal transparency effect would be the same. But the overlayBlendMode is quite different as Coconuts has pointed out. I assume the issue is that the compositingFilter only works with the view below, even if this view is transparent.
I tried finding a workaround by using a mask that cuts out a square of the size of the childchild from the childview. But this also didn't work as the mask is also applied to all subviews. The only way I got it to work is by making the childchildview a sibling of childview instead, or a direct subview of the background view. But not sure if this will be possible in the complex view hierarchy mentioned by Coconuts.
// Sibling view with adjusted x and y
let childChildView = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
childChildView.backgroundColor = .white
childChildView.layer.compositingFilter = "overlayBlendMode"
parentView.addSubview(childChildView)
MISC:
To only get the visual result of the sample images, not actually using the overlayBlendMode filter as asked by Coconut.
If you only need to blend the color you could change the alpha value of the color.
// Child child view
let childChildView = UIView(frame: CGRect(x: 50, y: 50, width: 100, height: 50))
childChildView.backgroundColor = UIColor(white: 1, alpha: 0.5)
//childChildView.layer.compositingFilter = "overlayBlendMode"
childView.addSubview(childChildView)
Or try this:
// Child child view
let childChildView = UIView(frame: CGRect(x: 50, y: 50, width: 100, height: 50))
childChildView.backgroundColor = .white
childChildView.layer.opacity = 0.5
childView.addSubview(childChildView)
ADDITIONAL ATTEMPTS WHEN HAVING SEVERAL SCROLL VIEWS:
This is an attempt to solve the from Coconut added more complicated view hierarchy with multiple scroll views. The performance needs to be improved or the part that adjusts the background image of the background image layer needs to run in sync when the app is updating (redrawing) its views. At the moment it's lagging behind a bit.
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
override func loadView() {
let parentView = UIView()
// Background image
let backgroundImageView = UIImageView(image: UIImage(named: "image.jpg")!)
backgroundImageView.frame = UIScreen.main.bounds
parentView.addSubview(backgroundImageView)
// Page view (horizontal scrollview)
let pageView = UIScrollView(frame: CGRect(x: 50, y: 50, width: 200, height: 200))
pageView.contentSize = CGSize(width: 600, height: 200)
pageView.flashScrollIndicators()
pageView.layer.borderColor = UIColor.yellow.cgColor
pageView.layer.borderWidth = 3
pageView.clipsToBounds = true
parentView.addSubview(pageView)
// Child view (vertical scrollview)
let childView = UIScrollView(frame: CGRect(x: 20, y: 20, width: 100, height: 150))
childView.contentSize = CGSize(width: 100, height: 300)
childView.layer.borderColor = UIColor.red.cgColor
childView.layer.borderWidth = 3
pageView.addSubview(childView)
// Child child view
let childChildView = UIView(frame: CGRect(x: 50, y: 50, width: 50, height: 50))
//Child child view foreground sublayer
let childChildFrontLayer = CALayer()
childChildFrontLayer.frame = childChildView.frame.offsetBy(dx: -75, dy: -50)
childChildFrontLayer.backgroundColor = UIColor.white.cgColor
childChildFrontLayer.compositingFilter = "overlayBlendMode"
//Child child view background sublayer
let childChildBackLayer = CALayer()
childChildBackLayer.contents = UIImage(named: "image.jpg")?.cgImage
var absolutFrame = parentView.convert(childChildView.frame, from: childView)
childChildBackLayer.frame = CGRect(x: -absolutFrame.minX, y: -absolutFrame.minY, width: backgroundImageView.frame.width, height: backgroundImageView.frame.height)
childChildView.layer.addSublayer(childChildBackLayer)
childChildView.layer.addSublayer(childChildFrontLayer)
childView.addSubview(childChildView)
//Checking for any scrolling. Is slightly faster then the scollview delegate methods but might cause main thread checker warning.
DispatchQueue.global(qos: .userInteractive).async {
while true {
if pageView.isDragging || pageView.isTracking || pageView.isDecelerating || childView.isDragging || childView.isTracking || childView.isDecelerating {
absolutFrame = parentView.convert(childChildView.frame, from: childView)
DispatchQueue.main.async {
childChildBackLayer.frame = CGRect(x: -absolutFrame.minX, y: -absolutFrame.minY, width: backgroundImageView.frame.width, height: backgroundImageView.frame.height)
}
}
}
}
self.view = parentView
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
Is the issue related to the child view background being clear and therefore 'blending' to give the white colour. Could set the child view background colour to be equal to the app background and then then just blend the childView within the childChildView?

How do I add two UILabel to a single TableView?

I'm making a message when the TableView is empty, this is code :
let emptyLabel=UILabel(frame: CGRect(x: 0,y: 0, width: self.view.bounds.width, height: self.view.bounds.height))
let emptyLabel2=UILabel(frame: CGRect(x: 0,y: 0, width: self.view.bounds.width, height: self.view.bounds.height))
emptyLabel.text = "no reminder added yet"
emptyLabel.textColor=UIColor.darkGray
emptyLabel.font=UIFont(name: "HelveticaNeue-Light", size: 18)
emptyLabel.textAlignment = NSTextAlignment.center
emptyLabel2.text = "you add by going back to the homescreen"
emptyLabel2.textColor=UIColor.darkGray
emptyLabel2.font=UIFont(name: "HelveticaNeue-Light", size: 12)
emptyLabel2.textAlignment = NSTextAlignment.center
self.tableView.backgroundView = emptyLabel2
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.none
return 0
It works, but how do I add emptyLabel2 beneath the emptyLabel. I want to use the defined label properties.
If you're trying to add your 2 labels to the superview, with emptyLabel2 on top of emptyLabel, all you need to do is this:
self.view.addSubview(emptyLabel)
self.view.addSubview(emptyLabel2)
They will be added in the order you call addSubview.
If you are asking about how to define the frame so that they show one before the next, you need to modify how you are initializing. Something like this (for example):
let emptyLabel=UILabel(frame: CGRect(x: 0,y: 0, width: self.view.bounds.width, height: 20))
let emptyLabel2=UILabel(frame: CGRect(x: 0,y: 20, width: self.view.bounds.width, height: 20))
self.view.addSubview(emptyLabel)
self.view.addSubview(emptyLabel2)
In reality you may want to find a better way to set the size, or just make 1 label with attributedText so that you do not need 2 labels.

How to add Header/Custom View to JSQMessagesViewController?

I'm using a storyboard to build my UIs. I wasn't able to find same ticket with same question on JSQMessageViewController's repo on Github.
Basically, I want to add a custom view, say a header in my controller, like so:
What I did so far:
Add the view to the storyboard - didn't work.
I programmatically made a UICollectionReusableView and add it to the data source function: viewForSupplementaryElementOfKind
Any ideas?
You can change anything you like but here is how to do it very simply programatically.
call addViewOnTop() this in your viewDidLoad
func addViewOnTop() {
let selectableView = UIView(frame: CGRect(x: 0, y: 60, width: self.view.bounds.width, height: 40))
selectableView.backgroundColor = .red
let randomViewLabel = UILabel(frame: CGRect(x: 20, y: 10, width: 100, height: 16))
randomViewLabel.text = "RandomView"
selectableView.addSubview(randomViewLabel)
view.addSubview(selectableView)
}
Add an UIEdgeInset to let you view your messages under the new view
Call this in the viewDidLoad()
self.collectionView?.collectionViewLayout.sectionInset = UIEdgeInsets(top: 80, left: 0, bottom: 0, right: 0)

Are iOS "views" and HTML divs similar?

I found that placing a view in my app and sizing it to my needs is pretty similar to divs in HTML. Should I be using them this way?
Here's an example of a place I want to use a view.
I want to fill that in, should I be using a view here? or something more semantical?
End result with a view:
If you want to set a rectangle somewhere you could definitely use an UIView(), If you´re using your storyboard make sure to set the right constraint and if you´re doing it programmatically you could do the following to get it work with all phone sizes:
Swift 3.0:
let screen = UIScreen.main.bounds
let anotherView = UIView(frame: CGRect(x: 0, y: 0, width: screen.width, height: 45))
anotherView.backgroundColor = UIColor.blue
view.addSubview(anotherView)
Swift 2.x:
let screen = UIScreen.mainScreen().bounds
let anotherView = UIView(frame: CGRect(x: 0, y: 0, width: screen.width, height: 45))
anotherView.backgroundColor = UIColor.blueColor()
view.addSubview(anotherView)

Subview on top of window view in Swift

I want to place a UIView over the entire screen (including the navigation bar). This view will be black with 0.3 opacity. I want to do this to darken out the screen content and push a view on top of this. I am using this code:
UIApplication.sharedApplication().keyWindow?.addSubview(darkView)
This covers the whole screen as expected. However I now want to place another view on top of this dark view. Is there a way to do this? Everything I try just results in the view being under the dark view. Any pointers would be really appreciated! thanks
It's really simple.
You just add another view to window! And it will be there, on top of the first view you added. For example, this code adds a black view and a white view:
let window = UIApplication.sharedApplication().keyWindow!
let v = UIView(frame: window.bounds)
window.addSubview(v)
v.backgroundColor = UIColor.blackColor()
let v2 = UIView(frame: CGRect(x: 50, y: 50, width: 100, height: 50))
v2.backgroundColor = UIColor.whiteColor()
window.addSubview(v2)
You can also add the new view as a sub view of the first view you added:
let window = UIApplication.sharedApplication().keyWindow!
let v = UIView(frame: window.bounds)
window.addSubview(v)
v.backgroundColor = UIColor.blackColor()
let v2 = UIView(frame: CGRect(x: 50, y: 50, width: 100, height: 50))
v2.backgroundColor = UIColor.whiteColor()
v.addSubview(v2)
Swift 4
let window = UIApplication.shared.keyWindow!
let v = UIView(frame: window.bounds)
window.addSubview(v)
v.backgroundColor = .black
let v2 = UIView(frame: CGRect(x: 50, y: 50, width: 100, height: 50))
v2.backgroundColor = UIColor.white
v.addSubview(v2)
Simple!
For SWIFT 3 use this:
let window = UIApplication.shared.keyWindow!
window.addSubview(someView)
Swift 4,
Adding a UIViewController as a subview to UIWindow
This code is for adding view controller as a subview, covering the whole window with simple animation.
let appDelegate = UIApplication.shared.delegate as! AppDelegate
var customReviewPopup = ReviewPopupViewController.init(nibName: "ReviewPopupViewController", bundle: Bundle.main)
self.appDelegate.window?.addSubview((customReviewPopup.view)!)
self.customReviewPopup.view.frame = (self.appDelegate.window?.bounds)!
self.customReviewPopup.view.alpha = 0
self.customReviewPopup.view.isHidden = true
UIView.animate(withDuration: 0.3, delay: 0, options: .transitionCrossDissolve, animations: {
self.customReviewPopup.view.isHidden = false
self.customReviewPopup.view.alpha = 1
}, completion: nil)
Swift 5:
let window = UIApplication.shared.windows.last!
let viewToShow = UIView(frame: CGRect(x: 0, y: 0, width: window.frame.size.width, height: 40.0))
viewToShow.backgroundColor = UIColor.white
window.addSubview(viewToShow)

Resources