web-dev-qa-db-ja.com

UISegmentedControlの色のカスタマイズ

文字列ベースのUISegmentedControlの外観をカスタマイズする方法を誰かが知っていますか?アイテムの選択状態に応じて、セルの背景色とテキストの色を別々に設定しようとしています。

または、カスタム文字列を含めるUIImageをその場で作成する方法を知っていますか? (たとえば、白い背景でUUImageを作成し、テキストをオーバーレイし、セグメント化されたコントロールに追加します)。

セグメント化されたコントロールには文字列または画像しか含めることができないことを知っています...

25
nicktmro

UISegmentedControlにはtintColorプロパティがあります。これにより、コントロールの色を変更できますが、一般的な「スタイル」(丸みを帯びたベベル形状)は変更できません。

_segmentedControl.tintColor = [UIColor blueColor];
_

オンザフライでUIImageを作成する場合と同様に、CGContextを作成し、そのコンテキスト(文字列を含む)で必要な描画をすべて実行してから、コンテキストのCGImageからUIImageを取得できます。

_CGContextRef drawContext = CGBitmapContextCreate(<many parameters>);
//do drawing here
CGImageRef finalImage = CGBitmapContextCreateImage(drawContext);
UIImage *cellImage = [UIImage finalImage];
_

UIView.appearance().tintColor = .myColor(またはObjCと同等)のようなコードを使用する場合、効果はほとんど発生しないことに注意してください。

22
Arclite
segmentedControl.tintColor = [UIColor colorWithRed:0.61176f green:0.61176f  blue:0.61176f  alpha:1.0f];

segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
13
jxdwinter

ここでの答えのほとんどは、選択された状態に基づいてボタンの色を設定する方法の特定の質問に答えていません。つまり、選択されていない状態には別の色が必要です。私はかなり長い間これに苦労し、他の人が使用できるように私のソリューションを共有したいと思いました。

私の例では、3つのセグメントを持つUISegmentedControlを使用しています。 3つすべての選択されていない色は、均一な外観を与えるために同じでなければなりません。最初と最後のセグメントの選択された状態は、一意の色を持っています。

enter image description here

問題は、セグメント化されたコントロールが同じ順序であることが保証されていないため、前後に選択すると色が混ざり合うことです。 Danはタグを使用するソリューションを投稿しましたが、残念ながらiOS 6以降での動作が保証されなくなりました。

このコードのほとんどは この投稿 から取得されます。個性的なセレクトカラーに変更しました。

機能するのは並べ替えですが、選択した色を設定するために次の2つの重要な行に注意してください。

NSInteger selectedIdx = betterSegmentedControl.selectedSegmentIndex;
[[sortedViews objectAtIndex:selectedIdx] setTintColor:[self.segmentColors objectAtIndex:selectedIdx]];

- (void) updateSegmentColors
{
    UIColor *checkColor = [UIColor colorWithRed: 29/255.0 green:166/255.0 blue:47/255.0 alpha:1.0];
    NSArray *segmentColors = [[NSArray alloc] initWithObjects:checkColor, [UIColor blueColor], [UIColor redColor], nil];

    UISegmentedControl *betterSegmentedControl = self.StatusControl;

    // Get number of segments
    NSUInteger numSegments = [betterSegmentedControl.subviews count];

    // Reset segment's color (non selected color)
    for( int i = 0; i < numSegments; i++ ) {
        // reset color
        [[betterSegmentedControl.subviews objectAtIndex:i] setTintColor:nil];
        [[betterSegmentedControl.subviews objectAtIndex:i] setTintColor:[UIColor blueColor]];
    }

    // Sort segments from left to right
    NSArray *sortedViews = [betterSegmentedControl.subviews sortedArrayUsingFunction:compareViewsByOrigin context:NULL];

    // Change color of selected segment
    NSInteger selectedIdx = betterSegmentedControl.selectedSegmentIndex;
    [[sortedViews objectAtIndex:selectedIdx] setTintColor:[self.segmentColors objectAtIndex:selectedIdx]];

    // Remove all original segments from the control
    for (id view in betterSegmentedControl.subviews) {
        [view removeFromSuperview];
    }

    // Append sorted and colored segments to the control
    for (id view in sortedViews) {
        [betterSegmentedControl addSubview:view];
    }
}


NSInteger static compareViewsByOrigin(id sp1, id sp2, void *context)
{
    // UISegmentedControl segments use UISegment objects (private API). But we can safely cast them to UIView objects.
    float v1 = ((UIView *)sp1).frame.Origin.x;
    float v2 = ((UIView *)sp2).frame.Origin.x;
    if (v1 < v2)
        return NSOrderedAscending;
    else if (v1 > v2)
        return NSOrderedDescending;
    else
        return NSOrderedSame;
}

これらのセグメント化されたコントロールをテーブルビューにロードし、ロード時(ストレージからの既存の状態)に、およびユーザーが選択を変更したときにコードを実行する必要があるため、コードを独自のメソッドに配置しました。今、私は[Self updateSegmentColors];何かが変わったとき。

11
Portland Runner

あなたがしなければならないすべては:

// Get an array of the subviews of a UISegmentedControl, for example myUISegmentedControl:

NSArray *arri = [myUISegmentedControl subviews];

// Change the tintColor of each subview within the array:

[[arri objectAtIndex:0] setTintColor:[UIColor redColor]];

[[arri objectAtIndex:1] setTintColor:[UIColor greenColor]];

このようなことをするために私が見つけた最良の方法は、セグメント化されたコントロールのさまざまなUIControlStatesにさまざまな属性を設定することです。

self.segmentedControl.tintColor = [UIColor cb_Grey1Color];
self.segmentedControl.backgroundColor = [UIColor cb_Grey3Color];
NSDictionary *selectedAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                    [UIFont cbGothamBookFontWithSize:13.0], NSFontAttributeName,
                                    [UIColor whiteColor], NSForegroundColorAttributeName,
                                    [UIColor cb_Grey1Color], NSBackgroundColorAttributeName, nil];
[self.segmentedControl setTitleTextAttributes:selectedAttributes forState:UIControlStateSelected];
NSDictionary *unselectedAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                      [UIFont cbGothamBookFontWithSize:13.0], NSFontAttributeName,
                                      [UIColor cb_Grey2Color], NSForegroundColorAttributeName,
                                      [UIColor cb_Grey3Color], NSBackgroundColorAttributeName, nil];
[self.segmentedControl setTitleTextAttributes:unselectedAttributes forState:UIControlStateNormal];
7
Colin

IOS13以降、セグメントコントローラのティントカラーを変更することはできなくなります。色をカスタマイズする必要がある場合は、selectedSegmentTintColorを使用する必要があります。 self.yourSegmentControl.selectedSegmentTintColor = UIColor(red:240.0/255.0、green:183.0/255.0、blue:0.0/255.0、alpha:1.0)

2
vinny

IOS9で動作するサンプルコードを次に示しますが、これはハックであり、以降のバージョンでは動作しない可能性があります。

UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@"Title1", @"Title2"]];
for (id segment in [segmentedControl subviews])
{
    for (id view in [segment subviews])
    {
        NSString *desc = [view description];
        if ([desc containsString:@"UISegmentLabel"])
        {
            [segment setTintColor:([desc containsString:@"Title1"] ? [UIColor blueColor] : [UIColor greenColor])];
        }
    }
}
2
david72

フォントの色Swift 3およびSwift 4変更する場合

選択されていないアイテムの場合

 segcntrl.setTitleTextAttributes(titleTextAttributes, for: .normal)

選択したアイテム

  segcntrl.setTitleTextAttributes(titleTextAttributes, for: .selected)



//MARK:- Segment color change
    self.segc.setTitleTextAttributes([NSAttributedStringKey.foregroundColor: 
UIColor.white], for: UIControlState.selected)
    self.segc.setTitleTextAttributes([NSAttributedStringKey.foregroundColor: 
UIColor.white], for: UIControlState.normal)
2
Shakeel Ahmed

同様のことを実現したかった-選択したセグメントの背景色を1つの色に設定し、残りのセグメントの「アウトライン」は別の色にした。

Portland Runner's answer を多用し、UISegmentedControlをサブクラス化し、2つのメソッドをオーバーライドして初期状態のスタイルを設定するとともに、ユーザーが異なるセグメントを選択したときに変更イベントをキャプチャして自動的にスタイルを設定するという考え方です。

- (void)layoutSubviews {
    [super layoutSubviews];
    [self updateSegmentColors];
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesEnded:touches withEvent:event];
    [self updateSegmentColors];
}
- (void)updateSegmentColors {
    NSArray* segments = [self.subviews sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        // UISegmentedControl segments use UISegment objects (private API). But we can safely cast them to UIView objects.
        float v1 = ((UIView *)obj1).frame.Origin.x;
        float v2 = ((UIView *)obj2).frame.Origin.x;
        if (v1 < v2) return NSOrderedAscending;
        else if (v1 > v2) return NSOrderedDescending;
        else return NSOrderedSame;
    }];
    for (int i=0; i<segments.count; i++) {
        if (i == self.selectedSegmentIndex) {
            [segments[i] setTintColor:[UIColor redColor]];
        } else {
            [segments[i] setTintColor:[UIColor grayColor]];
        }
    }
}
1
IMFletcher

XCode 6のInterface Builderを介してそれを行うことができました。添付されているのはtintプロパティです。

enter image description here

1
okysabeni

ストーリーボードソリューション

Xcode 11

コントロールを選択すると、複数のカラーオプションが使用できるようになります。さらに調整が必要な場合は、ユーザー定義のランタイム属性を確認してください。

image2

image1

0
Tommie C.