Настройка цветов UISegmentedControl
Кто-нибудь знает способ настроить внешний вид строки на основе UISegmentedControl? Я пытаюсь установить цвет фона ячейки и цвет текста по-разному в зависимости от выбранного состояния элемента.
В качестве альтернативы, вы знаете способ создания UIImages на лету, в который можно включать пользовательские строки? (например, создать UUImage с белым фоном, наложить текст, добавить в сегментированный элемент управления).
Я знаю, что вы можете иметь только строки или изображения в сегментном элементе управления...
Ответы
Ответ 1
UISegmentedControl имеет свойство tintColor - это позволяет вам изменить цвет элемента управления, но не общий "стиль" (округленная, скошенная форма):
segmentedControl.tintColor = [UIColor blueColor];
Что касается создания UIImages на лету, вы можете создать CGContext, сделать любой чертеж, который вам нужен в этом контексте (включая строки), а затем получить UIImage из контекста CGImage:
CGContextRef drawContext = CGBitmapContextCreate(<many parameters>);
//do drawing here
CGImageRef finalImage = CGBitmapContextCreateImage(drawContext);
UIImage *cellImage = [UIImage finalImage];
Обратите внимание, что если вы используете код, подобный UIView.appearance().tintColor = .myColor
(или эквивалент в ObjC), эффект, скорее всего, не произойдет.
Ответ 2
segmentedControl.tintColor = [UIColor colorWithRed:0.61176f green:0.61176f blue:0.61176f alpha:1.0f];
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
Ответ 3
Большинство ответов здесь не отвечают на конкретный вопрос о том, как установить цвет кнопки на основе выбранного состояния, что подразумевает, что для невыбранного состояния требуется другой цвет. Я довольно долго боролся с этим и хотел поделиться своим решением, чтобы другие могли использовать.
В моем примере используется UISegmentedControl
с тремя сегментами. Невыбранный цвет для всех трех должен быть таким же, чтобы придать ему однородный вид. Выбранное состояние для первого и последнего сегмента имеет уникальные цвета.
![enter image description here]()
Проблема заключается в том, что сегментированный элемент управления не гарантируется в том же порядке, чтобы цвета смешались, когда вы выбираете назад и вперед. Дэн опубликовал решение, которое использует теги, но, к сожалению, он больше не гарантированно работает для iOS 6 и выше.
Большая часть этого кода взята из этого сообщения. Я немного изменил его, чтобы иметь уникальные выбранные цвета.
Что заставляет работать сортировка, но обратите внимание на эти две важные строки для установки выбранного цвета:
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 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];
, когда что-то изменится.
Ответ 4
Все, что вам нужно сделать, это:
// 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]];
Ответ 5
Лучшим способом, который я нашел для этого, является установка различных атрибутов для разных 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];
Ответ 6
Вот пример кода, который работает с 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])];
}
}
}
Ответ 7
Цвет шрифта 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)
Ответ 8
Я смог сделать это через Interface Builder в XCode 6. Прикрепленное свойство tint:
![enter image description here]()
Ответ 9
Я хотел сделать что-то похожее - установить цвет фона выбранного сегмента на один цвет, в то время как "контур" остальных сегментов был другого цвета.
В значительной степени заимствуя из ответа Portland Runner, идея состоит в том, чтобы создать подкласс 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]];
}
}
}
Ответ 10
Начиная с iOS13, вы больше не сможете изменять цвет оттенка контроллера сегмента. Необходимо использовать selectedSegmentTintColor, если цвет должен быть настроен. self.yourSegmentControl.selectedSegmentTintColor = UIColor (красный: 240,0/255,0, зеленый: 183,0/255,0, синий: 0,0/255,0, альфа: 1,0)
Ответ 11
Решение раскадровки
Xcode 11
Выберите элемент управления, и теперь доступны несколько вариантов цвета. Если вам нужно дальнейшее уточнение - проверьте пользовательские атрибуты времени выполнения.
![image2]()
![image1]()