Saya punya pertanyaan berurusan dengan UIButton dan area hit-nya. Saya menggunakan tombol Info Dark di pembangun antarmuka, tetapi saya menemukan bahwa area hit tidak cukup besar untuk jari-jari beberapa orang.
Apakah ada cara untuk menambah area tekan tombol baik secara terprogram atau di Interface Builder tanpa mengubah ukuran grafik InfoButton?
ios
cocoa-touch
uibutton
uikit
Kevin Bomberry
sumber
sumber
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return bounds.insetBy(dx: -20, dy: -20).contains(point) }
Jawaban:
Karena saya menggunakan gambar latar belakang, tidak ada solusi yang bekerja dengan baik untuk saya. Berikut adalah solusi yang melakukan beberapa keajaiban obyektif-c dan menawarkan solusi drop in dengan kode minimal.
Pertama, tambahkan kategori ke
UIButton
yang menimpa tes hit dan juga menambahkan properti untuk memperluas kerangka uji hit.UIButton + Extensions.h
UIButton + Ekstensi.m
Setelah kelas ini ditambahkan, yang perlu Anda lakukan adalah mengatur insets tepi tombol Anda. Perhatikan bahwa saya memilih untuk menambahkan insets jadi jika Anda ingin membuat area hit lebih besar, Anda harus menggunakan angka negatif.
Catatan: Ingatlah untuk mengimpor kategori (
#import "UIButton+Extensions.h"
) di kelas Anda.sumber
[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"arrow.png"] forState:UIControlStateNormal];
Dan cukup set lebar & tinggi yang Anda butuhkan: `backButton.frame = CGRectMake (5, 28, 45, 30);`Cukup atur nilai inset tepi gambar di pembuat antarmuka.
sumber
button.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10);
Inilah solusi elegan menggunakan Extensions in Swift. Ini memberi semua UIButtons area hit setidaknya 44x44 poin, sesuai dengan Panduan Antarmuka Manusia Apple ( https://developer.apple.com/ios/human-interface-guidelines/visual-design/layout/ )
Swift 2:
Swift 3:
sumber
Anda juga dapat subkelas
UIButton
atau kustomUIView
dan menimpapoint(inside:with:)
dengan sesuatu seperti:Cepat 3
Objektif-C
sumber
Inilah UIButton + Extensions Chase di Swift 3.0.
Untuk menggunakannya, Anda dapat:
sumber
UIControl
, bukanUIButton
.pTouchAreaEdgeInsets
harusInt
, bukanUIEdgeInsets
. (Sebenarnya, itu bisa berupa jenis apa saja, tetapiInt
merupakan jenis yang paling umum dan sederhana, sehingga umum dalam konstruksi seperti itu). (Karena itu saya sangat menyukai pendekatan ini secara umum. Terima kasih, dcRay!)Saya sarankan menempatkan UIButton dengan tipe Kustom di tengah tombol info Anda. Ubah ukuran tombol kustom ke ukuran yang Anda inginkan menjadi area hit. Dari sana Anda memiliki dua opsi:
Periksa opsi 'Tampilkan sentuhan pada highlight' dari tombol kustom. Cahaya putih akan muncul di atas tombol info, tetapi dalam kebanyakan kasus jari pengguna akan membahas hal ini dan yang akan mereka lihat hanyalah cahaya di luar.
Siapkan IBOutlet untuk tombol info dan dua IBAksi untuk tombol kustom satu untuk 'Touch Down' dan satu untuk 'Touch Up Inside'. Kemudian dalam Xcode buat acara touchdown atur properti yang disorot dari tombol info ke YES dan event touchupinside atur properti yang disorot menjadi TIDAK.
sumber
Jangan atur
backgroundImage
properti dengan gambar Anda, aturimageView
properti. Juga, pastikan Anda telahimageView.contentMode
mengatur diUIViewContentModeCenter
.sumber
imageView.contentMode
dapat ditetapkan sebagaiUIContentModeCenter
.[[backButton imageView] setContentMode: UIViewContentModeCenter]; [backButton setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
Solusi saya di Swift 3:
sumber
Tidak ada yang salah dengan jawaban yang disajikan; namun saya ingin memperluas jawaban jlarjlar karena memiliki potensi luar biasa yang dapat menambah nilai untuk masalah yang sama dengan kontrol lain (misalnya SearchBar). Ini karena sejak pointInside terpasang ke UIView, seseorang dapat mensubklasifikasikan kontrol apa pun untuk meningkatkan area sentuh. Jawaban ini juga menunjukkan sampel lengkap tentang bagaimana menerapkan solusi lengkap.
Buat subkelas baru untuk tombol Anda (atau kontrol apa pun)
Selanjutnya timpa metode pointInside dalam implementasi subclass Anda
Pada file storyboard / xib Anda pilih kontrol yang dimaksud dan buka inspektur identitas dan ketikkan nama kelas khusus Anda.
Di kelas UIViewController Anda untuk adegan yang berisi tombol, ubah tipe kelas untuk tombol tersebut ke nama subkelas Anda.
Hubungkan tombol storyboard / xib Anda ke IBOutlet properti dan area sentuh Anda akan diperluas agar sesuai dengan area yang ditentukan dalam subkelas.
Selain mengganti metode pointInside bersama-sama dengan metode CGRectInset dan CGRectContainsPoint , kita harus meluangkan waktu untuk memeriksa CGGeometry untuk memperluas area sentuh persegi panjang dari setiap subkelas UIView. Anda juga dapat menemukan beberapa tips bagus tentang kasus penggunaan CGGeometry di NSHipster .
Misalnya seseorang dapat membuat area sentuh tidak teratur menggunakan metode yang disebutkan di atas atau hanya memilih untuk membuat area sentuh lebar dua kali lebih besar dari area sentuh horizontal:
NB: Mengganti kontrol Kelas UI harus menghasilkan hasil yang serupa pada perluasan area sentuh untuk kontrol yang berbeda (atau subkelas UIView lainnya, seperti UIImageView, dll.).
sumber
Ini bekerja untuk saya:
sumber
Jangan mengubah perilaku UIButton.
sumber
Saya menggunakan pendekatan yang lebih umum dengan swizzling
-[UIView pointInside:withEvent:]
. Ini memungkinkan saya untuk memodifikasi perilaku pengujian hit pada apa punUIView
, bukan hanyaUIButton
.Seringkali, sebuah tombol ditempatkan di dalam tampilan wadah yang juga membatasi pengujian hit. Misalnya, ketika sebuah tombol berada di atas tampilan wadah dan Anda ingin memperpanjang target sentuh ke atas, Anda juga harus memperluas target sentuh dari tampilan wadah.
Yang menyenangkan tentang pendekatan ini adalah Anda dapat menggunakannya bahkan di Storyboards dengan menambahkan Atribut Runtime yang Ditentukan Pengguna. Sayangnya,
UIEdgeInsets
tidak langsung tersedia sebagai jenis ada tapi karenaCGRect
juga terdiri dari struct dengan empatCGFloat
bekerja sempurna dengan memilih "Rect" dan mengisi nilai-nilai seperti ini:{{top, left}, {bottom, right}}
.sumber
Saya menggunakan kelas berikut di Swift, untuk juga mengaktifkan properti Interface Builder untuk menyesuaikan margin:
sumber
Nah, Anda dapat menempatkan UIButton Anda di dalam UIView yang transparan dan sedikit lebih besar, dan kemudian menangkap peristiwa sentuhan pada instance UIView seperti pada UIButton. Dengan begitu, Anda masih memiliki tombol, tetapi dengan area sentuh yang lebih besar. Anda harus secara manual berurusan dengan negara-negara yang dipilih & disorot dari tombol jika pengguna menyentuh tampilan bukan tombol.
Kemungkinan lain melibatkan penggunaan UIImage, bukan UIButton.
sumber
Saya dapat meningkatkan area klik tombol info secara terprogram. Grafik "i" tidak mengubah skala dan tetap berpusat di bingkai tombol baru.
Ukuran tombol info tampaknya diperbaiki hingga 18x19 [*] di Interface Builder. Dengan menghubungkannya ke IBOutlet, saya dapat mengubah ukuran frame dalam kode tanpa masalah.
[*]: Versi iOS belakangan tampaknya meningkatkan area hit dari tombol info.
sumber
Ini adalah Solusi Swift 3 saya (berdasarkan blog ini: http://bdunagan.com/2010/03/01/iphone-tip-larger-hit-area-for-uibutton/ )
sumber
Tes hit kustom Chase diimplementasikan sebagai subkelas UIButton. Ditulis dalam Objective-C.
Tampaknya berfungsi untuk
init
danbuttonWithType:
konstruktor. Untuk kebutuhan saya itu sempurna, tetapi karena subkelasUIButton
bisa berbulu, saya akan tertarik untuk mengetahui apakah ada yang salah dengan itu.CustomeHitAreaButton.h
CustomHitAreaButton.m
sumber
Implementasi melalui menimpa UIButton yang diwarisi.
Swift 2.2 :
sumber
WJBackgroundInsetButton.h
WJBackgroundInsetButton.m
sumber
Jangan pernah menimpa metode dalam kategori. Tombol subclass dan override
- pointInside:withEvent:
. Misalnya jika sisi tombol Anda lebih kecil dari 44 px (yang disarankan sebagai area tappable minimum) gunakan ini:sumber
Saya membuat perpustakaan untuk tujuan ini.
Anda dapat memilih untuk menggunakan
UIView
kategori, tidak perlu subklas :Atau Anda dapat mensubklasifikasikan UIView atau UIButton Anda dan mengatur
minimumHitTestWidth
dan / atauminimumHitTestHeight
. Area tes tekan tombol Anda kemudian akan diwakili oleh 2 nilai ini.Sama seperti solusi lain, ia menggunakan
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
metode ini. Metode ini dipanggil ketika iOS melakukan pengujian hit. Posting blog ini memiliki deskripsi yang baik tentang cara kerja uji coba iOS.https://github.com/kgaidis/KGHitTestingViews
Anda juga bisa hanya subkelas dan menggunakan Pembuat Antarmuka tanpa menulis kode apa pun:
sumber
Berdasarkan jawaban giaset di atas (yang saya temukan solusi paling elegan), berikut adalah versi cepat 3:
sumber
Sederhana saja:
Itu semuanya.
sumber
Saya menggunakan trik ini untuk tombol di dalam tableviewcell.accessoryView untuk memperbesar area sentuhnya
sumber
Saya baru saja melakukan port dari solusi @Chase di swift 2.2
Anda dapat menggunakan seperti ini
Untuk referensi lain, lihat https://stackoverflow.com/a/13067285/1728552
sumber
@ jawaban antoine diformat untuk Swift 4
sumber
Saya telah mengikuti respons Chase dan berfungsi dengan baik, satu masalah tunggal ketika Anda membuat arrea terlalu besar, lebih besar dari zona tempat tombolnya tidak dipilih (jika zona tidak lebih besar) tidak memanggil pemilih untuk acara UIControlEventTouchUpInside .
Saya pikir ukurannya lebih dari 200 arah atau sesuatu seperti itu.
sumber
Saya sangat terlambat ke permainan ini, tetapi ingin mempertimbangkan teknik sederhana yang dapat memecahkan masalah Anda. Berikut adalah cuplikan UIButton terprogram terprogram untuk saya:
Saya memuat Gambar png transparan untuk tombol saya dan mengatur gambar latar belakang. Saya mengatur frame berdasarkan UIImage dan scaling 50% untuk retina. OK, mungkin Anda setuju dengan yang di atas atau tidak, TETAPI jika Anda ingin membuat area hit lebih BESAR dan menyelamatkan diri Anda dari sakit kepala:
Apa yang saya lakukan, buka gambar di photoshop dan cukup tambahkan ukuran kanvas hingga 120% dan hemat. Secara efektif Anda baru saja membuat gambar lebih besar dengan piksel transparan.
Hanya satu pendekatan.
sumber
@ jlajlar jawaban di atas tampak bagus dan langsung tetapi tidak cocok dengan Xamarin.iOS, jadi saya mengubahnya menjadi Xamarin. Jika Anda mencari solusi pada Xamarin iOS, ini dia:
Anda bisa menambahkan metode ini ke kelas tempat Anda meng-override UIView atau UIImageView. Ini bekerja dengan baik :)
sumber
Tidak ada jawaban yang berfungsi sempurna untuk saya, karena saya menggunakan gambar latar belakang dan judul pada tombol itu. Selain itu, tombol akan mengubah ukuran seiring perubahan ukuran layar.
Sebagai gantinya, saya memperbesar area keran dengan membuat area transparan png lebih besar.
sumber