How to set Gradient color for statusbar - swift3

Code:
extension UIApplication {
class var statusBarBackgroundColor: UIColor? {
get {
return (shared.value(forKey: "statusBar") as? UIView)?.backgroundColor
} set {
(shared.value(forKey: "statusBar") as? UIView)?.backgroundColor = newValue
}
}
}
UIApplication.statusBarBackgroundColor = .blue
I am trying to set gradient colour for status bar alone.How to change my code to set gradient colour.any help will be appreciated.thanks in advance

This is how I manage it.
let gradientLayer = CAGradientLayer()
gradientLayer.frame = CGRect(x:0, y:-20, width:375, height:64)
let colorTop = UIColor(red: 69/255, green: 90/255, blue: 195/255, alpha: 1.0).cgColor
let colorBottom = UIColor(red: 230/255, green: 44/255, blue: 75/255, alpha: 1.0).cgColor
gradientLayer.colors = [ colorTop, colorBottom]
gradientLayer.locations = [ 0.0, 1.0]
gradientLayer.frame = CGRect(x:0, y:-20, width:375, height:self.view.frame.height * 0.06)
let window: UIWindow? = UIApplication.shared.keyWindow
let view = UIView()
view.backgroundColor = UIColor.clear
view.translatesAutoresizingMaskIntoConstraints = false
view.frame = CGRect(x: 0, y: 0, width: (window?.frame.width)!, height: self.view.frame.height * 0.07)
view.layer.addSublayer(gradientLayer)
window?.addSubview(view)
That only add the gradient to the view behind the status bar

Related

Gradient not redrawing properly

I am attempting to have a CGRect that has a dynamic gradient. When I use the view models gradient I am able to observe the gradient changing. However the view does not change as expected.
If I use hardcoded gradients in the view which toggle between red and blue I see that the view is redrawing with the updated gradient.
What am I missing?
View Model:
#Published var forceRedraw: Bool = false
#Published var annGradient: Gradient = Gradient(colors: [.red]) {
didSet {
print("ViewModel", annGradient.stops.first!, annGradient.stops.last!)
forceRedraw.toggle()
}
}
View:
struct SchematicView: View {
#EnvironmentObject var vM: AppViewModel
#State var refresh: Bool = false
var body: some View {
VStack(alignment: .center) {
Spacer()
ScrollView {
if refresh {
Canvas { context, size in
let w = size.width
let h = size.height
let grad = vM.annGradient
print("View1", grad.stops.first!, grad.stops.last!)
let annPath = CGRect(x: w/2, y: 0, width: 100, height: h)
context.fill(Path(annPath), with: .linearGradient(grad, startPoint: CGPoint(x: 0, y: 0), endPoint: CGPoint(x: 0, y: h)))
}.frame(width: 300, height: 500)
} else {
Canvas { context, size in
let w = size.width
let h = size.height
let grad = vM.annGradient
print("View2", grad.stops.first!, grad.stops.last!)
let annPath = CGRect(x: w/2, y: 0, width: 100, height: h)
context.fill(Path(annPath), with: .linearGradient(grad, startPoint: CGPoint(x: 0, y: 0), endPoint: CGPoint(x: 0, y: h)))
}.frame(width: 300, height: 500)
}
}
.syncBool($vM.forceRedraw, with: $refresh)
.onAppear(perform: {
refresh = vM.forceRedraw
})

How to move scrollview with buttons only in SwiftUI

Previously I did with Swift4 UIScrollView which scrolled with buttons and x offset.
In Swift4 I have:
Set Scrolling Enabled and Paging Enabled to false.
Created the margins, offsets for each frame in UIScrollView and changed the position with buttons Back and Next.
Here is the code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var buttonSound: UIButton!
#IBOutlet weak var buttonPrev: UIButton!
#IBOutlet weak var buttonNext: UIButton!
#IBOutlet weak var scrollView: UIScrollView!
var levels = ["level1", "level2", "level3", "level4"]
let screenWidth = UIScreen.main.bounds.width
let screenHeight = UIScreen.main.bounds.height
var currentLevel = 1
var previousLevel: Int? = nil
override func viewDidLoad() {
super.viewDidLoad()
//Defining the Various Swipe directions (left, right, up, down)
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(self.handleGesture(gesture:)))
swipeLeft.direction = .left
self.view.addGestureRecognizer(swipeLeft)
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(self.handleGesture(gesture:)))
swipeRight.direction = .right
self.view.addGestureRecognizer(swipeRight)
addHorizontalLevelsList()
customizeButtons()
resizeSelected()
}
func addHorizontalLevelsList() {
var frame : CGRect?
for i in 0..<levels.count {
let button = UIButton(type: .custom)
let buttonW = screenWidth/3
let buttonH = screenHeight/2
frame = CGRect(x: CGFloat(i+1) * (screenWidth/2) - (buttonW/2),
y: buttonH - 100,
width: buttonW,
height: buttonH)
button.frame = frame!
button.tag = i+1
button.backgroundColor = .lightGray
button.addTarget(self, action: #selector(selectTeam), for: .touchUpInside)
button.setTitle(levels[i], for: .normal)
scrollView.addSubview(button)
}
scrollView.contentSize = CGSize(width: (screenWidth/2 * CGFloat(levels.count)),
height: screenHeight)
scrollView.backgroundColor = .clear
self.view.addSubview(scrollView)
}
func customizeButtons(){
buttonPrev.frame = CGRect(x: 0,
y: (screenHeight/2) - 40,
width: 80, height: 80)
buttonNext.frame = CGRect(x: screenWidth - 80,
y: (screenHeight/2) - 40,
width: 80, height: 80)
buttonPrev.superview?.bringSubviewToFront(buttonPrev)
buttonNext.superview?.bringSubviewToFront(buttonNext)
}
#objc func selectTeam(button: UIButton) {
button.transform = CGAffineTransform(scaleX: 0.6, y: 0.6)
UIView.animate(withDuration: 1.0,
delay: 0,
usingSpringWithDamping: CGFloat(0.20),
initialSpringVelocity: CGFloat(6.0),
options: UIView.AnimationOptions.allowUserInteraction,
animations: {
button.transform = CGAffineTransform.identity
},
completion: { Void in() }
)
print(levels[button.tag])
let vc = PopTypeVC(nibName: "PopTypeVC", bundle: nil)
vc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
self.present(vc, animated: true)
}
#IBAction func prevLevel(_ sender: Any) {
if currentLevel > 0 {
currentLevel -= 1
scroll()
}
}
#IBAction func nextLevel(_ sender: Any) {
if currentLevel < levels.count {
currentLevel += 1
scroll()
}
}
func scroll(){
print(currentLevel)
print(previousLevel as Any)
scrollView.setContentOffset(CGPoint(x: currentLevel * Int(screenWidth/2), y: 0), animated: true)
resizeSelected()
}
// The #objc before func is a must, since we are using #selector (above)
#objc func handleGesture(gesture: UISwipeGestureRecognizer) -> Void {
if gesture.direction == UISwipeGestureRecognizer.Direction.right {
prevLevel(self)
}
else if gesture.direction == UISwipeGestureRecognizer.Direction.left {
nextLevel(self)
}
}
func resizeSelected(){
if previousLevel != nil {
let previousFrame = CGRect(x:CGFloat(previousLevel!) * (screenWidth/2) - (screenWidth/3)/2,
y: (screenHeight/2) - 100,
width: screenWidth/3,
height: screenHeight/2)
scrollView.viewWithTag(previousLevel!)?.frame = previousFrame
}
let currentFrame = CGRect(x: CGFloat(currentLevel) * (screenWidth/2) - (screenWidth/3)/2 - 10,
y: (screenHeight/2) - 110,
width: screenWidth/3 + 20,
height: screenHeight/2 + 20)
scrollView.viewWithTag(currentLevel)?.frame = currentFrame
previousLevel = currentLevel
}
}
The problem is I can't do this with SwiftUI:
struct ContentView: View {
static var levels = ["level1",
"level2",
"level3",
"level4"]
var currentLevel = 1
var previousLevel: Int? = nil
let screenW = UIScreen.main.bounds.width
let screenH = UIScreen.main.bounds.height
let margin1 = 50
let margin2 = 100
let margin3 = 20
let sceneButtonW = 100
let buttonPadding = 40
var body: some View {
ZStack {
// Horizontal list
VStack {
Spacer()
.frame(height: margin2)
ScrollView(.horizontal, showsIndicators: false) {
HStack{
Spacer()
.frame(width: buttonPadding + sceneButtonW/2)
ForEach(0..<ContentView.levels.count) { i in
cardView(i: i).tag(i+1)
}
Spacer()
.frame(width: buttonPadding + sceneButtonW/2)
}
}
Spacer()
.frame(height: margin3)
}
}
.background(Image("bg")
.resizable()
.edgesIgnoringSafeArea(.all)
.aspectRatio(contentMode: .fill))
}
}
Question: Are there any methods to disable automatic scrolling at all and use offsets at ScrollView with SwiftUI?
This already built solution for SwiftUI
https://github.com/fermoya/SwiftUIPager
However, there is no real example.

how to gradient a background of a tableview in swift

func setTableViewBackgroundGradient(sender: UITableViewController, _ topColor:UIColor, _ bottomColor:UIColor) {
let gradientBackgroundColors = [topColor.cgColor, bottomColor.cgColor]
let gradientLocations = [0.0,1.0]
let gradientLayer = CAGradientLayer()
gradientLayer.colors = gradientBackgroundColors
gradientLayer.locations = gradientLocations as [NSNumber]
gradientLayer.frame = sender.tableView.bounds
let backgroundView = UIView(frame: sender.tableView.bounds)
backgroundView.layer.insertSublayer(gradientLayer, at: 0)
sender.tableView.backgroundView = backgroundView
}
Try this it's working for me (Swift 4)
Note : First of all set Tableview Cell & Cell ContentView Background
Color to Clear Color.
#IBOutlet fileprivate weak var tblVw: UITableView!
private var gradientLayer = CAGradientLayer()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if gradientLayer.superlayer != nil {
gradientLayer.removeFromSuperlayer()
}
let topColor = UIColor(red: 16.0/255.0, green: 12.0/255.0, blue: 54.0/255.0, alpha: 1.0)
let bottomColor = UIColor(red: 57.0/255.0, green: 33.0/255.0, blue: 61.0/255.0, alpha: 1.0)
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
gradientLayer.colors = [topColor.cgColor, bottomColor.cgColor]
gradientLayer.frame = tblVw.bounds
let backgroundView = UIView(frame: tblVw.bounds)
backgroundView.layer.insertSublayer(gradientLayer, at: 0)
tblVw.backgroundView = backgroundView
}
Output:

Can't get UILabel to word wrap

I have used Interface Builder to get UILabelViews to word wrap, but this is my first attempt to do it programmatically. I believe the issue is that although I'm setting:
label.lineBreakMode = .byWordWrapping
label.numberOfLines = 0
I'm setting a line height which might conflict with these properties?
override func layoutSubviews() {
super.layoutSubviews()
imageViewContent.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)
imageViewContent.loadImageWithURL(imageName!)
label.frame = CGRect(x: 0, y: 0, width: frame.size.width-10, height: 21)
label.center = imageViewContent.center
label.textAlignment = .center
label.clipsToBounds = true
label.layer.cornerRadius = 10.0
label.textColor = .white
label.font = UIFont(name: "AvenirNext-DemiBold", size: 15)
label.backgroundColor = UIColor.black.withAlphaComponent(0.5)
label.lineBreakMode = .byWordWrapping
label.numberOfLines = 0
label.text = photoName
}
As I suspected, hardcoding the height of the label prevented it from word wrapping. I've created a labelHeight variable and added a function at the bottom of the class to calculate the labelHeight based on the content, font size, and labelWidth I set. Code works fine now:
class NTWaterfallViewCell :UICollectionViewCell, NTTansitionWaterfallGridViewProtocol{
var photoName = ""
var imageName : String?
var labelHeight: CGFloat = 0.0
var imageViewContent : UIImageView = UIImageView()
var label = UILabel()
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.lightGray
contentView.addSubview(imageViewContent)
contentView.addSubview(label)
}
override func layoutSubviews() {
super.layoutSubviews()
imageViewContent.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)
imageViewContent.loadImageWithURL(imageName!)
label.text = photoName
labelHeight = heightForText(photoName, width: frame.size.width-10)
label.frame = CGRect(x: 0, y: 0, width: frame.size.width-10, height: labelHeight)
label.center = imageViewContent.center
label.textAlignment = .center
label.clipsToBounds = true
label.layer.cornerRadius = 10.0
label.textColor = .white
label.font = UIFont(name: "AvenirNext-DemiBold", size: 15)
label.backgroundColor = UIColor.black.withAlphaComponent(0.5)
label.lineBreakMode = .byWordWrapping
label.numberOfLines = 0
}
func heightForText(_ text: String, width: CGFloat) -> CGFloat {
let font = UIFont(name: "AvenirNext-DemiBold", size: 15)
let rect = NSString(string: text).boundingRect(with: CGSize(width: width, height: CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return ceil(rect.height)
}
}

How to add spacing to Left BarButtonItem Image with Swift 3

I would like to add space to the left of the bar button.
So, I add this code.
navbar.autoresizingMask = [.flexibleWidth, .flexibleBottomMargin, .flexibleRightMargin]
navbar.delegate = self
UINavigationBar.appearance().barTintColor = UIColor(red: 0.0/255.0, green:49.0/255.0, blue:79.0/255.0, alpha:0.1)
UINavigationBar.appearance().tintColor = UIColor.white
UINavigationBar.appearance().isTranslucent = true
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName : UIColor.white]
navItem.title = prefs.value(forKey: "PROVIDER_NAME") as! String?
let image = UIImage(named: "back_image")
navItem.leftBarButtonItem = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(addTapped))
After adding this code, the button image does not show well and looks no good.
Could anyone help me to solve this problem?
Hi Code given below might be useful for you.
extension UIBarButtonItem {
class func itemWith(colorfulImage: UIImage?, target: AnyObject, action: Selector) -> UIBarButtonItem {
let button = UIButton(type: .custom)
button.setImage(colorfulImage, for: .normal)
button.frame = CGRect(x: 0.0, y: 0.0, width: 44.0, height: 44.0)
button.imageEdgeInsets = UIEdgeInsetsMake(0, -50, 0, 0)
button.addTarget(target, action: action, for: .touchUpInside)
let barButtonItem = UIBarButtonItem(customView: button)
return barButtonItem
}
}
You can increase or decrease Left Padding for UIEdgeInsetsMake(0, -50, 0, 0) as per your requirement for left padding.
You can use above extension in your code as describe below.
self.navigationItem.leftBarButtonItem = UIBarButtonItem.itemWith(colorfulImage: UIImage(named: "ic_back")?.withColor(UIColor.white), target: self, action: #selector(btnBackClicked))
func btnBackClicked() {
print("your code here on back button tapped.")
}