UITextfield leftView / rightView padding di iOS7


94

Tampilan leftView dan rightView dari UITextField di iOS7 sangat dekat dengan batas bidang teks.

Bagaimana saya bisa menambahkan beberapa padding (horizontal) ke item tersebut?

Saya mencoba memodifikasi bingkai, tetapi tidak berhasil

uint padding = 10;//padding for iOS7
UIImageView * iconImageView = [[UIImageView alloc] initWithImage:iconImage];    
iconImageView.frame = CGRectMake(0 + padding, 0, 16, 16);
textField.leftView = iconImageView;

Harap, perhatikan bahwa saya tidak tertarik untuk menambahkan padding ke teks bidang teks, seperti ini Set padding untuk UITextField dengan UITextBorderStyleNone


kemungkinan duplikat dari inset Teks untuk UITextField?
Zorayr

1
Tidak, ini menanyakan tentang mengindentasi gambar yang ditampilkan sebagai leftView di bidang teks. Tidak mengindentasi teks itu sendiri. Coba kodenya dan Anda akan melihat bahwa pengaturan leftView ke gambar menempatkan gambar itu di tepi kiri bidang teks, tanpa padding. Itu terlihat jelek.
Batu

Jawaban:


90

Baru saja mengerjakan ini sendiri dan menggunakan solusi ini:

- (CGRect) rightViewRectForBounds:(CGRect)bounds {

    CGRect textRect = [super rightViewRectForBounds:bounds];
    textRect.origin.x -= 10;
    return textRect;
}

Ini akan memindahkan gambar dari kanan sebesar 10 alih-alih membuat gambar terjepit ke tepi di iOS 7.

Selain itu, ini adalah subkelas dari UITextField, yang dapat dibuat oleh:

  1. Buat file baru yang merupakan subkelas, UITextFieldbukan defaultNSObject
  2. Tambahkan metode baru bernama - (id)initWithCoder:(NSCoder*)coderuntuk mengatur gambar

    - (id)initWithCoder:(NSCoder*)coder {
        self = [super initWithCoder:coder];
    
        if (self) {
    
            self.clipsToBounds = YES;
            [self setRightViewMode:UITextFieldViewModeUnlessEditing];
    
            self.leftView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"textfield_edit_icon.png"]];
        }
    
        return self;
    }
    
  3. Anda mungkin harus mengimpor #import <QuartzCore/QuartzCore.h>

  4. Tambahkan rightViewRectForBoundscara di atas

  5. Di Interface Builder, klik BidangTeks yang ingin Anda buat menjadi subkelas dan ubah atribut kelas menjadi nama subkelas baru ini.


bagaimana cara menggunakan IBDesignable untuk hal yang sama?
riddhi

untuk versi terbaru atau jika Anda melihat ini pada tahun 2020. kunjungi: stackoverflow.com/a/55041786/6596443
AKINNUBI ABIOLA SYLVESTER

167

Solusi yang jauh lebih sederhana, yang memanfaatkan contentMode:

    arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"down_arrow"]];
    arrow.frame = CGRectMake(0.0, 0.0, arrow.image.size.width+10.0, arrow.image.size.height);
    arrow.contentMode = UIViewContentModeCenter;

    textField.rightView = arrow;
    textField.rightViewMode = UITextFieldViewModeAlways;

Di Swift 3,

    let arrow = UIImageView(image: UIImage(named: "arrowDrop"))
    if let size = arrow.image?.size {
        arrow.frame = CGRect(x: 0.0, y: 0.0, width: size.width + 10.0, height: size.height)
    }
    arrow.contentMode = UIViewContentMode.center
    self.textField.rightView = arrow
    self.textField.rightViewMode = UITextFieldViewMode.always

1
Anda juga dapat menggunakan ScaleAspectFit daripada center ... jika ukuran gambar tidak sesuai dengan frame yang tepat.
Mihir Mehta

Saya menggunakan contoh Anda untuk UIButton (bukan UIImageView) sementara tipenya adalah InfoLight.
OhadM

Saya menemukan bahwa ".right" daripada ".center" membuatnya lebih terlihat seperti bilah Pencarian bawaan seperti yang ada di aplikasi Kontak. Solusi hebat untuk ini, terima kasih telah mempostingnya.
James Toomey

Atau jika Anda harus cermat dalam rekreasi desain, letakkan gambar di kiri dan kemudian tingkatkan lebarnya untuk mencapai padding yang tepat
jovanjovanovic

4
Ini sepertinya tidak berfungsi lagi dengan iOS 13 dan Xcode 11 Beta 7. Namun, berfungsi dengan baik pada iOS 11/12.
PatrickDotStar

49

Cara termudah adalah menambahkan UIView ke leftView / righView dan menambahkan ImageView ke UIView, menyesuaikan asal ImageView di dalam UIView di mana pun Anda suka, ini bekerja untuk saya seperti pesona. Ini hanya membutuhkan beberapa baris kode

UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 5, 26, 26)];
imgView.image = [UIImage imageNamed:@"img.png"];

UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 32, 32)];
[paddingView addSubview:imgView];
[txtField setLeftViewMode:UITextFieldViewModeAlways];
[txtField setLeftView:paddingView];

UIViewContentMode tidak berfungsi tetapi jawaban ini berfungsi dengan sangat baik!
nigong

14

Ini berfungsi dengan baik untuk Swift:

let imageView = UIImageView(image: UIImage(named: "image.png"))
imageView.contentMode = UIViewContentMode.Center
imageView.frame = CGRectMake(0.0, 0.0, imageView.image!.size.width + 20.0, imageView.image!.size.height)
textField.rightViewMode = UITextFieldViewMode.Always
textField.rightView = imageView

tidak dapat mengonversi nilai jenis 'string' ke jenis argumen yang diharapkan 'UIImage? "

8

Ini berhasil untuk saya

UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 20)];
self.passwordTF.leftView = paddingView;
self.passwordTF.leftViewMode = UITextFieldViewModeAlways;

Semoga ini membantu Anda.


6

Saya suka solusi ini karena memecahkan masalah dengan satu baris kode

myTextField.layer.sublayerTransform = CATransform3DMakeTranslation(10.0f, 0.0f, 0.0f);

Catatan: .. atau 2 jika Anda mempertimbangkan untuk menyertakan QuartzCore sebagai garis :)


1
Ini juga memindahkan perbatasan
Softlion

1
tetapi tidak menyelesaikan masalah dengan padding kanan hanya masalah padding kiri
carmen_munich

1
Saya mendapatkan hasil yang lebih baik menggunakan rightView.layer.sublayerTransform = CATransform3DMakeTranslation (-10.0f, 0.0f, 0.0f), tetapi +1 untuk metode ini
Thibaud David

Ingatlah bahwa ini juga akan menggeser tombol "hapus" bidang teks ke kanan, yang dapat mendorongnya melewati tepi bidang teks. Jika Anda tidak memerlukan tombol hapus, ini adalah pendekatan yang bagus, jika tidak, mungkin tidak.
Tom Harrington

4

Cara terbaik untuk melakukannya adalah dengan membuat kelas menggunakan subclass UITextField dan dalam file .m

  #import "CustomTextField.h"
  #import <QuartzCore/QuartzCore.h>
  @implementation CustomTextField


- (id)initWithCoder:(NSCoder*)coder 
 {
self = [super initWithCoder:coder];

if (self) {

    //self.clipsToBounds = YES;
    //[self setRightViewMode:UITextFieldViewModeUnlessEditing];

    self.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,15,46)];
    self.leftViewMode=UITextFieldViewModeAlways;
      }

return self;

}

dengan melakukan ini, buka storyboard atau xib Anda dan klik inspektur identitas dan ganti UITextfield dengan opsi kelas "CustomTextField" Anda sendiri.

Catatan: Jika Anda hanya memberikan padding dengan tata letak otomatis untuk bidang teks maka aplikasi Anda tidak akan berjalan dan hanya menampilkan layar kosong.


4

Alih-alih memanipulasi imageView atau gambar, kita bisa mengganti metode yang disediakan oleh apple untuk rightView.

class CustomTextField : UITextField { 

override func rightViewRect(forBounds bounds: CGRect) -> CGRect {
    let offset = 5
    let width  = 20
    let height = width
    let x = Int(bounds.width) - width - offset
    let y = offset
    let rightViewBounds = CGRect(x: x, y: y, width: width, height: height)
    return rightViewBounds
}}

dan dengan cara yang sama kita dapat mengganti fungsi di bawah untuk tampilan kiri.

override func leftViewRect(forBounds bounds: CGRect) -> CGRect {
    /*return as per requirement*/

}

3

Saya menemukan ini di suatu tempat ...

UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 20)];
paddingView.backgroundColor = [UIColor clearColor];
itemDescription.leftView = paddingView;
itemDescription.leftViewMode = UITextFieldViewModeAlways;

[self addSubview:itemDescription];

4
Itu hanya menambahkan padding ke teks, yang bukan yang dicari penanya. Dia tidak ingin leftView yang jelas. Dia ingin gambar ditampilkan sebagai leftView.
Batu

Anda tinggal menambahkan gambar di paddingView.
Matheus Weber

3

Cepat 5

class CustomTextField: UITextField {
    func invalidate() {
        let errorImage =  UIImageView(image: UIImage(named: "errorImage"))
        errorImage.frame = CGRect(x: 8, y: 8, width: 16, height: 16)
        rightView = UIView(frame: CGRect(x: 0, y: 0, width: 32, height: 32))
        rightView?.addSubview(errorImage)
        rightViewMode = .always
    }
}

Anda ingin:

  • Subkelas UITextField
  • Tulis metode tidak valid di dalam bidang teks subclass
  • Dalam metode invalidate, buat UIView lebih besar dari gambar Anda
  • Tempatkan gambar Anda di dalam tampilan
  • Tetapkan tampilan ke UITextField.rightView

2

Inilah salah satu solusinya:

 UIView *paddingTxtfieldView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 42)]; // what ever you want 
 txtfield.leftView = paddingTxtfieldView;
 txtfield.leftViewMode = UITextFieldViewModeAlways;

1

Buat kelas UITextField kustom dan gunakan kelas itu sebagai ganti UITextField. Override - (CGRect) textRectForBounds: (CGRect) bounds untuk menyetel persegi yang Anda butuhkan

Contoh

- (CGRect)textRectForBounds:(CGRect)bounds{
     CGRect textRect = [super textRectForBounds:bounds];
     textRect.origin.x += 10;
     textRect.size.width -= 10;
     return textRect;
}

1

Contoh di bawah ini adalah untuk menambahkan pengisi horizontal ke tampilan kiri yang kebetulan merupakan ikon - Anda dapat menggunakan pendekatan serupa untuk menambahkan pengisi ke apa pun UIViewyang ingin Anda gunakan sebagai tampilan kiri bidang teks.

Di dalam UITextFieldsubclass:

static CGFloat const kLeftViewHorizontalPadding = 10.0f;

@implementation TextFieldWithLeftIcon
{
  UIImage *_image;
  UIImageView *_imageView;
}

- (instancetype)initWithFrame:(CGRect)frame image:(UIImage *)image
{
  self = [super initWithFrame:frame];
  if (self) {
    if (image) {
      _image = image;
      _imageView = [[UIImageView alloc] initWithImage:image];
      _imageView.contentMode = UIViewContentModeCenter;
      self.leftViewMode = UITextFieldViewModeAlways;
      self.leftView = _imageView;
    }
  }
  return self;
}

#pragma mark - Layout 

- (CGRect)leftViewRectForBounds:(CGRect)bounds
{
  CGFloat widthWithPadding = _image.size.width + kLeftViewHorizontalPadding * 2.0f;
  return CGRectMake(0, 0, widthWithPadding, CGRectGetHeight(bounds));
}

Meskipun kami adalah subclassing di UITextFieldsini, saya yakin ini adalah pendekatan terbersih.


1
- (CGRect)rightViewRectForBounds:(CGRect)bounds
{
    return CGRectMake(bounds.size.width - 40, 0, 40, bounds.size.height);
}

Jika UITextFieldtertanam dalam a UISearchBar, bagaimana Anda memberi tahu UISearchBaruntuk menggunakan UITextFieldsubkelas Anda ?
crishoj

1

terima kasih teman-teman atas jawaban Anda, yang mengejutkan saya tidak satupun dari mereka yang benar-benar sesuai dengan gambar tampilan yang benar ke textfield saya sambil tetap memberikan padding yang dibutuhkan. kemudian saya berpikir untuk menggunakan mode AspectFill dan keajaiban terjadi. untuk pencari masa depan, inilah yang saya gunakan:

UIImageView *emailRightView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 35, 35)];
emailRightView.contentMode = UIViewContentModeScaleAspectFill;
emailRightView.image = [UIImage imageNamed:@"icon_email.png"];
emailTextfield.rightViewMode = UITextFieldViewModeAlways;
emailTextfield.rightView = emailRightView;

35 di bingkai imageview saya mewakili ketinggian emailTextfield saya, silakan sesuaikan dengan kebutuhan Anda.


1

Saya sendiri pernah mengalami masalah ini, dan sejauh ini solusi termudah adalah memodifikasi gambar Anda dengan menambahkan padding ke setiap sisi gambar!

Saya baru saja mengubah gambar png saya untuk menambahkan bantalan transparan 10 piksel, dan itu bekerja dengan baik, tanpa pengkodean sama sekali!


1

Jika Anda menggunakan UIImageView sebagai leftView maka Anda harus menggunakan kode ini:

Perhatian: Jangan gunakan di dalam viewWillAppear atau viewDidAppear

-(UIView*)paddingViewWithImage:(UIImageView*)imageView andPadding:(float)padding
{
    float height = CGRectGetHeight(imageView.frame);
    float width =  CGRectGetWidth(imageView.frame) + padding;

    UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)];

    [paddingView addSubview:imageView];

    return paddingView;
}

1

Saya membuat metode khusus di kelas ViewController saya, seperti yang ditunjukkan di bawah ini:

- (void) modifyTextField:(UITextField *)textField
{
    // Prepare the imageView with the required image
    uint padding = 10;//padding for iOS7
    UIImageView * iconImageView = [[UIImageView alloc] initWithImage:iconImage];    
    iconImageView.frame = CGRectMake(0 + padding, 0, 16, 16);

    // Set the imageView to the left of the given text field.
    textField.leftView = iconImageView;
    textField.leftViewMode = UITextFieldViewModeAlways;
}

Sekarang saya dapat memanggil metode itu di dalam ( viewDidLoadmetode) dan mengirim salah satu dari saya TextFieldske metode itu dan menambahkan padding untuk kanan dan kiri, dan memberi warna teks dan latar belakang hanya dengan menulis satu baris kode, sebagai berikut:

[self modifyTextField:self.firstNameTxtFld];

Ini Bekerja dengan sempurna di iOS 7! Semoga ini masih berfungsi di iOS 8 dan 9 juga!

Saya tahu bahwa menambahkan terlalu banyak Tampilan mungkin membuat objek ini sedikit lebih berat untuk dimuat. Tetapi ketika khawatir tentang kesulitan dalam solusi lain, saya mendapati diri saya lebih condong ke metode ini dan lebih fleksibel dengan menggunakan cara ini. ;)

Semoga jawaban ini bisa membantu atau berguna untuk mencari solusi lain untuk orang lain.

Bersulang!


1

Ini berfungsi untuk saya seperti yang saya cari:

func addImageViewInsideMyTextField() {
    let someView = UIView(frame: CGRect(x: 0, y: 0, width: 40, height: 24))
    let imageView = UIImageView(image: UIImage(named: "accountImage"))
    imageView.frame = CGRect(x: 16, y: 0, width: 24, height: 24)
    imageView.contentMode = .scaleAspectFit
    someView.addSubview(imageView)

    self.myTextField.leftView = someView
    self.myTextField.leftViewMode = .always
}

1

Sejak iOS 13 dan Xcode 11, ini adalah satu-satunya solusi yang berfungsi untuk kami.

// Init of custom UITextField
override init(frame: CGRect) {
    super.init(frame: frame)

    if let size = myButton.imageView?.image?.size {
        myButton.frame = CGRect(x:0, y: 0, width: size.width, height: size.height)

        let padding: CGFloat = 5
        let container = UIView(frame: CGRect(x:0, y: 0, width: size.width + padding, height: size.height))
        container.addSubview(myButton)

        myButton.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            myButton.topAnchor.constraint(equalTo: container.topAnchor),
            myButton.leftAnchor.constraint(equalTo: container.leftAnchor),
            myButton.bottomAnchor.constraint(equalTo: container.bottomAnchor),
            myButton.rightAnchor.constraint(equalTo: container.rightAnchor, constant: -padding),
        ])

        textField.rightViewMode = .always
        textField.rightView = container
    }
}

jawaban di atas tidak berhasil untuk saya, yang ini berhasil.
Mark Dylan B Mercado

1

// Setel Tampilan Kanan UITextField, swift 4.2TxtPass.rightViewMode = UITextField.ViewMode.always let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 18, height: 18)) imageView.contentMode = UIView.ContentMode.scaleAspectFit let image = UIImage(named: "hidepass") imageView.image = image let rightView = UIView(frame: CGRect(x: 0, y: 0, width: 28, height: 18)) rightView.addSubview(imageView) rightView.contentMode = UIView.ContentMode.left TxtPass.rightView = rightView


0

Satu trik: Tambahkan UIView yang berisi UIImageView ke UITextField sebagai rightView. UIView ini harus berukuran lebih besar, sekarang tempatkan UIImageView di sebelah kiri. Jadi akan ada bantalan ruang dari kanan.

// Add a UIImageView to UIView and now this UIView to UITextField - txtFieldDate
UIView *viewRightIntxtFieldDate = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 30)]; 
// (Height of UITextField is 30px so height of viewRightIntxtFieldDate = 30px)
UIImageView *imgViewCalendar = [[UIImageView alloc] initWithFrame:CGRectMake(0, 10, 10, 10)];
[imgViewCalendar setImage:[UIImage imageNamed:@"calendar_icon.png"]];
[viewRightIntxtFieldDate addSubview:imgViewCalendar];
txtFieldDate.rightViewMode = UITextFieldViewModeAlways;
txtFieldDate.rightView = viewRightIntxtFieldDate;

0

Cara termudah hanyalah mengubah Textfield sebagai RoundRect, bukan Custom dan lihat keajaibannya. :)


0

untuk Swift2, saya gunakan

...
        self.mSearchTextField.leftViewMode = UITextFieldViewMode.Always
        let searchImg = UIImageView(image: UIImage(named: "search.png"))
        let size = self.mSearchTextField.frame.height
        searchImg.frame = CGRectMake(0, 0, size,size)
        searchImg.contentMode = UIViewContentMode.ScaleAspectFit
        self.mSearchTextField.leftView = searchImg
...

0
...
textField.rightView = UIImageView(image: ...)
textField.rightView?.contentMode = .top
textField.rightView?.bounds.size.height += 10
textField.rightViewMode = .always
...

0

Pendekatan sederhana:

textField.rightViewMode = .always
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 25, height: 15))
textField.contentMode = .scaleAspectFit
imageView = UIImage(named: "imageName")
textField.rightView = imageView

Catatan: Tinggi harus lebih kecil dari lebar untuk memungkinkan bantalan horizontal.


0

Saya menyadari ini posting lama dan jawaban ini agak spesifik untuk kasus penggunaan saya, tetapi saya mempostingnya jika orang lain mencari solusi serupa. Saya ingin memindahkan leftView atau rightView UITextField tetapi saya tidak meletakkan gambar di dalamnya dan tidak ingin ada konstanta yang dikodekan keras.

UI saya meminta untuk menyembunyikan tombol hapus bidang teks dan menampilkan UIActivityIndicatorView di mana tombol hapus berada.

Saya menambahkan spinner ke rightView, tetapi di luar kotak (di iOS 13) itu digeser 20 piksel ke kanan clearButton. Saya tidak suka menggunakan angka ajaib karena posisi clearButton dan rightView dapat berubah sewaktu-waktu oleh Apple. Maksud desain UI adalah "pemintal di mana tombol hapus" jadi solusi saya adalah untuk subclass UITextField dan menimpa rightViewRect(forBounds).

override func rightViewRect(forBounds bounds: CGRect) -> CGRect {

    // Use clearButton's rectangle
    return self.clearButtonRect(forBounds: bounds)
}

Di bawah ini adalah contoh kerja (sans Storyboard):

//------------------------------------------------------------------------------
class myCustomTextField: UITextField {

    override func rightViewRect(forBounds bounds: CGRect) -> CGRect {

        // Use clearButton rectangle
        return self.clearButtonRect(forBounds: bounds)
    }
}

//------------------------------------------------------------------------------
class myViewController: UIViewController {

    var activityView: UIActivityIndicatorView = {
        let activity = UIActivityIndicatorView()
        activity.startAnimating()
        return activity
    }()

    @IBOutlet weak var searchTextField: myCustomTextField!

    //------------------------------------------------------------------------------
    // MARK: - Lifecycle
    //------------------------------------------------------------------------------
    override func viewDidLoad() {

        super.viewDidLoad()

        searchTextField.rightView = activityView
        searchTextField.rightViewMode = .never // Hide spinner
        searchTextField.clearButtonMode = .never // Hide clear button

        setupUIForTextEntry()
    }

    // ...
    // More code to switch between user text entry and "search progress" 
    // by calling setupUI... functions below
    // ...

    //------------------------------------------------------------------------------
    // MARK: - UI
    //------------------------------------------------------------------------------
    func setupUIForTextEntry() {

        // Hide spinner
        searchTextField.rightViewMode = .never

        // Show clear button
        searchTextField.clearButtonMode = .whileEditing
        searchTextField.becomeFirstResponder()
    }

    //------------------------------------------------------------------------------
    func setupUIForSearching() {

        // Show spinner
        searchTextField.rightViewMode = .always

        // Hide clear button
        searchTextField.clearButtonMode = .never
        searchTextField.resignFirstResponder()
    }

    //------------------------------------------------------------------------------

}

//------------------------------------------------------------------------------
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.