Saya menggunakan jawabannya di Bagaimana cara membuat UILabel dengan sudut bulat pada iPhone? dan kode dari Bagaimana tampilan persegi bundar dengan transparansi dilakukan di iphone? untuk membuat kode ini.
Kemudian saya menyadari bahwa saya telah menjawab pertanyaan yang salah (memberikan UILabel bulat daripada UIImage) jadi saya menggunakan kode ini untuk mengubahnya:
http://discussions.apple.com/thread.jspa?threadID=1683876
Buat proyek iPhone dengan template View. Di pengontrol tampilan, tambahkan ini:
- (void)viewDidLoad
{
CGRect rect = CGRectMake(10, 10, 200, 100);
MyView *myView = [[MyView alloc] initWithFrame:rect];
[self.view addSubview:myView];
[super viewDidLoad];
}
MyView
hanyalah sebuah UIImageView
subclass:
@interface MyView : UIImageView
{
}
Saya belum pernah menggunakan konteks grafis sebelumnya, tetapi saya berhasil mengatur kode ini dengan pincang. Ini kehilangan kode untuk dua sudut. Jika Anda membaca kode, Anda dapat melihat bagaimana saya menerapkan ini (dengan menghapus beberapa CGContextAddArc
panggilan, dan menghapus beberapa nilai radius dalam kode. Kode untuk semua sudut ada di sana, jadi gunakan itu sebagai titik awal dan hapus bagian yang membuat sudut tidak perlu. Perhatikan bahwa Anda dapat membuat persegi panjang dengan 2 atau 3 sudut membulat juga jika mau.
Kodenya tidak sempurna, tapi saya yakin Anda bisa sedikit merapikannya.
static void addRoundedRectToPath(CGContextRef context, CGRect rect, float radius, int roundedCornerPosition)
{
// all corners rounded
// CGContextMoveToPoint(context, rect.origin.x, rect.origin.y + radius);
// CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height - radius);
// CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius,
// radius, M_PI / 4, M_PI / 2, 1);
// CGContextAddLineToPoint(context, rect.origin.x + rect.size.width - radius,
// rect.origin.y + rect.size.height);
// CGContextAddArc(context, rect.origin.x + rect.size.width - radius,
// rect.origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1);
// CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + radius);
// CGContextAddArc(context, rect.origin.x + rect.size.width - radius, rect.origin.y + radius,
// radius, 0.0f, -M_PI / 2, 1);
// CGContextAddLineToPoint(context, rect.origin.x + radius, rect.origin.y);
// CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + radius, radius,
// -M_PI / 2, M_PI, 1);
// top left
if (roundedCornerPosition == 1) {
CGContextMoveToPoint(context, rect.origin.x, rect.origin.y + radius);
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height - radius);
CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius,
radius, M_PI / 4, M_PI / 2, 1);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width,
rect.origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y);
}
// bottom left
if (roundedCornerPosition == 2) {
CGContextMoveToPoint(context, rect.origin.x, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width,
rect.origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x + radius, rect.origin.y);
CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + radius, radius,
-M_PI / 2, M_PI, 1);
}
// add the other corners here
CGContextClosePath(context);
CGContextRestoreGState(context);
}
-(UIImage *)setImage
{
UIImage *img = [UIImage imageNamed:@"my_image.png"];
int w = img.size.width;
int h = img.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextBeginPath(context);
CGRect rect = CGRectMake(0, 0, w, h);
addRoundedRectToPath(context, rect, 50, 1);
CGContextClosePath(context);
CGContextClip(context);
CGContextDrawImage(context, rect, img.CGImage);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
[img release];
return [UIImage imageWithCGImage:imageMasked];
}
teks alt http://nevan.net/skitch/skitched-20100224-092237.png
Jangan lupa bahwa Anda harus mendapatkan kerangka QuartzCore di sana agar ini berfungsi.
Mulai di iOS 3.2, Anda dapat menggunakan fungsionalitas
UIBezierPath
s untuk membuat persegi bundar di luar kotak (di mana hanya sudut yang Anda tentukan yang dibulatkan). Anda kemudian dapat menggunakan ini sebagai jalur aCAShapeLayer
, dan menggunakan ini sebagai topeng untuk lapisan tampilan Anda:Dan hanya itu - tidak mengotak-atik mendefinisikan bentuk secara manual di Core Graphics, tidak membuat gambar masking di Photoshop. Lapisan tersebut bahkan tidak perlu dibatalkan. Menerapkan sudut membulat atau mengubah ke sudut baru semudah mendefinisikan yang baru
UIBezierPath
dan menggunakannyaCGPath
sebagai jalur lapisan topeng. Thecorners
parameterbezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
metode adalah bitmask, dan sehingga beberapa sudut dapat dibulatkan oleh ORing mereka bersama-sama.EDIT: Menambahkan bayangan
Jika Anda ingin menambahkan bayangan ke ini, diperlukan sedikit pekerjaan lagi.
Karena
imageView.layer.mask = maskLayer
menggunakan topeng, bayangan biasanya tidak akan muncul di luarnya. Triknya adalah dengan menggunakan tampilan transparan, lalu menambahkan dua subCALayer
-lapisan ke lapisan tampilan:shadowLayer
danroundedLayer
. Keduanya perlu memanfaatkanUIBezierPath
. Gambar ditambahkan sebagai kontenroundedLayer
.sumber
Saya telah menggunakan kode ini di banyak tempat di kode saya dan berfungsi 100% dengan benar. Anda dapat mengubah urutan apa pun dengan mengubah satu properti "byRoundingCorners: UIRectCornerBottomLeft"
sumber
UITableView
-subviews (misalnyaUITableViewCell
s atauUITableViewHeaderFooterView
s), ini menghasilkan kelancaran yang buruk saat menggulir . Pendekatan lain untuk penggunaan itu adalah solusi ini dengan kinerja yang lebih baik (menambahkan sudut Radius ke semua sudut). Untuk 'menampilkan' hanya sudut tertentu yang dibulatkan (seperti sudut kanan atas dan bawah) saya menambahkan subview dengan nilai negatif padaframe.origin.x
dan menetapkan cornerRadius ke lapisannya. Jika seseorang menemukan solusi yang lebih baik, saya tertarik.Di iOS 11, kami sekarang hanya dapat melewati beberapa sudut
sumber
Ekstensi CALayer dengan sintaks Swift 3+
Ini bisa digunakan seperti:
sumber
Contoh Stuarts untuk membulatkan sudut tertentu bekerja dengan baik. Jika Anda ingin membulatkan beberapa sudut seperti kiri dan kanan atas, inilah cara melakukannya
sumber
UITableView
-subviews (misalnyaUITableViewCell
s atauUITableViewHeaderFooterView
s), ini menghasilkan kelancaran yang buruk saat menggulir . Pendekatan lain untuk penggunaan itu adalah solusi ini dengan kinerja yang lebih baik (menambahkan sudut Radius ke semua sudut). Untuk 'menampilkan' hanya sudut tertentu yang dibulatkan (seperti sudut kanan atas dan bawah) saya menambahkan subview dengan nilai negatif padaframe.origin.x
dan menetapkan cornerRadius ke lapisannya. Jika seseorang menemukan solusi yang lebih baik, saya tertarik.Terima kasih telah berbagi. Di sini saya ingin membagikan solusi pada swift 2.0 untuk referensi lebih lanjut tentang masalah ini. (untuk menyesuaikan protokol UIRectCorner)
sumber
ada jawaban yang lebih mudah dan lebih cepat yang mungkin bekerja tergantung pada kebutuhan Anda dan juga bekerja dengan bayangan. Anda dapat menyetel maskToBounds pada superlayer ke true, dan mengimbangi layer anak sehingga 2 sudutnya berada di luar batas superlayer, secara efektif memotong sudut membulat pada 2 sisi.
tentu saja ini hanya berfungsi jika Anda ingin memiliki hanya 2 sudut membulat di sisi yang sama dan konten lapisan terlihat sama saat Anda memotong beberapa piksel dari satu sisi. berfungsi dengan baik karena diagram batang hanya dibulatkan di sisi atas.
sumber
Lihat pertanyaan terkait ini . Anda harus menggambar persegi panjang Anda sendiri ke a
CGPath
dengan beberapa sudut membulat, tambahkanCGPath
ke AndaCGContext
dan kemudian klip ke sana menggunakanCGContextClip
.Anda juga dapat menggambar persegi bulat dengan nilai alfa ke gambar dan kemudian menggunakan gambar itu untuk membuat lapisan baru yang Anda tetapkan sebagai
mask
properti lapisan Anda ( lihat dokumentasi Apple ).sumber
Terlambat setengah dekade, tapi menurut saya cara orang saat ini melakukan ini tidak 100% benar. Banyak orang memiliki masalah bahwa menggunakan metode UIBezierPath + CAShapeLayer mengganggu Tata letak otomatis, terutama saat disetel di Storyboard. Tidak ada jawaban yang membahas ini, jadi saya memutuskan untuk menambahkan jawaban saya sendiri.
Ada cara yang sangat mudah untuk mengelaknya: Gambarlah sudut yang membulat di
drawRect(rect: CGRect)
fungsi tersebut.Misalnya, jika saya menginginkan sudut membulat atas untuk UIView, saya akan membuat subkelas UIView dan kemudian menggunakan subkelas itu di mana saja.
Ini adalah cara terbaik untuk mengatasi masalah dan tidak membutuhkan waktu sama sekali untuk beradaptasi.
sumber
drawRect(_:)
jika Anda melakukan gambar kustom dalam tampilan Anda (mis. Dengan Core Graphics), jika tidak, implementasi kosong pun dapat memengaruhi performa. Membuat lapisan topeng baru setiap saat juga tidak perlu. Yang perlu Anda lakukan hanyalah memperbaruipath
properti lapisan topeng saat batas tampilan berubah, dan tempat untuk melakukannya adalah di dalamlayoutSubviews()
metode yang diganti .Membulatkan hanya beberapa sudut tidak akan berfungsi baik dengan pengubahan ukuran otomatis atau tata letak otomatis.
Jadi opsi lain adalah menggunakan reguler
cornerRadius
dan menyembunyikan sudut yang tidak Anda inginkan di bawah tampilan lain atau di luar batas tampilan supernya memastikan itu diatur untuk memotong kontennya.sumber
Untuk menambah jawaban dan penambahan , saya membuat yang sederhana, dapat digunakan kembali
UIView
di Swift. Bergantung pada kasus penggunaan Anda, Anda mungkin ingin membuat modifikasi (hindari membuat objek pada setiap tata letak, dll.), Tetapi saya ingin membuatnya sesederhana mungkin. Ekstensi memungkinkan Anda untuk menerapkan ini ke tampilan lain (mis.UIImageView
) Lebih mudah jika Anda tidak suka subclassing.Inilah cara Anda menerapkannya ke
UIViewController
:sumber
Mengakhiri jawaban Stuart, Anda dapat menggunakan metode sudut pembulatan sebagai berikut:
Jadi untuk menerapkan sudut pembulatan, Anda cukup melakukan:
sumber
Saya sarankan untuk mendefinisikan topeng lapisan. Topeng itu sendiri harus berupa
CAShapeLayer
objek dengan jalur khusus. Anda dapat menggunakan ekstensi UIView berikutnya (Swift 4.2):sumber