简体   繁体   中英

Is it possible to set the alignment of segmented Control titles to the left?

I have been looking around for a way to set the alignment of the segmented control titles to the left but I don't seem to be able to achieve what I want.

I have created this little function to change the frame of the subviews of the segment control. It works at first.

    func modifyFrameOfSegment() {
       for segment in segmentedControl.subviews {
          guard segment.subviews.isNotEmpty else { return }
          segment.contentMode = .left
           for label in segment.subviews where label is UILabel {
              label.frame = CGRect(x: 0, y: label.frame.origin.y, width: label.frame.size.width, height: label.frame.size.height)
              (label as! UILabel).textAlignment = .left
           }
       }
    }

But everytime I select a new segment it resets the frames of all the subviews and center align all the titles again.

Is there a way to achieve a permanent left alignment for the segment titles in a segmented control?

Any tips or advice would be greatly appreciated.

Thank you for your time.

Let's use this method

self.segmentedControl.setContentPositionAdjustment(UIOffset(horizontal: -20, vertical: 0), forSegmentType: .left, barMetrics: .default)

And you can do what you want (Of course, you can change the horizontal & vertical value by your needs). Here is the result:

在此处输入图像描述

Update:

There's apparently no way to set the alignment of the items, but you can fake it by adjusting the position of each individual item using setContentOffset(_ offset: CGSize, forSegmentAt segment: Int) . Here's a kludgy example:

class LeftSegmentedControl: UISegmentedControl {

    var margin : CGFloat = 10

    override func layoutSubviews() {
        super.layoutSubviews()
        leftJustifyItems()
    }

    func leftJustifyItems() {
        let fontAttributes = titleTextAttributes(for: .normal)
        let segments = numberOfSegments - 1
        let controlWidth = frame.size.width
        let segmentWidth = controlWidth / CGFloat(numberOfSegments)
        for segment in 0...segments {
            let title = titleForSegment(at: segment)
            setWidth(segmentWidth, forSegmentAt: segment)
            if let t = title {
                let titleSize = t.size(withAttributes: fontAttributes)
                let offset = (segmentWidth - titleSize.width) / 2 - margin
                self.setContentOffset(CGSize(width: -offset, height: 0), forSegmentAt: segment)
            }
        }
    }
}

Here's what it looks like:

There are a few caveats:

  • This version sets the segments to all have equal width, which might not be what you want.

  • I used a fixed left margin of 10px because it seems unlikely that you'd want to vary that, but you can obviously change it or make it a settable property.

  • Just because you can do this doesn't mean you should. Personally, I don't think it looks great, and it suffers in the usability department too. Users expect segmented control items to be centered, and left-justifying the items will make it harder for them to know where to tap to hit the segment. That seems particularly true for short items like the one labelled "3rd" in the example. It's not terrible, it just seems a little weird.

Original answer:

UIControl (of which UISegmentedControl is a subclass) has a contentHorizontalAlignment property that's supposed to tell the control to align its content a certain way, so the logical thing to do would be to set it like this:

let segmented = UISegmentedControl(items: ["Yes", "No", "Maybe"])
segmented.frame = CGRect(x:75, y:250, width:250, height:35)
segmented.contentHorizontalAlignment = .left

But that doesn't work — you still get the labels centered. If you've got a compelling use case for left-aligned segments, you should send the request to Apple.

One way you could work around this problem is to render your labels into images and then use the images as the segment labels instead of plain strings. Starting from the code in How to convert a UIView to an image , you could easily subclass UISegmentedControl to create images from the item strings.

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