简体   繁体   中英

Swift: UISlider one side of track not rounded

I have a custom UISlider, but there is a side of the slider which is not rounded在此处输入图像描述

Here my custom view:

class PrimarySliderView: UISlider {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setup()
    }

    override func trackRect(forBounds bounds: CGRect) -> CGRect {
        return CGRect(origin: bounds.origin, size: CGSize(width: bounds.width, height: 6))
    }

    func setup() {
        tintColor = .cornFlowerBlue
    }

How to round the right side also?

EDIT

The slider is cutted because my application is RTL, when I change to LTR this display correctly but not in RTL, how to resolve this problem?

In My AppDelegate I force RTL:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        UIView.appearance().semanticContentAttribute = .forceRightToLeft

        return true
    }

Either you need to add rounded image for minimum and maximum track or you can create rounded view using colors

other workaround is

override func layoutSubviews() {
          super.layoutSubviews()

        self.layer.sublayers![1].cornerRadius = 10

    }

在此处输入图片说明

try this one

if(UIApplication.sharedApplication().userInterfaceLayoutDirection == UIUserInterfaceLayoutDirection.RightToLeft)
{
   uiSlider.transform = CGAffineTransformMakeScale(-1.0, 1.0);
}

Here is a solution/workaround and it works with iOS 14 based on this answer . Also, it is tweaked to solve blurry edges.

if UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft {
        setMinimumTrackImage(getImageWithColor(color: .blue, size: frame.size).resizableImage(withCapInsets: UIEdgeInsets(top: 3, left: 3, bottom: 3, right: 3), resizingMode: .stretch), for: .normal)
}

And here is the implementation of getImageWithColor:

private func getImageWithColor(color: UIColor, size: CGSize) -> UIImage {
    
    let layer: CALayer =  CALayer()
    layer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
    layer.masksToBounds = true
    layer.cornerRadius = 3
    layer.backgroundColor = color.cgColor
    
    UIGraphicsBeginImageContextWithOptions(size, false, 0)
    layer.render(in: UIGraphicsGetCurrentContext()!)
    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return image
}

NOTE: Don't forget to change cornerRadius and UIEdgeInsets to suit your needs.

Before applying the fix:

修复前

After applying the fix:

修复后

iOS14+ version of Jawad's answer

final class RoundedSlider: UISlider {
    override func layoutSubviews() {
        super.layoutSubviews()

        if #available(iOS 14.0, *) {
            if let layers = layer.sublayers?.first?.sublayers, layers.count > 0, let layer = layers[1] {
                layer.cornerRadius = layer.bounds.height / 2
            }
        } else {
            if let layers = layer.sublayers, layers.count > 0, let layer = layers[1] {
                layer.cornerRadius = layer.bounds.height / 2
            }
        }
    }
}

For SwiftUI

The problem occurs, as mentioned in the question when forcing the environment to be RTL. like so .environment(\.layoutDirection, .rightToLeft)

I found a simple solution that works for me.

Just use a rotation effect like so: .rotationEffect(Angle(degrees: 180)) on the slider and it will look as if it's RTL.

This will just rotate the slider 180 degrees

Note

if you would like to add some padding make sure to put it after this modifier so it will make sense or else you will have to enter the opposite edge. (for example .bottom instead of .top )

This will apply the padding to the top

Slider(value: $progress)
    .rotationEffect(Angle(degrees: 180))
    .padding(.top, 20) // After rotating

This will apply the padding to the bottom

Slider(value: $progress)
    .padding(.top, 20) // before 
    .rotationEffect(Angle(degrees: 180))

Hope this helps:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM