Cocoa Touch: Bagaimana Cara Mengubah Warna Dan Ketebalan Perbatasan UIView?

Jawaban:

596

Anda perlu menggunakan layer view untuk mengatur properti border. misalnya:

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

Anda juga perlu menautkan dengan QuartzCore.framework untuk mengakses fungsi ini.

Vladimir
sumber
Apakah ada cara untuk mengatur lebar / warna yang berbeda untuk setiap sisi?
lluismontero
2
@lluismontero Saya khawatir Anda harus membuat UIView khusus dengan drawRect: metode untuk itu
Vladimir
1
Jika saya melakukan ini, dan di atas tampilan ini saya memiliki animasi, seperti modal UINavigationController menolak, saya melihat banyak gangguan terjadi, sulit untuk dijelaskan. Jika saya menonaktifkan perbatasan, semuanya akan kembali normal.
Nicu Surdu
5
Hanya kepala untuk orang lain. Xcode menyarankan bridging UIColor ke CGColorRef sebagai __bridge CGColorRef. Ini tidak bekerja. Itu perlu [UIColor blackColor].CGColorseperti yang disebutkan dalam jawaban.
GoodSp33d
6
#import <QuartzCore/QuartzCore.h>tidak lagi dibutuhkan.
maknanya penting
43

Pembaruan Xcode 6

Karena versi terbaru Xcode ada solusi yang lebih baik untuk ini:

Dengan @IBInspectableAnda dapat mengatur Atribut langsung dari dalam yang Attributes Inspector.

My Custom View @IBInspectable Attributes

Ini menentukan User Defined Runtime Attributesuntuk Anda:

masukkan deskripsi gambar di sini

Ada dua pendekatan untuk mengatur ini:

Opsi 1 (dengan pembaruan langsung di Storyboard)

  1. Buat MyCustomView.
  2. Ini mewarisi dari UIView.
  3. Set @IBDesignable(ini membuat Lihat pembaruan hidup). *
  4. Atur Atribut Runtime Anda (perbatasan, dll.) Dengan @IBInspectable
  5. Ubah Kelas Tampilan Anda menjadi MyCustomView
  6. Edit di Panel Atribut dan lihat perubahan di Storyboard :)

`

@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
        }
    }
}

* @IBDesignableHanya berfungsi bila diset pada awalclass MyCustomView

Opsi 2 (tidak berfungsi sejak Swift 1.2, lihat komentar)

Perpanjang Kelas UIView Anda:

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
        }
    }
}

Dengan cara ini, Tampilan default Anda selalu memiliki bidang tambahan yang dapat diedit Attributes Inspector. Keuntungan lain adalah Anda tidak perlu mengubah kelas MycustomViewsetiap saat. Namun, satu kelemahannya adalah Anda hanya akan melihat perubahan saat menjalankan aplikasi.

MMachinegun
sumber
1
Ekstensi Anda tidak berfungsi dalam versi terbaru Xcode hari ini.
Edgar Aroutiounian
1
Saya akan mengkonfirmasi @EdgarAroutiounian hanya untuk mengatakan bahwa di Swift 1.2 pendekatan kedua tidak lagi berfungsi
Sergey Grischyov
Bagaimana dengan Objective-C?
Nik Kov
Lihat jawaban spencery2 lebih lanjut di bawah ini, ia meluangkan waktu untuk menuliskannya di Objective-C:
MMachinegun
perbarui ekstensi untuk tidak menyimpan nilai dan gunakan set (value) {} dan dapatkan {} untuk mengakses layer secara langsung, ia berfungsi kemudian.
LightningStryk
17

Anda juga dapat membuat batas dengan warna keinginan Anda ..

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

* r, g, b adalah nilai antara 0 hingga 255.

rohan-patel
sumber
6
Perlu dicatat r, gdan bmungkin seharusnya mengapung; pembagi juga harus mengapung: r / 255.0.
tidak, sintaks C tidak seperti yang Anda katakan. r, g dan b dapat berupa int, karena C (dan objC IS C) promosi akan memberikan int r = 128 untuk menggandakan ketika membuat: r / 255.0. Ngomong-ngomong, Anda mendapat dobel, dan Dentang akan berperan untuk CGFloat.
ingconti
10

Tambahkan @IBInspectables berikut dalam ekstensi 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
    }
  }
}

Dan kemudian Anda harus dapat mengatur atribut borderColor dan borderWidth langsung dari inspektur Atribut. Lihat gambar terlampir

Inspektur Atribut

Bikramjit Singh
sumber
8

Ketika saya menggunakan solusi CALayer dari Vladimir, dan di atas tampilan saya memiliki animasi, seperti modal UINavigationController yang ditolak, saya melihat banyak gangguan yang terjadi dan memiliki masalah kinerja gambar.

Jadi, cara lain untuk mencapai ini, tetapi tanpa gangguan dan kehilangan kinerja, adalah dengan membuat UIView khusus dan mengimplementasikan drawRectpesan seperti:

- (void)drawRect:(CGRect)rect
{
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(contextRef, 1);
    CGContextSetRGBStrokeColor(contextRef, 255.0, 255.0, 255.0, 1.0);
    CGContextStrokeRect(contextRef, rect);    
}
Nicu Surdu
sumber
@ Krish Anda menyimpan warna dalam suatu variabel dan ketika Anda perlu mengubah warna batas, Anda mengubah nilai variabel dan memanggil setNeedsDisplaytampilan. Ini akan memaksa redraw UIView dan secara implisit akan menelepon kembali drawRect. Tidak diuji, tho ...
Nicu Surdu
8
view.layer.borderWidth = 1.0
view.layer.borderColor = UIColor.lightGray.cgColor
shaiju mathew
sumber
1
Saya benar-benar tidak suka orang-orang yang terpilih tanpa penjelasan. Itu tidak membantu siapa pun.
David DelMonte
7

Coba kode ini:

view.layer.borderColor =  [UIColor redColor].CGColor;
view.layer.borderWidth= 2.0;
[view setClipsToBounds:YES];
Vikram Biwal
sumber
4

Saya tidak akan menyarankan mengganti drawRect karena menyebabkan hit kinerja.

Sebagai gantinya, saya akan memodifikasi properti kelas seperti di bawah ini (di uiview khusus Anda):

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

Saya tidak melihat gangguan ketika mengambil pendekatan di atas - tidak yakin mengapa menempatkan initWithFrame menghentikan ini ;-)

DEzra
sumber
3

Saya ingin menambahkan ini ke jawaban @ marczking ( Opsi 1 ) sebagai komentar, tetapi status rendah saya di StackOverflow mencegahnya.

Saya melakukan port jawaban @ marczking untuk Objective C. Bekerja seperti pesona, terima kasih @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
spencery2
sumber
2

@IBInspectable bekerja untuk saya di 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
    }
}
anhtran
sumber
1

Jika Anda tidak ingin mengedit lapisan UIView, Anda selalu dapat menyematkan tampilan dalam tampilan lain. Tampilan induk akan mengatur warna latar belakang ke warna batas. Ini juga akan sedikit lebih besar, tergantung pada seberapa lebar Anda ingin menjadi perbatasan.

Tentu saja, ini hanya berfungsi jika tampilan Anda tidak transparan dan Anda hanya ingin warna garis tunggal. OP ingin perbatasan dalam pandangan itu sendiri, tetapi ini mungkin merupakan alternatif yang layak.

Matt Becker
sumber
0

Jika Anda ingin menambahkan batas yang berbeda di sisi yang berbeda, mungkin menambahkan subview dengan gaya spesifik adalah cara yang mudah dibuat.

Yuanfei Zhu
sumber
0

warna batas item dalam cepat 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
Akhrua
sumber