22

Is there anyone who can teach me how to show an UISegmentedControl object in vertical direction, instead of in horizontal direction?

xeron
  • 255
  • 1
  • 2
  • 9

5 Answers5

29

You can always modify the transform on the segmented control.

segmentedControl.transform = CGAffineTransformMakeRotation(M_PI / 2.0);

Ben Gottlieb
  • 85,404
  • 22
  • 176
  • 172
  • +1 for answering the question :). I do wonder about the usability of a rotated segmented control. – RedBlueThing Aug 16 '10 at 06:23
  • 1
    Yeah, I wasn't passing judgement on whether it was a good idea or not ;-) – Ben Gottlieb Aug 16 '10 at 13:09
  • 1
    @ben-gottlieb An admirable quality :) – RedBlueThing Aug 17 '10 at 02:04
  • This is pretty old but I came across it and was wondering why use `M_PI / 2.0` instead of `M_PI_2`? – BFeher Dec 18 '14 at 07:16
  • This is old :) but the usability can be quite good if the control is customized to look appropriate for the vertical layout. My use case is a vertical menu bar with tabs. `UISegmentedControl` is perfect for that as it tracks selected/deselected states and allows only one (or none) selection at a time. – SaltyNuts Oct 15 '15 at 15:07
23

+1 for Ben's answer, although rotating the segmented control also rotates the text inside. Never fear! We just have to rotate the inside labels, like so:

    NSArray *arr = [segmentedControl subviews];
    for (int i = 0; i < [arr count]; i++) {
    UIView *v = (UIView*) [arr objectAtIndex:i];
    NSArray *subarr = [v subviews];
        for (int j = 0; j < [subarr count]; j++) {
            if ([[subarr objectAtIndex:j] isKindOfClass:[UILabel class]]) {
                UILabel *l = (UILabel*) [subarr objectAtIndex:j];
                l.transform = CGAffineTransformMakeRotation(- M_PI / 2.0); //do the reverse of what Ben did
            }
        }
    }

Swift 2 version:

for view in segmentedControl.subviews {
    for subview in view.subviews {
        if subview.isKindOfClass(UILabel) {
            subview.transform = CGAffineTransformMakeRotation(CGFloat(-M_PI / 2.0))
        }
    }
}
Andrew M.
  • 9
  • 1
  • 4
Mirkules
  • 1,709
  • 15
  • 21
  • 1
    This works well for labels, but if your control has images instead, it doesn't work. In that case, I would follow Ben's suggestion, and then just rotate the images in the OSX Preview tool (or Photoshop) instead of trying to rotate the UIImageView in your code. – R.S Apr 18 '13 at 05:32
  • 3
    This code relies on the internal (undocumented) implementation of UISegmentedControl. It is prone to failure whenever Apple changes the implementation of this control. Even a simple change such as the insertion of an extra layer of views between the UILabel instances you're seeking and the top level would break this code. – Arda Mar 07 '16 at 21:08
  • @Arda It might break, but it would take around 10 minutes to invent your own segmented controller that did the same thing if that were the case, so do it and enjoy it. More than likely, you will always be able to find a way to do this if something is changed anyhow. – Sethmr Nov 16 '16 at 19:01
  • @Sethmr Well, I already took the around 10 minutes to invent my own alternative at the time I posted that comment. My warning is for anyone who might want to use the code in the accepted answer. Writing your own version, like you said, takes only 10 minutes. Making an update to an already released app because it breaks with a new iOS release is a much bigger and longer process that most developers should aim to avoid. Just my opinion. – Arda Nov 19 '16 at 02:47
  • It's no longer a theoretical problem! This breaks under iOS 11. – benzado Sep 30 '17 at 03:11
5

This control is horizontal only. From the UISegementedControl documentation:

A UISegmentedControl object is a horizontal control made of multiple segments, each segment functioning as a discrete button. A segmented control affords a compact means to group together a number of controls.

You will have to do this as a custom control.

RedBlueThing
  • 42,006
  • 17
  • 96
  • 122
3

Update of Bens answer for more modern swift versions.

segmentedControl.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi / 2))

Noting the casting of the value to a CGFloat and using the more modern Double.pi ( can be shortened to .pi too.

Adam Ware
  • 1,202
  • 11
  • 17
0

I found the below control in cocoa controls which looks nice. It is a custom control and looks like a subclass of UIControl.

smverticalsegmentedcontrol

But if you ask me, I may try a different approach, I will create a tabelview with a column width (44px) and keep it as a child in the container and may align it to one corner of the container, customize the cells and have my list on that and on tap of each row, load the corresponding content in the details view in your contentview. Not tried it, will try and post the results soon.

anoop4real
  • 7,598
  • 4
  • 53
  • 56