RangeSeekSlider should start from Right to Left if language is Arabic - ios

I am using RangeSeekSlider for displaying slider in my app. In normal case i.e. for all the LTR languages(Left to Right) it is working perfectly. But when working with languages like Arabic which require the slider to start from Right to Left i.e. opposite of the normal it is not working for me.
For your reference i have tried following piece of code but it did not worked for me,
#IBOutlet weak var sliderAmount: RangeSeekSlider!
override func viewDidLoad() {
super.viewDidLoad()
if AppUtils.checkIfArabic() == true{
sliderAmount.semanticContentAttribute = .forceRightToLeft
}else{
self.sliderAmount.semanticContentAttribute = .forceLeftToRight
}
// Do any additional setup after loading the view.
}
Following is the screenshot of normal slider which is setup using below code
//MARK:- Setup Slider View
func setupSliderView(){
sliderAmount.disableRange = true
sliderAmount.enableStep = true
sliderAmount.step = 500
sliderAmount.delegate = self
sliderAmount.minValue = 500.0
lblAmt.text = "500"
sliderAmount.maxValue = 25000.0
sliderAmount.handleImage = UIImage(named: "ic_SliderHandler")
sliderAmount.handleDiameter = 35.0
sliderAmount.lineHeight = 7.0
sliderAmount.hideLabels = true
sliderAmount.tintColor = UIColor(displayP3Red: 235/255, green: 235/255, blue: 235/255, alpha: 1.0)
sliderAmount.colorBetweenHandles = UIColor(displayP3Red: 135/255, green: 102/255, blue: 123/255, alpha: 1.0)
}
Current output:
TIA.

Solved the issue using following piece of code
if L102Language.currentAppleLanguage() == "ar" { //Arabic
UIView.animate(withDuration: 0.1) {
self.sliderAmount.transform = CGAffineTransform(scaleX: -1, y: 1);
}
}
So, the Output now is,

Related

Update UI with Firebase Observe Data (Swift)

I am having a hard time updating the UI on my Swift app while observing a Firebase node. I have a red_value, a green_value, and a blue_value stored in firebase which is being fetched and used to construct a UIColor which is then used to update the background color of a button on my UI. I am successfully fetching the color values, but when i try to update the UI from within the observe closure, the color always turns out to be white and I can't figure out why.
My code can be found below for a better idea of what i am trying to accomplish when loading the view:
override func viewDidLoad() {
super.viewDidLoad()
self.charitiesReference.child(charityUsername!).observe(.value) {
snapshot in
let values = snapshot.value as! [String: Any]
let redValue = values["red_value"] as! CGFloat
let greenValue = values["green_value"] as! CGFloat
let blueValue = values["blue_value"] as! CGFloat
let charityColor = UIColor(red: redValue, green: greenValue, blue: blueValue, alpha: 1.0)
let ripplerFollowers = values["follower_ripplers"] as! [String: Bool]
if ripplerFollowers["\(self.username!)"] ?? false {
self.followOrFollowingButton.setTitle("Following", for: .normal)
//ERROR -> The line below is producing a white background on my button
self.followOrFollowingButton.backgroundColor = charityColor
} else {
self.followOrFollowingButton.setTitle("Follow", for: .normal)
self.followOrFollowingButton.backgroundColor = .clear
}
}
}
Update:
When I change self.followOrFollowingButton.backgroundColor = charityColor line to self.followOrFollowingButton.backgroundColor = UIColor(red: 0, green: 120, blue: 120, alpha: 1.0)
it works as intended, which means that something is going on with the redValue, greenValue, & blueValue variables
Thank you in advance for your help!
As it turned out, I had forgotten to divide each of the color values by 255 to put them in the 0.0 - 1.0 range. if the value is above 1.0, it is set to 1.0, which resulted in the white color.
After dividing by 255, it's working like a charm

Change the colors of CAGradientLayer with slider in realtime

I want to be able to change to change the colours of a CAGradientLayer in realtime with values i receive over #IBAction in the main ViewController. UISlider moves, color changes in background. I m asking for a theoretical approach.
What is the pattern or technique used to achieve this ? i really got lost and the mighty internet didn't reveal any usable help.
Subclasssing a UIView and add the gradientLayer there ? Then observe the variable with the incoming values and let KVO update the array entries (color sets) with cgColor values ?
Instantiate the gradientLayer in the main ViewController and update its color Properties there when value changes come in via #IBAction ?
Code helps, but its secondary here. i am asking more for a theoretical solution. I try to follow MVC but i am hardly confused where the gradientLayer should be instantiated, whats the best method to change the colours dynamically ect…
open for inputs, thx
Using a very simple extension for UIView you can get what you need. Here is a quick example using semi-static colors just for simplicity, but you can extend it as you need.
extension UIView {
/**
Adds colors to a CAGradient Layer.
- Parameter value: The Float coming from the slider.
- Parameter gradientLayer: The CAGradientLayer to change the colors.
*/
func addColorGradient (value: CGFloat, gradientLayer: CAGradientLayer) {
let topColor = UIColor(red: value / 255, green: 1, blue: 1, alpha: 1)
let bottomColor = UIColor(red: 1, green: 1, blue: value / 255, alpha: 1)
gradientLayer.colors = [topColor.cgColor, bottomColor.cgColor]
}
}
Usage example:
import UIKit
class ViewController: UIViewController {
let slider : UISlider = {
let slider = UISlider(frame: .zero)
slider.maximumValue = 255
slider.minimumValue = 0.0
return slider
}()
var gradientLayer = CAGradientLayer()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(slider)
slider.translatesAutoresizingMaskIntoConstraints = false
slider.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
slider.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
slider.widthAnchor.constraint(equalToConstant: 200).isActive = true
slider.heightAnchor.constraint(equalToConstant: 20).isActive = true
slider.addTarget(self, action: #selector(sliderValueChanged), for: .valueChanged)
gradientLayer.bounds = self.view.bounds
self.view.layer.insertSublayer(gradientLayer, at: 0)
}
#objc func sliderValueChanged(sender: UISlider) {
let currentValue = CGFloat(sender.value)
self.view.addColorGradient(value: currentValue, gradientLayer: gradientLayer)
}
}
Just change the topColor and bottomColor as you need and manipulate their values with the slider. Hope it helps
class ViewController: UIViewController {
var gradientLayer = CAGradientLayer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
gradientLayer.bounds = self.view.bounds
self.view.layer.insertSublayer(gradientLayer, at: 0)
}
// Slider Input
#IBAction func sliderValueChanged(_ sender: UISlider) {
self.view.addColorGradient(value: CGFloat(sender.value), gradientLayer: gradientLayer)
}
}

Status Bar clock has been truncated on iPhoneX

After adding a gradient layer to the statusbar and make it light or dark for different view controllers, at some random point in navigation, my clock in the status bar of notch iPhones has become truncated. like 1... or ...
I have tried these two solutions for make statusbar content white; But this has no effect on this random clock behaviour.
this:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.barStyle = .blackOpaque
self.setNeedsStatusBarAppearanceUpdate()
}
or this:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
Both of them changes my status bar color of content. Any idea about what is cause of this behavior???
and this is how I make the status bar gradient:
extension UIViewController {
func makeStatusBarGradient(){
let statusBarView = UIView(frame: UIApplication.shared.statusBarFrame)
let gradientLayer1 = CAGradientLayer()
gradientLayer1.frame = statusBarView.frame
gradientLayer1.colors = [UIColor.APColors.redGradient.cgColor, UIColor.APColors.orangeGradient.cgColor]
gradientLayer1.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer1.endPoint = CGPoint(x: 1.0, y: 0.5)
gradientLayer1.cornerRadius = 0
gradientLayer1.zPosition = -10
gradientLayer1.name = "gradient"
//Change status bar color
if let statusBar = UIApplication.shared.value(forKey: "statusBar") as? UIView{
statusBar.layer.addSublayer(gradientLayer1)
}
setNeedsStatusBarAppearanceUpdate()
}
func clearStatusBarGradient(){
if let statusBar = UIApplication.shared.value(forKey: "statusBar") as? UIView{
if let layers = statusBar.layer.sublayers?.filter({$0.name == "gradient"}){
if (layers.count > 0){
layers.first?.removeFromSuperlayer()
}
}
}
setNeedsStatusBarAppearanceUpdate()
}
}
and, the APColors are:
extension UIColor {
struct APColors {
static var redGradient : UIColor { return UIColor(red: 1.00, green: 0.42, blue: 0.24, alpha: 1) }
static var orangeGradient : UIColor { return UIColor(red: 0.95, green: 0.19, blue: 0.42, alpha: 1)}
}
}
You are using extension on UILabel, which override it's intrinsicContentSize. (or maybe you swizzling this method) So status bar clock label trigger it and got wrong intrinsicContentSize. Try to fix textSize calculation in this overrided method, or avoid overriding it if possible.
I can guess you're using UILabel+Padding from popular SO answer, so check if you've got this:
if let insets = padding {
insetsWidth += insets.left + insets.right
insetsHeight += insets.top + insets.bottom
textWidth -= insetsWidth
}
if you do, then simply change it:
if let insets = padding {
insetsWidth += insets.left + insets.right
insetsHeight += insets.top + insets.bottom
textWidth -= insetsWidth
} else {
return contentSize
}
As i do not know what's the APColor, so I changed the line with below & everything is working fine.
gradientLayer1.colors = [UIColor.red.cgColor, UIColor.orange.cgColor]
Try to change the same line and check your issue is solved or not. Most probably, APColor does not caused the issue.
Check is their any multiple stuffs is in you statusbar is available or not. e.g. indicator etc.
If you added anything else in your status bar then let me know.
Output

Swift 4 Page Controll Watcher

I'm using xcode 9.1 and swift 4.
I have 2 Buttons in my View Controller, and i want their colors changed when my carousel page is changed.
Here's my code but it.
I want it to check every time my carousel Scrolls.
is there any "OnPageControl" Methods in swift 4?
Here's my code ( in viewDidLoad ) :
if (self.carousel.pageControl.currentPage == 0)
{
self.registerButton.layer.borderColor = UIColor(red:68/255.0, green:180/255.0, blue:194/255.0, alpha: 1.0).cgColor
self.loginButton.layer.backgroundColor = UIColor(red:68/255.0, green:180/255.0, blue:194/255.0, alpha: 1.0).cgColor
NSLog("1")
}
else if (self.carousel.pageControl.currentPage == 1)
{
self.registerButton.layer.borderColor = UIColor(red:139/255.0, green:21/255.0, blue:21/255.0, alpha: 1.0).cgColor
self.loginButton.layer.backgroundColor = UIColor(red:139/255.0, green:21/255.0, blue:21/255.0, alpha: 1.0).cgColor
NSLog("2")
}
else if (self.carousel.pageControl.currentPage == 2)
{
self.registerButton.layer.borderColor = UIColor(red:174/255.0, green:135/255.0, blue:46/255.0, alpha: 1.0).cgColor
self.loginButton.layer.backgroundColor = UIColor(red:174/255.0, green:135/255.0, blue:46/255.0, alpha: 1.0).cgColor
NSLog("3")
}
There is nothing like a UIPageControlDelegate but UIScrollViewDelegate offers scrollViewDidScroll for that purpose. Using scrollView.contentOffset.x you can get the current page, assign it to the pageControl.currentPage and update your buttons there.

Comparing 2 UIColor(s)

This must have been asked before, but I cannot find a suitable reference. I have found this question, but that compares three numbers with each other.
I am trying to compare 2 UIColor(s) to avoid duplication. Each color is referenced in r, g, b, alpha. I form the colors so I can control number formatting.
What would be the appropriate way to handle this?
All help appreciated.
If you are creating all color the same way you can just use ==.
If your colors are in different color spaces and you just want to compare their RGBA value use the following:
extension UIColor {
func equals(_ rhs: UIColor) -> Bool {
var lhsR: CGFloat = 0
var lhsG: CGFloat = 0
var lhsB: CGFloat = 0
var lhsA: CGFloat = 0
self.getRed(&lhsR, green: &lhsG, blue: &lhsB, alpha: &lhsA)
var rhsR: CGFloat = 0
var rhsG: CGFloat = 0
var rhsB: CGFloat = 0
var rhsA: CGFloat = 0
rhs.getRed(&rhsR, green: &rhsG, blue: &rhsB, alpha: &rhsA)
return lhsR == rhsR &&
lhsG == rhsG &&
lhsB == rhsB &&
lhsA == rhsA
}
}
For instance:
let white1 = UIColor.white
let white2 = UIColor(colorLiteralRed: 1, green: 1, blue: 1, alpha: 1)
white1 == white2 //false
white1.cgColor == white2.cgColor //false
white1.equals(white2) //true
If you initialize as UIColor, you should be able to compare the colors to each other easily:
import UIKit
let myFirstColor = UIColor.red
let mySecondColor = UIColor.red
let myThirdColor = UIColor(colorLiteralRed: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
let iosWhite = UIColor.white
let myWhite = UIColor(white: 1.0, alpha: 1.0)
myFirstColor == mySecondColor //True
myFirstColor == myThirdColor //True
iosWhite == myWhite // True
From comments, there edge cases. I think these are all grays black, white and clear. To compensate, you can create your own grays and compare to it:
let myOtherWhite = UIColor(colorLiteralRed: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
which is not equal to UIColor.white
That said, it is easy to find the edge cases on playground:

Resources