Cocoa Touch: วิธีเปลี่ยนสีขอบและความหนาของ UIView


275

ฉันเห็นในผู้ตรวจสอบว่าฉันสามารถเปลี่ยนสีพื้นหลังได้ แต่ฉันต้องการเปลี่ยนสีและความหนาของเส้นขอบด้วย


คำตอบ:


596

คุณต้องใช้เลเยอร์ของมุมมองเพื่อตั้งค่าคุณสมบัติเส้นขอบ เช่น:

#import <QuartzCore/QuartzCore.h>
...
view.layer.borderColor = [UIColor redColor].CGColor;
view.layer.borderWidth = 3.0f;

คุณต้องเชื่อมโยงกับ QuartzCore.framework เพื่อเข้าถึงฟังก์ชั่นนี้


มีวิธีการตั้งค่าความกว้าง / สีที่แตกต่างกันสำหรับทุกด้านหรือไม่?
lluismontero

2
@lluismontero ฉันเกรงว่าคุณจะต้องทำ UIView ที่กำหนดเองกับ drawRect: วิธีการที่
วลาดิเมีย

1
ถ้าฉันทำสิ่งนี้และบนมุมมองนี้ฉันมีภาพเคลื่อนไหวเช่น UINavigationController ที่เป็นโมฆะฉันเห็นว่ามีข้อบกพร่องมากมายเกิดขึ้นมันยากที่จะอธิบาย หากฉันปิดการใช้งานเส้นขอบทุกอย่างกลับเป็นปกติ
Nicu Surdu

5
แค่หัวขึ้นเพื่อคนอื่น Xcode แนะนำการเชื่อมโยง UIColor กับ CGColorRef __bridge CGColorRefดังนี้ สิ่งนี้ใช้ไม่ได้ มันจะต้องมีการ[UIColor blackColor].CGColorกล่าวถึงในคำตอบ
GoodSp33d

6
#import <QuartzCore/QuartzCore.h>ไม่จำเป็นอีกต่อไป
ความหมายมีความสำคัญ

43

อัปเดต Xcode 6

ตั้งแต่เวอร์ชั่นใหม่ล่าสุดของ Xcode มีวิธีแก้ปัญหาที่ดีกว่านี้:

ด้วย@IBInspectableคุณสามารถตั้งค่าแอตทริบิวต์โดยตรงจากภายในAttributes Inspector

My Custom View @IBInspectable แอตทริบิวต์

ชุดนี้User Defined Runtime Attributesสำหรับคุณ:

ป้อนคำอธิบายรูปภาพที่นี่

มีสองวิธีในการตั้งค่านี้:

ตัวเลือก 1 (พร้อมอัปเดตสดในกระดานเรื่องราว)

  1. MyCustomViewสร้าง
  2. UIViewสืบทอดจากนี้
  3. ตั้งค่า@IBDesignable(ทำให้การอัปเดตดูเป็นแบบสด) *
  4. ตั้งค่าคุณสมบัติแอททริบิวต์ของคุณ (เส้นขอบ ฯลฯ ) ด้วย @IBInspectable
  5. เปลี่ยน Views Class ของคุณเป็น MyCustomView
  6. แก้ไขในแผงคุณสมบัติและดูการเปลี่ยนแปลงในสตอรี่บอร์ด :)

`

@IBDesignable
class MyCustomView: UIView {
    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }
    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    @IBInspectable var borderColor: UIColor? {
        didSet {
            layer.borderColor = borderColor?.CGColor
        }
    }
}

* @IBDesignableใช้ได้เฉพาะเมื่อตั้งค่าเมื่อเริ่มต้นclass MyCustomView

ตัวเลือก 2 (ไม่ทำงานตั้งแต่ Swift 1.2 ดูความคิดเห็น)

ขยายคลาส UIView ของคุณ:

extension UIView {
    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }
    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    @IBInspectable var borderColor: UIColor? {
        didSet {
            layer.borderColor = borderColor?.CGColor
        }
    }
}

ด้วยวิธีนี้มุมมองเริ่มต้นของคุณจะมีช่องพิเศษที่สามารถแก้ไขได้Attributes Inspectorเสมอ ข้อดีอีกอย่างคือคุณไม่ต้องเปลี่ยนคลาสเป็นMycustomViewทุกครั้ง อย่างไรก็ตามข้อเสียเปรียบประการหนึ่งคือคุณจะเห็นการเปลี่ยนแปลงของคุณเมื่อคุณเรียกใช้แอป


1
ส่วนขยายของคุณไม่ทำงานใน Xcode เวอร์ชันล่าสุด ณ วันนี้
Edgar Aroutiounian

1
ฉันจะยืนยัน @EdgarAroutiounian เพียงเพื่อบอกว่าใน Swift 1.2 วิธีที่สองไม่สามารถใช้งานได้อีกต่อไป
Sergey Grischyov

แล้ว Objective-C ล่ะ?
Nik Kov

ตรวจสอบคำตอบของ spencery2เพิ่มเติมด้านล่างเขาใช้เวลาเขียนใน Objective-C:
MMachinegun

อัปเดตส่วนขยายเพื่อไม่เก็บค่าและใช้ set (value) {} และรับ {} เพื่อเข้าถึงเลเยอร์โดยตรงมันใช้งานได้แล้ว
LightningStryk

17

นอกจากนี้คุณยังสามารถสร้างเส้นขอบด้วยสีที่คุณต้องการ ..

view.layer.borderColor = [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0].CGColor;

* r, g, b คือค่าระหว่าง 0 ถึง 255


6
มันเป็นที่น่าสังเกตว่าr, gและbอาจจะลอย; ตัวหารควรเป็นแบบลอยตัว: r / 255.0.

ไม่ไวยากรณ์ C ไม่ได้เป็นอย่างที่คุณพูด r, g และ b สามารถเป็น int ได้เนื่องจากโปรโมชั่น C (และ objC IS C) จะใช้ค่า r = 128 เป็นสองเท่าเมื่อทำ: r / 255.0 โดยวิธีที่คุณได้รับสองครั้งและเสียงดังกราวจะโยนไปที่ CGFloat
ingconti

10

เพิ่ม @IBInspectables ต่อไปนี้ในส่วนขยาย UIView

extension UIView {

  @IBInspectable var borderWidth: CGFloat {
    get {
      return layer.borderWidth
    }
    set(newValue) {
      layer.borderWidth = newValue
    }
  }

  @IBInspectable var borderColor: UIColor? {
    get {
      if let color = layer.borderColor {
        return UIColor(CGColor: color)
      }
      return nil
    }
    set(newValue) {
      layer.borderColor = newValue?.CGColor
    }
  }
}

จากนั้นคุณควรจะสามารถตั้งค่า borderColor และ borderWidth ได้โดยตรงจากตัวตรวจสอบคุณสมบัติ ดูภาพที่แนบมา

คุณสมบัติของผู้ตรวจสอบ


8

เมื่อฉันใช้โซลูชัน CALayer ของ Vladimir และที่ด้านบนของมุมมองฉันมีภาพเคลื่อนไหวเช่นการเลิก UINavigationController แบบโมดัลฉันเห็นข้อบกพร่องมากมายที่เกิดขึ้นและมีปัญหาด้านประสิทธิภาพการวาด

ดังนั้นอีกวิธีหนึ่งในการบรรลุเป้าหมายนี้ แต่หากไม่มีข้อบกพร่องและการสูญเสียประสิทธิภาพคือการสร้าง UIView ที่กำหนดเองและใช้drawRectข้อความเช่นนั้น:

- (void)drawRect:(CGRect)rect
{
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(contextRef, 1);
    CGContextSetRGBStrokeColor(contextRef, 255.0, 255.0, 255.0, 1.0);
    CGContextStrokeRect(contextRef, rect);    
}

@Krish คุณเก็บสีไว้ในตัวแปรและเมื่อคุณต้องการเปลี่ยนสีเส้นขอบคุณจะเปลี่ยนค่าตัวแปรและเรียกใช้setNeedsDisplayในมุมมอง นี้จะบังคับวาดของ UIView drawRectและโดยปริยายจะโทรอีกครั้ง ยังไม่ผ่านการทดสอบดังนั้น ...
Nicu Surdu



4

ฉันจะไม่แนะนำให้เอาชนะ drawRect เนื่องจากเป็นสาเหตุให้เกิดการโจมตี

แต่ฉันจะแก้ไขคุณสมบัติของคลาสเหมือนด้านล่าง (ใน uiview ที่คุณกำหนดเอง):

  - (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
      self.layer.borderWidth = 2.f;
      self.layer.borderColor = [UIColor redColor].CGColor;
    }
  return self;

ฉันไม่เห็นความผิดพลาดใด ๆ เมื่อทำตามวิธีข้างต้น - ไม่แน่ใจว่าทำไมการใส่ initWithFrame จึงหยุด ;-)


3

ฉันต้องการเพิ่มสิ่งนี้ในคำตอบของ @ marczking ( ตัวเลือก 1 ) เป็นความคิดเห็น แต่สถานะต่ำสุดของฉันใน StackOverflow ป้องกันไม่ให้

ฉันตอบคำถามของ @ marczking กับ Objective C. ทำงานเหมือนมีเสน่ห์ขอบคุณ @marczking!

UIView + Border.h:

#import <UIKit/UIKit.h>

IB_DESIGNABLE
@interface UIView (Border)

-(void)setBorderColor:(UIColor *)color;
-(void)setBorderWidth:(CGFloat)width;
-(void)setCornerRadius:(CGFloat)radius;

@end

UIView + Border.m:

#import "UIView+Border.h"

@implementation UIView (Border)
// Note: cannot use synthesize in a Category

-(void)setBorderColor:(UIColor *)color
{
    self.layer.borderColor = color.CGColor;
}

-(void)setBorderWidth:(CGFloat)width
{
    self.layer.borderWidth = width;
}

-(void)setCornerRadius:(CGFloat)radius
{
    self.layer.cornerRadius = radius;
    self.layer.masksToBounds = radius > 0;
}

@end

2

@IBInspectable ใช้งานได้กับฉันใน iOS 9, Swift 2.0

extension UIView {

@IBInspectable var borderWidth: CGFloat {
get {
        return layer.borderWidth
    }
    set(newValue) {
        layer.borderWidth = newValue
    }
}

@IBInspectable var cornerRadius: CGFloat {
    get {
        return layer.cornerRadius
    }
    set(newValue) {
        layer.cornerRadius = newValue
    }
}

@IBInspectable var borderColor: UIColor? {
    get {
        if let color = layer.borderColor {
            return UIColor(CGColor: color)
        }
        return nil
    }
    set(newValue) {
        layer.borderColor = newValue?.CGColor
    }
}

1

หากคุณไม่ต้องการแก้ไขเลเยอร์ของ UIView คุณสามารถฝังมุมมองภายในมุมมองอื่นได้เสมอ มุมมองพาเรนต์จะตั้งค่าสีพื้นหลังเป็นสีเส้นขอบ มันก็จะใหญ่ขึ้นเล็กน้อยขึ้นอยู่กับว่าคุณต้องการให้เส้นขอบกว้างเท่าไหร่

แน่นอนว่าจะได้ผลก็ต่อเมื่อมุมมองของคุณไม่โปร่งใสและคุณต้องการสีเส้นขอบเดียว OP ต้องการเส้นขอบในมุมมองของตัวเอง แต่นี่อาจเป็นทางเลือกที่ทำงานได้


0

หากคุณต้องการเพิ่มขอบที่แตกต่างกันในด้านที่แตกต่างกันอาจจะเพิ่มมุมมองย่อยที่มีสไตล์เฉพาะเป็นวิธีที่ง่ายต่อการเกิดขึ้น


0

สีเส้นขอบของรายการในรวดเร็ว 4.2:

let cell = tableView.dequeueReusableCell(withIdentifier: "Cell_lastOrderId") as! Cell_lastOrder
cell.layer.borderWidth = 1
cell.layer.borderColor = UIColor.white.cgColor
cell.layer.cornerRadius = 10
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.