Có thể thay đổi màu nền UIButtons không?


105

Cái này làm tôi bí.

Có thể thay đổi màu nền của UIButton trong Cocoa cho iPhone không. Tôi đã thử thiết lập màu nền nhưng nó chỉ thay đổi các góc. setBackgroundColor:dường như là phương pháp duy nhất có sẵn cho những thứ như vậy.

[random setBackgroundColor:[UIColor blueColor]];
[random.titleLabel setBackgroundColor:[UIColor blueColor]];

bạn có thể sửa hình ảnh, hoặc loại bỏ nó? kthx;)
stigi

o-0 hmmmm ....., hình ảnh vẫn ổn nhưng bây giờ nó sẽ không hiển thị nữa. Vừa mới xóa nó
dubbeat


Tôi giải quyết vấn đề này trong bài đăng previos của mình, vui lòng kiểm tra liên kết [Tự động thay đổi đường viền hoặc backgraound của UIButton] [1] [1]: stackoverflow.com/questions/9733213/…
IMMORTAL

tốt hướng dẫn và mẫu mã tìm thấy ở đây cimgf.com/2010/01/28/...
Shamsudheen TK

Câu trả lời:


160

Điều này có thể được thực hiện theo chương trình bằng cách tạo một bản sao:

loginButton = [UIButton buttonWithType:UIButtonTypeCustom];
[loginButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
loginButton.backgroundColor = [UIColor whiteColor];
loginButton.layer.borderColor = [UIColor blackColor].CGColor;
loginButton.layer.borderWidth = 0.5f;
loginButton.layer.cornerRadius = 10.0f;

chỉnh sửa: tất nhiên, bạn phải #import <QuartzCore/QuartzCore.h>

chỉnh sửa: đối với tất cả người đọc mới, bạn cũng nên xem xét một vài tùy chọn được thêm vào như "một khả năng khác". để bạn xem xét.

Vì đây là một câu trả lời cũ, tôi thực sự khuyên bạn nên đọc các nhận xét để khắc phục sự cố


Đây là những gì OP đang tìm kiếm.
Steven

4
ngọt! Trong số tất cả các solns tôi tìm thấy đây là một trong những tôi đã đi cùng. Như một điểm cần làm rõ, tạo một 'bản sao' có nghĩa là sử dụng Quartz để vẽ một hình chữ nhật tròn trong một nút tùy chỉnh, thay vì sử dụng nút kiểu RoundedRect. Lúc đầu, tôi nghĩ nó có nghĩa là bằng cách nào đó tạo ra một bản sao của một hình chữ nhật tròn với một màu khác để mô phỏng việc thay đổi màu bg.
daver

1
Hoạt động hoàn hảo, câu trả lời tốt nhất cho OP. Cám ơn vì đã chia sẻ.
Bram

@daver: Câu trả lời này rất phổ biến nên chắc chắn tôi đang thiếu sót. Làm thế nào người ta có thể thay đổi màu nền tùy theo trạng thái? Có lẽ người ta phải thay đổi màu nền một cách rõ ràng mỗi khi trạng thái thay đổi. Nút của tôi bị tắt khi nhấn cho đến khi dịch vụ web phản hồi. Tôi có phải thay đổi thành màu tô sáng khi nhấn và có bộ hẹn giờ thay đổi thành màu bị tắt trong khi chờ phản hồi của ws không? Nếu tôi thiếu điểm ai đó có thể vui lòng giải thích. Cảm ơn Polly.
Polly

1
@Polly: Xin lỗi đã không thấy nhận xét của bạn sớm hơn, nhưng nếu bạn vẫn quan tâm thì đây là những gì tôi đã làm: lớp con UIButton và ghi đè drawRect: để vẽ hình chữ nhật tròn bằng cách sử dụng một số UIBezierPath. Sau khi vẽ, tô nó với một gradient bằng cách sử dụng CGGradientCreateWithColorComponents (). Một trong các args của hàm này là mảng float gồm 4 phần tử (tương ứng với R, G, B, & alpha). Tôi đã xác định 2 mảng màu, một mảng cho mỗi trạng thái và chọn mảng màu thích hợp trong drawRect dựa trên trạng thái nút.
daver

59

Tôi có một cách tiếp cận khác,

[btFind setTitle:NSLocalizedString(@"Find", @"") forState:UIControlStateNormal];    
[btFind setBackgroundImage:[CommonUIUtility imageFromColor:[UIColor cyanColor]] 
        forState:UIControlStateNormal];
btFind.layer.cornerRadius = 8.0;
btFind.layer.masksToBounds = YES;
btFind.layer.borderColor = [UIColor lightGrayColor].CGColor;
btFind.layer.borderWidth = 1;

Từ CommonUIUtility,

+ (UIImage *) imageFromColor:(UIColor *)color {
    CGRect rect = CGRectMake(0, 0, 1, 1);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [color CGColor]);
    //  [[UIColor colorWithRed:222./255 green:227./255 blue: 229./255 alpha:1] CGColor]) ;
    CGContextFillRect(context, rect);
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

Đừng quên #import <QuartzCore/QuartzCore.h>


2
Tốt lắm. Tôi thấy tôi phải thêm mộtbtFind.layer.borderWidth = 1;
Phòng thủ

Tôi thích giải pháp này, nhưng hiện tại tôi không thể sử dụng nó. Tôi gặp lỗi vì không tìm thấy "CommonUIUtility". Google chỉ cung cấp cho tôi nội dung nhật thực, nhưng tôi đoán nó phải có trong QuartzCore? Bất kỳ ý tưởng?
Stephan

Không, đó là lớp do người dùng xác định để thực hiện các nội dung giao diện người dùng phổ biến trong ứng dụng. Bạn viết phương thức imageFromColor trong lớp của riêng bạn.
karim

1
Có mùi giống như một phương pháp loại trên UIButton: setBackgroundColor:(UIColor *) forState:(UIControlState).
EthanB

3
Thật ngớ ngẩn khi chúng tôi đang sử dụng iOS 7 và đây VẪN là cách rõ ràng nhất để thêm màu nền
dmur

32

Tôi giả sử bạn đang nói về UIButton với UIButtonTypeRoundedRect? Bạn không thể thay đổi màu nền của nó. Khi bạn thử thay đổi màu nền của nó, bạn muốn thay đổi màu của hình chữ nhật mà nút được vẽ (thường rõ ràng). Vì vậy, có hai cách để đi. Hoặc bạn phân lớp UIButton và ghi đè lên -drawRect:phương thức của nó hoặc bạn tạo hình ảnh cho các trạng thái nút khác nhau (điều này hoàn toàn tốt để làm).

Nếu bạn đặt hình ảnh nền trong Trình tạo giao diện, bạn nên lưu ý rằng IB không hỗ trợ thiết lập hình ảnh cho tất cả các trạng thái mà nút có thể có, vì vậy tôi khuyên bạn nên đặt hình ảnh trong mã như sau:

UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setBackgroundImage:[UIImage imageNamed:@"normal.png"] forState:UIControlStateNormal];
[myButton setBackgroundImage:[UIImage imageNamed:@"disabled.png"] forState:UIControlStateDisabled];
[myButton setBackgroundImage:[UIImage imageNamed:@"selected.png"] forState:UIControlStateSelected];
[myButton setBackgroundImage:[UIImage imageNamed:@"higligted.png"] forState:UIControlStateHighlighted];
[myButton setBackgroundImage:[UIImage imageNamed:@"highlighted+selected.png"] forState:(UIControlStateHighlighted | UIControlStateSelected)];

Dòng cuối cùng cho biết cách đặt hình ảnh cho trạng thái đã chọn & đánh dấu (đó là điều IB không thể đặt). Bạn không cần các hình ảnh đã chọn (dòng 4 & 6) nếu nút của bạn không cần trạng thái đã chọn.


Cám ơn vì sự giải thích. Chỉ là một câu hỏi nhanh. Nếu tôi đang ghi đè phương thức drawrect, tôi đoán điều đó sẽ liên quan đến việc tôi sử dụng thư viện bản vẽ? Một cái gì đó một mình những dòng lập trình vẽ một hình chữ nhật tròn và tô nó bằng màu?
dubbeat

2
Tôi chỉ cần làm một truy vấn google viết tắt của "iphone drawRect góc tròn" và thấy điều này: iphonedevelopment.blogspot.com/2008/11/... Kiểm tra phương pháp drawRect cho một ví dụ làm thế nào để vẽ một rect tròn. Bạn có thể sử dụng CGContextSetFillColorWithColorCGContextFillPathđiền vào đường dẫn được vẽ bởi CGContextAddArcToPoint.
stigi,

2
+50 để chỉ ra tiềm năng tạo mặt nạ bit cho các trạng thái điều khiển, tức là: forState:(UIControlStateHighlighted | UIControlStateSelected)Chúc mừng.
NSTJ

28

Khả năng khác:

  1. Tạo UIButton trong Trình tạo giao diện.
  2. Cung cấp cho nó một loại 'Tùy chỉnh'
  3. Bây giờ, trong IB có thể thay đổi màu nền

Tuy nhiên, nút có hình vuông, và đó không phải là điều chúng tôi muốn. Tạo IBOutlet có tham chiếu đến nút này và thêm phần sau vào phương thức viewDidLoad:

[buttonOutlet.layer setCornerRadius:7.0f];
[buttonOutlet.layer setClipToBounds:YES];

Đừng quên nhập QuartzCore.h


7
Hoàn hảo, cảm ơn bạn! Tôi không chắc có phải do phiên bản iOS mà tôi đang sử dụng (5.1) hay không mà setClipToBounds không khả dụng. Thay vào đó, tôi sử dụng buttonOutlet.layer.masksToBounds = TRUE;
iforce2d

Khi tôi thêm mã này, nó sẽ hiển thị một hình chữ nhật tròn, nhưng khi tôi nhấp vào nó, nút không đảo ngược đánh dấu. Điều gì đang xảy ra?
Sẽ

Vấn đề với cách tiếp cận này là bạn không thể đặt màu nền cho trạng thái được đánh dấu của nút.
ch3rryc0ke

17

Lớp con UIButton và ghi đè các phương thức setHighlighted và setSelected

-(void) setHighlighted:(BOOL)highlighted {

  if(highlighted) {
    self.backgroundColor = [self.mainColor darkerShade];
  } else {
    self.backgroundColor = self.mainColor;
  }
  [super setHighlighted:highlighted];
}

-(void) setSelected:(BOOL)selected {

  if(selected) {
    self.backgroundColor = [self.mainColor darkerShade];
  } else {
    self.backgroundColor = self.mainColor;
  }
  [super setSelected:selected];
}

Phương thức darkShade của tôi nằm trong danh mục UIColor như thế này

-(UIColor*) darkerShade {

  float red, green, blue, alpha;
  [self getRed:&red green:&green blue:&blue alpha:&alpha];

  double multiplier = 0.8f;
  return [UIColor colorWithRed:red * multiplier green:green * multiplier blue:blue*multiplier alpha:alpha];
}

7

UIButton màu

Nếu bạn không muốn sử dụng hình ảnh và muốn nó trông giống hệt như kiểu Rounded Rect, hãy thử cách này. Chỉ cần đặt một UIView trên UIButton, với khung giống hệt và mặt nạ tự động thay đổi kích thước, đặt alpha thành 0,3 và đặt nền thành màu. Sau đó, sử dụng đoạn mã bên dưới để cắt các cạnh tròn ra khỏi chế độ xem lớp phủ màu. Ngoài ra, hãy bỏ chọn hộp kiểm 'Người dùng đã bật tương tác' trong IB trên UIView để cho phép các sự kiện cảm ứng chuyển xuống UIButton bên dưới.

Một tác dụng phụ là văn bản của bạn cũng sẽ bị tô màu.

#import <QuartzCore/QuartzCore.h>

colorizeOverlayView.layer.cornerRadius = 10.0f;
colorizeOverlayView.layer.masksToBounds = YES;

7

Một khả năng khác (imho tốt nhất và đẹp nhất):

Tạo một UISegmentedControl với 2 phân đoạn bằng màu nền bắt buộc trong Trình tạo giao diện. Đặt loại thành 'bar'. Sau đó, thay đổi nó thành chỉ có một phân đoạn. Trình tạo giao diện không chấp nhận một phân đoạn, vì vậy bạn phải làm điều đó theo chương trình.

Do đó, hãy tạo IBOutlet cho nút này và thêm nó vào viewDidLoad của chế độ xem của bạn:

[segmentedButton removeSegmentAtIndex:1 animated:NO];

Bây giờ bạn có một nút màu bóng đẹp với màu nền được chỉ định. Đối với các hành động, hãy sử dụng sự kiện 'giá trị đã thay đổi'.

(Tôi đã tìm thấy điều này trên http://chris-software.com/index.php/2009/05/13/creating-a-nice-glass-buttons/ ). Cảm ơn Chris!


5

Tôi 99% khẳng định rằng bạn không thể chỉ đi và thay đổi màu nền của UIButton. Thay vào đó, bạn phải tự mình thay đổi hình ảnh nền mà tôi nghĩ là một điều khó khăn. Tôi ngạc nhiên rằng tôi đã phải làm điều này.

Nếu tôi sai hoặc nếu có cách nào tốt hơn mà không cần phải đặt hình nền, vui lòng cho tôi biết

[random setBackgroundImage:[UIImage imageNamed:@"toggleoff.png"] forState:UIControlStateNormal];
    [random setTitleColor:[UIColor darkTextColor] forState:UIControlStateNormal];


[random setBackgroundImage:[UIImage imageNamed:@"toggleon.png"] forState:UIControlStateNormal];
    [random setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];

5
Bạn hoàn toàn đúng. Đó là một nỗi đau, và việc gì đó sẽ mất vài phút để làm thay vì tạo ra những hình ảnh phức tạp. Thêm vào đó, nếu nút của bạn tròn, nó thậm chí còn khiến bạn khó làm hơn ... Thật là đau.
Henley Chiu

2

Theo đề xuất @EthanB và @karim tạo ra một hình chữ nhật lấp đầy phía sau, tôi vừa tạo một danh mục cho UIButton để đạt được điều này.

Chỉ cần thả mã Danh mục: https://github.com/zmonteca/UIButton-PLColor

Sử dụng:

[button setBackgroundColor:uiTextColor forState:UIControlStateDisabled];

Các forStates tùy chọn để sử dụng:

UIControlStateNormal
UIControlStateHighlighted
UIControlStateDisabled
UIControlStateSelected

2

Bạn cũng có thể thêm CALayer vào nút - bạn có thể làm nhiều việc với những thứ này bao gồm cả lớp phủ màu, ví dụ này sử dụng một lớp màu trơn, bạn cũng có thể dễ dàng chuyển màu. Hãy lưu ý mặc dù các lớp được thêm vào sẽ che khuất những lớp bên dưới

+(void)makeButtonColored:(UIButton*)button color1:(UIColor*) color
{

    CALayer *layer = button.layer;
    layer.cornerRadius = 8.0f;
    layer.masksToBounds = YES;
    layer.borderWidth = 4.0f;
    layer.opacity = .3;//
    layer.borderColor = [UIColor colorWithWhite:0.4f alpha:0.2f].CGColor;

    CAGradientLayer *colorLayer = [CAGradientLayer layer];
    colorLayer.cornerRadius = 8.0f;
    colorLayer.frame = button.layer.bounds;
    //set gradient colors
    colorLayer.colors = [NSArray arrayWithObjects:
                         (id) color.CGColor,
                         (id) color.CGColor,
                         nil];

    //set gradient locations
    colorLayer.locations = [NSArray arrayWithObjects:
                            [NSNumber numberWithFloat:0.0f],
                            [NSNumber numberWithFloat:1.0f],
                            nil];


    [button.layer addSublayer:colorLayer];

}

Xuất sắc!!!!!! Nhưng không thể được gọi nhiều lần với cùng một nút. Có thể, nhưng các lớp mới được thêm vào nhiều lần.
Valeriy Van

@StanJames: Các chỉnh sửa mã nên được gợi ý bằng nhận xét (hoặc, nếu thích hợp, bằng câu trả lời của riêng bạn).
mafso

1

thêm mục tiêu thứ hai cho UIButtonfor UIControlEventTouchedvà thay đổi UIButtonmàu nền. Sau đó, thay đổi nó trở lại trong UIControlEventTouchUpInsidemục tiêu;


1

Đối với các nút chuyên nghiệp và đẹp mắt, bạn có thể kiểm tra thành phần nút tùy chỉnh này . Bạn có thể sử dụng nó trực tiếp trong các dạng xem và bảng của mình hoặc sửa đổi mã nguồn để làm cho nó đáp ứng nhu cầu của bạn. Hi vọng điêu nay co ich.


1

Điều này không thanh lịch như UIButton phân loại phụ, tuy nhiên nếu bạn chỉ muốn một cái gì đó nhanh chóng - những gì tôi đã làm là tạo nút tùy chỉnh, sau đó tạo hình ảnh 1px x 1px với màu sắc mà tôi muốn nút và đặt nền của nút tới hình ảnh đó cho trạng thái được đánh dấu - phù hợp với nhu cầu của tôi.


1

Tôi biết điều này đã được hỏi cách đây rất lâu và bây giờ có một UIButtonTypeSystem mới. Nhưng các câu hỏi mới hơn đang được đánh dấu là bản sao của câu hỏi này, vì vậy đây là câu trả lời mới hơn của tôi trong ngữ cảnh của nút hệ thống iOS 7, hãy sử dụng thuộc .tintColortính.

let button = UIButton(type: .System)
button.setTitle("My Button", forState: .Normal)
button.tintColor = .redColor()

0

[myButton setBackgroundColor:[UIColor blueColor]]; [myButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];

Có thể thay đổi theo cách này hoặc chuyển sang Storyboard và thay đổi nền trên các tùy chọn ở phía bên phải.


0

Swift 3:

        static func imageFromColor(color: UIColor, width: CGFloat, height: CGFloat) -> UIImage {
            let rect = CGRect(x: 0, y: 0, width: width, height: height)
            UIGraphicsBeginImageContext(rect.size)
            let context = UIGraphicsGetCurrentContext()!
            context.setFillColor(color.cgColor)
            context.fill(rect)
            let img = UIGraphicsGetImageFromCurrentImageContext()!
            UIGraphicsEndImageContext()
            return img
        }

        let button = UIButton(type: .system)
        let image = imageFromColor(color: .red, width: 
        button.frame.size.width, height: button.frame.size.height)
        button.setBackgroundImage(image, for: .normal)

Đây sẽ là một câu trả lời hữu ích hơn nhiều nếu bạn nói cách gọi hoặc sử dụng mã bạn đã đặt ở đó. Nó có đi vào tiện ích mở rộng UIButton không?
Michael Dautermann
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.