UITextField için metin iç metin?


Yanıtlar:


628

Geçersiz kılma -textRectForBounds:, yalnızca yer tutucu metnin iç metnini değiştirir. Düzenlenebilir metnin iç metnini değiştirmek için ayrıca geçersiz kılmanız gerekir-editingRectForBounds:

// placeholder position
- (CGRect)textRectForBounds:(CGRect)bounds {
     return CGRectInset(bounds, 10, 10);
}

// text position
- (CGRect)editingRectForBounds:(CGRect)bounds {
     return CGRectInset(bounds, 10, 10);
}

10
Bu çözüm benim için çalıştı, ancak CGRectInset'in bir dönüş değerini kullandım (sınırlar, 9, 0); Ayrıca textRectForBounds, editingRectForBounds ve placeholderRectForBounds için bu değeri ayarlamak gerekiyordu.
RyJ

2
Bu çözüm clearButton ile iyi sonuç vermiyor. TextField overlays düğmesinin içindeki metin.
Piotr

Bence, yukarıdaki yöntemlerin geçersiz kılınması UITextFielda UIScrollView.
Bharat Dodeja

2
ClearButton'u yerleştirmek için: - (CGRect)clearButtonRectForBounds:(CGRect)bounds { return CGRectMake(x, y, w, h); } Burada bulundu: stackoverflow.com/questions/5361369/…
Miros

22
CGRectInset'i (sınırlar, 10, 10) çağırmadan önce [super textRectForBounds: bounds] ve [super editingRectForBounds: bounds] 'ı çağırmanızı öneririm. Bu, temizle düğme yer paylaşımı sorununu çözecektir.
mrvincenzo

294

Bunu şu şekilde yapabildim:

myTextField.layer.sublayerTransform = CATransform3DMakeTranslation(5, 0, 0);

Tabii ki QuartzCore'u içe aktarmayı ve ayrıca Çerçeve'yi projenize eklemeyi unutmayın.


38
Yaratıcılık için +1, ancak bu biraz sorunlu, aynı zamanda metin alanındaki düğmeyi de siliyor
Nikita

2
Tüm alt katmanların bir dizisi olan myTextField.layer.sublayers yapabilirsin ... ve onun UIImageView <- X'in bir görüntü olduğunu varsayarım ... ya da belki UIButton ... ya da her birini detaylı olarak döngüye sokabilir ve hangi alt görünüm aittir ... ama myfield.layer.sublayerTüm alt katmanları dönüştürmek ve böylece X düğmesi de hareket ..
chuthan20

Bu çözüm benim için çalışmıyor. Yalnızca Sol ve Üst kenar boşluğunu ayarlayabilirim ancak sağ ve alt olarak ayarlayamam. UITextFieldsağ tarafındaki içerikle çakışıyor.
Bharat Dodeja

2
Bu, alt sınıflama olmadan en iyi çözümdür ve ekrana yerleştirmek için ekstra, gereksiz görünümler gerektirmez! 1!
Rambatino

1
@ jeet.chanchawat Bu resimde sağ taraftaki X düğmesi .. developer.apple.com/library/content/documentation/…
chuthan20

169

Yalnızca sol kenar boşluğuna ihtiyacınız varsa, bunu deneyebilirsiniz:

UItextField *textField = [[UITextField alloc] initWithFrame:...];
UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, textField.frame.size.height)];
leftView.backgroundColor = textField.backgroundColor;
textField.leftView = leftView;
textField.leftViewMode = UITextFieldViewModeAlways;

Benim için çalışıyor. Umarım bu yardımcı olabilir.


17
Bu, yalnızca bir iç metin almak için alt sınıflandırmadan çok daha kolaydır ve solda rastgele bir görünüm eklemenizi sağlar (sağa bir şey koymak için rightView'u da kullanabilirsiniz). Kabul edilen cevaptan daha iyi IMHO.
Kenny Grant

4
+1 kolay, alt sınıflandırma içermez ve metin alanı özellikleriyle çalışmak üzere tasarlanmıştır ('hack' yerine).
So Over It

Üçüncü satır leftView.backgroundColor = textField.backgroundColor;... Bu harika çözüm dışında ... Teşekkürler (:
Aviel Gross

Azdev'in yanıtı kadar zarif / kapsamlı değil, ortak ve basit bir dava için harika bir çözüm!
Rembrandt Q. Einstein

1
Eğer ihtiyacınız olan tek bir metin kutunuz yoksa, alt sınıflama bu cevapta size zaman kazandırır.
Crake

168

UITextField öğesinden türetilmiş bir sınıfta, en azından bu iki yöntemi geçersiz kılın:

- (CGRect)textRectForBounds:(CGRect)bounds;
- (CGRect)editingRectForBounds:(CGRect)bounds;

Ek içeriğiniz yoksa bu kadar basit olabilir:

return CGRectInset(bounds , 10, 10);

UITextField, geçersiz kılabileceğiniz çeşitli konumlandırma yöntemleri sağlar.


2
evet, editRectForBounds'u geçersiz kılmazsanız, metin alanının sol üst köşesinde düzenleme yaparken metni alırsınız. - (CGRect) editingRectForBounds: (CGRect) sınırları {return CGRectInset (sınırları, 10, 10); }
Mark W

1
EditRectForBounds yöntemini
ıɾuǝʞ

5
Bu bana korkunç bir kesmek gibi görünüyor - ayrıca geçersiz - (CGRect)borderRectForBounds:(CGRect)bounds; - (CGRect)placeholderRectForBounds:(CGRect)bounds; - (CGRect)clearButtonRectForBounds:(CGRect)bounds; - (CGRect)leftViewRectForBounds:(CGRect)bounds; - (CGRect)rightViewRectForBounds:(CGRect)bounds;
kılmanız

98

Nasıl hakkında @IBInspectable, @IBDesignablehızlı sınıfa.

@IBDesignable
class TextField: UITextField {
    @IBInspectable var insetX: CGFloat = 6 {
       didSet {
         layoutIfNeeded()
       }
    }
    @IBInspectable var insetY: CGFloat = 6 {
       didSet {
         layoutIfNeeded()
       }
    }

    // placeholder position
    override func textRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds , insetX , insetY)
    }

    // text position
    override func editingRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds , insetX , insetY)
    }
}

Bunu film şeridinizde göreceksiniz.

resim açıklamasını buraya girin

Güncelleme - Swift 3

@IBDesignable
class TextField: UITextField {
    @IBInspectable var insetX: CGFloat = 0
    @IBInspectable var insetY: CGFloat = 0

    // placeholder position
    override func textRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: insetX, dy: insetY)
    }

    // text position
    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: insetX, dy: insetY)
    }
}

1
Y üzerindeki etkiyi istenmeyen buldum, metin için rektifi küçültmek istemiyorum, daha ziyade alanın taban çizgisine doğru itiyorum. Uygulamaları şu şekilde ayarladımlet rect = CGRect(x: bounds.minX, y: bounds.minY + insetY, width: bounds.width, height: bounds.height) return CGRectInset(rect , insetX , 0)
Chris Wagner

1
Ve siz de yer tutucu kullanıyorsanız geçersiz kılın func placeholderRectForBounds (sınırlar: CGRect) -> CGRect {return CGRectInset (sınırlar, insetX, insetY)} `
RameshVel

Tuhaf bir şekilde (metinlerin textRect/ içine yerleştirilmesi editingRect), metin görünür doğrultuyu aştığında kaydırma performansını (en az iOS 12'de) etkiler. 15 iç metinle kaydırma bile durur.
Ixx

29

Net bir düğmeniz varsa, kabul edilen cevap sizin için çalışmaz. Ayrıca Apple'ı gelecekte değişen şeyleri arayarak korumalıyız super.

Bu nedenle, metnin silme düğmesinin üzerine gelmediğinden emin olmak için önce 'varsayılan' değeri alalım super, ardından gerektiği gibi ayarlayalım.

Bu kod, metin alanının üstüne, soluna ve altına 10 piksellik bir metin ekler:

@interface InsetTextField : UITextField

@end


@implementation InsetTextField

// Placeholder position
- (CGRect)textRectForBounds:(CGRect)bounds {
    CGRect rect = [super textRectForBounds:bounds];
    UIEdgeInsets insets = UIEdgeInsetsMake(10, 10, 10, 0);

    return UIEdgeInsetsInsetRect(rect, insets);
}

// Text position
- (CGRect)editingRectForBounds:(CGRect)bounds {
    CGRect rect = [super editingRectForBounds:bounds];
    UIEdgeInsets insets = UIEdgeInsetsMake(10, 10, 10, 0);

    return UIEdgeInsetsInsetRect(rect, insets);
}

// Clear button position
- (CGRect)clearButtonRectForBounds:(CGRect)bounds {
    CGRect rect = [super clearButtonRectForBounds:bounds];

    return CGRectOffset(rect, -5, 0);
}

@end

Not: UIEdgeInsetsMake parametreleri sırasıyla alır: üst , sol , alt , sağ .


Kullanılması textRectForBounds:ve editingRectForBounds:yöntemler olmadan clearButtonRectForBounds: iOS 7+ benim için çalıştı üzerinde.
Stunner

clearButtonRectForBounds:temizle düğmesini biraz sola sürüklemeye yardımcı olur. Dışarıda bırakmak isteyebilirsiniz. Metin alanım koyu bir arka plandaydı ve temizle düğmesi sağ tarafta biraz fazla dolgu gerektiriyordu.
Chris Nolet

Tuhaf bir şekilde, bu metin görünür doğrultuyu aştığında kaydırma performansını (en az iOS 12'de) etkiler. 15 iç metinle kaydırma bile durur.
Ixx

22

Hızlı bir çözüm sağlayacağımı düşündüm

import UIKit

class TextField: UITextField {
    let inset: CGFloat = 10

    // placeholder position
    override func textRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds , inset , inset)
    }

    // text position
    override func editingRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds , inset , inset)
    }

    override func placeholderRectForBounds(bounds: CGRect) -> CGRect {
        return CGRectInset(bounds, inset, inset) 
    }
}

Hızlı 3+

import UIKit

class TextField: UITextField {
    let inset: CGFloat = 10

    // placeholder position
    override func textRect(forBounds: CGRect) -> CGRect {
        return forBounds.insetBy(dx: self.inset , dy: self.inset)
    }

    // text position
    override func editingRect(forBounds: CGRect) -> CGRect {
        return forBounds.insetBy(dx: self.inset , dy: self.inset)
    }

    override func placeholderRect(forBounds: CGRect) -> CGRect {
        return forBounds.insetBy(dx: self.inset, dy: self.inset)
    }
}

2
Unutma override func placeholderRectForBounds(bounds: CGRect) -> CGRect { return CGRectInset(bounds, inset, inset) }
Eugene Braginets

Swift 3'te 'CGRect.insetBy ()' yöntemini kullanmalısınız
Den

1
En azından iOS 11'de, geçersiz kılarsanız textRectForBounds, yer tutucu da etkilenir - bu nedenle yer tutucu geçersiz kılma eklenmesi, yer tutucuyu 10pt daha ekler. Eğer aradığınız şey buysa, 👍🏼, ama değilse, farkında olmak iyidir.
DesignatedNerd

Tuhaf bir şekilde, bu metin görünür doğrultuyu aştığında kaydırma performansını (en az iOS 12'de) etkiler. 15 iç metinle kaydırma bile durur.
Ixx

14

Kullanmak textRectForBounds:doğru yaklaşımdır. Bunu kullanabilmem için alt sınıfımda tamamladım textEdgeInsets. Bkz. SSTextField .


Bu yaklaşım, SSToolkit bölmesini içe aktarmak için cocoapod'ları kullanmanın yanı sıra harika çalışıyor - bence bu en güzel yol.
Chris

Teşekkürler Chris! Bunu yararlı bulduğunuz için memnunuz.
Sam Soffes

14

hızlı

 class TextField: UITextField {

    let inset: CGFloat = 8

    // placeholder position
    override func textRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: inset, dy: inset)
    }

    // text position
    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        return bounds.insetBy(dx: inset, dy: inset)
    }
}

Tuhaf bir şekilde, bu metin görünür doğrultuyu aştığında kaydırma performansını (en az iOS 12'de) etkiler. 15 iç metinle kaydırma bile durur.
Ixx

12

Daha kolay bir çözüm arayan insanlar için.

UITextFieldİçini ekleyin a UIView. Metin alanının etrafındaki bir metni simüle etmek için 10 piksel sola yaslıyorum ve genişlik görünümden 20 piksel daha az. Metin alanının çevresindeki yuvarlak köşe kenarlığı için görünümün kenarlığını kullanın

viewBG.layer.cornerRadius = 8.0;
viewBG.layer.borderColor = [UIColor darkGrayColor].CGColor;
viewBG.layer.borderWidth = 1.0;

2
Dürüst olmak gerekirse, sadece bir UIView'i UITextField'ın arkasına koymak en iyi ve en basit çözümdür. UITextField öğesini şeffaf ve bitmiş yapın. Bir UITextView ile hizaladım - yaklaşık 6 piksel iç metin olduğu ortaya çıkıyor. Bir alt sınıf oluşturmaktan çok daha kolay ve daha esnek ...
n13

Bu yaklaşımla ilgili bir sorun, kaydırma çubuğunun görüneceği konumdur.
Doug Amos

@DougAmos Hangi kaydırma çubuğu? UITextViewBelki de mi bahsediyorsun ?
anlam-önemli

12

LeftView ayarını yaparak UITextField için metin iç metin ayarlayabilirsiniz.

Bunun gibi:

UITextField *yourTextField = [[UITextField alloc] init];
UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 5)];
leftView.backgroundColor = [UIColor clearColor];
yourTextField.leftViewMode = UITextFieldViewModeAlways;
yourTextField.leftView = leftView;

1
Bir simge için sol görünümü de kullanmanız gerektiğinde, bu çalışamaz
Reaper

@ Bu yöntemi bir görüntü için de kullanabilirsiniz. istediğiniz dolgu miktarını görüntü görüntüleme çerçevesinin genişliğine ekleyin ve içerik modunu merkeze ayarlayın. imageView.contentMode = UIViewContentMode.Center imageView.frame = CGRectMake(0.0, 0.0, imageView.image!.size.width + 16.0, imageView.image!.size.height)
Andy

bu çok acayip. eki ayarlamak için zaten bir textRectForBounds yöntemi var
Gerald

12

hızlı

    // adjust place holder text
    let paddingView = UIView(frame: CGRectMake(0, 0, 10, usernameOrEmailField.frame.height))
    usernameOrEmailField.leftView = paddingView
    usernameOrEmailField.leftViewMode = UITextFieldViewMode.Always

1
Bu gerçekten ucuz ve kolay bir çözümdür. Teşekkürler!
shnaz

11

UITextField öğesine dolgu eklemek için iyi bir yaklaşım, UITextField alt sınıfını oluşturmak ve bir edgeInsets özelliği eklemektir. Daha sonra edgeInsets öğesini ayarlarsınız ve UITextField buna göre çizilir. Bu, özel bir leftView veya rightView setiyle de doğru şekilde çalışacaktır.

OSTextField.h

#import <UIKit/UIKit.h>

@interface OSTextField : UITextField

@property (nonatomic, assign) UIEdgeInsets edgeInsets;

@end

OSTextField.m

#import "OSTextField.h"

@implementation OSTextField

- (id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        self.edgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
    }
    return self;
}

-(id)initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if(self){
        self.edgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
    }
    return self;
}

- (CGRect)textRectForBounds:(CGRect)bounds {
    return [super textRectForBounds:UIEdgeInsetsInsetRect(bounds, self.edgeInsets)];
}

- (CGRect)editingRectForBounds:(CGRect)bounds {
    return [super editingRectForBounds:UIEdgeInsetsInsetRect(bounds, self.edgeInsets)];
}

@end

İyi cevap. Eksik mal
tedarik

6

Swift 3 / Arayüz oluşturucuda tasarlanabilir / Ayrı yatay ve dikey böcekler / kutudan çıkar çıkmaz

@IBDesignable
class TextFieldWithPadding: UITextField {

@IBInspectable var horizontalInset: CGFloat = 0
@IBInspectable var verticalInset: CGFloat = 0

override func textRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: horizontalInset, dy: verticalInset)
}

override func editingRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: horizontalInset , dy: verticalInset)
}

override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: horizontalInset, dy: verticalInset)
}
}

kullanımı:

kullanım

&

resim açıklamasını buraya girin


5

Bunu IB'de yaptım ve burada biraz daha uzun olan textView'in arkasında bir UIView oluşturdum. TextField arka plan rengini temizlemek için ayarlanmış olarak. resim açıklamasını buraya girin


5

Alt sınıf yapmadan bulduğum en hızlı yol:

UIView *spacerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10., 10.)];
[textField setLeftViewMode:UITextFieldViewModeAlways];
[textField setLeftView:spacerView];

Swift'te:

let spacerView = UIView(frame:CGRect(x:0, y:0, width:10, height:10))
textField.leftViewMode = UITextFieldViewMode.Always
textField.leftView = spacerView

4

İşte Swift 3'te yazılmış aynı alt sınıf UITextField. Göreceğiniz gibi Swift'in önceki sürümlerinden oldukça farklı:

import UIKit

class MyTextField: UITextField
    {
    let inset: CGFloat = 10

    // placeholder position
    override func textRect(forBounds bounds: CGRect) -> CGRect
        {
        return bounds.insetBy(dx: inset, dy: inset)
        }

    // text position
    override func editingRect(forBounds bounds: CGRect) -> CGRect
        {
        return bounds.insetBy(dx: inset, dy: inset)
        }

    override func placeholderRect(forBounds bounds: CGRect) -> CGRect
        {
        return bounds.insetBy(dx: inset, dy: inset)
        }
    }

Bu arada, sadece bir tarafın iç kısmını kontrol etmek istiyorsanız, aşağıdakine benzer bir şey de yapabilirsiniz. UITextField öğesinin üstüne bir görüntü yerleştirirseniz, ancak kullanıcının metin alanında görünmesini istiyorsanız, yalnızca sol iç metni ayarlamaya ilişkin bu özel örnek kullanışlı olur:

    override func editingRect(forBounds bounds: CGRect) -> CGRect
        {
        return CGRect.init(x: bounds.origin.x + inset, y: bounds.origin.y, width: bounds.width - inset, height: bounds.height)
        }

4

Swift 4.2 sürümü:

import UIKit

class InsetTextField: UITextField {

  let inset: CGFloat = 10

  override func textRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: inset, dy: inset)
  }


  override func editingRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: inset, dy: inset)
  }

  override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
    return bounds.insetBy(dx: inset, dy: inset)
  }

}

Tuhaf bir şekilde, bu metin görünür doğrultuyu aştığında kaydırma performansını (en az iOS 12'de) etkiler. 15 iç metinle kaydırma bile durur.
Ixx

3

Metnin bir metin alanı içindeki konumunu UITextField, -textRectForBounds:yöntemi bir alt sınıf haline getirip yöntemin üzerine yazarak ayarlayabilirsiniz .


3

UITextField@Adam Waite'nin işaret ettiği gibi, yöntemleri zaten uyguladığından alt sınıflara ayırmanız saçmadır. İşte kategoriler depomuzda da bulunan bir fabrika yöntemini ortaya çıkaran hızlı bir uzantı :

private class InsetTextField: UITextField {
    var insets: UIEdgeInsets

    init(insets: UIEdgeInsets) {
        self.insets = insets
        super.init(frame: CGRectZero)
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("not intended for use from a NIB")
    }

    // placeholder position
    override func textRectForBounds(bounds: CGRect) -> CGRect {
        return super.textRectForBounds(UIEdgeInsetsInsetRect(bounds, insets))
    }

    // text position
    override func editingRectForBounds(bounds: CGRect) -> CGRect {
        return super.editingRectForBounds(UIEdgeInsetsInsetRect(bounds, insets))
    }
}

extension UITextField {

    class func textFieldWithInsets(insets: UIEdgeInsets) -> UITextField {
        return InsetTextField(insets: insets)
    }

}

Cevabınızdaki bağlantı öldü, lütfen güncelleyebilir misiniz?
WendiKidd

@WendiKidd
Christopher Pickslay

2

Sol, üst, sağ ve alt iç metinleri destekleyen ve düğme konumlandırmayı da destekleyen UITextField öğesinin alt sınıflarını kullandım.

MRDInsetTextField.h

#import <UIKit/UIKit.h>

@interface MRDInsetTextField : UITextField

@property (nonatomic, assign) CGRect inset;

@end

MRDInsetTextField.m

#import "MRDInsetTextField.h"

@implementation MRDInsetTextField

- (id)init
{
    self = [super init];
    if (self) {
        _inset = CGRectZero;
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        _inset = CGRectZero;
    }
    return self;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        _inset = CGRectZero;
    }
    return self;
}

- (void)setInset:(CGRect)inset {
    _inset = inset;

    [self setNeedsLayout];
}

- (CGRect)getRectForBounds:(CGRect)bounds withInset:(CGRect)inset {

    CGRect newRect = CGRectMake(
                         bounds.origin.x + inset.origin.x,
                         bounds.origin.y + inset.origin.y,
                         bounds.origin.x + bounds.size.width - inset.origin.x - inset.size.width,
                         bounds.origin.y + bounds.size.height - inset.origin.y - inset.size.height
                         );

    return newRect;
}

- (CGRect)textRectForBounds:(CGRect)bounds {
    return [self getRectForBounds:[super textRectForBounds:bounds] withInset:_inset];
}

- (CGRect)placeholderRectForBounds:(CGRect)bounds {
    return [self getRectForBounds:bounds withInset:_inset];
}

- (CGRect)editingRectForBounds:(CGRect)bounds {
    return [self getRectForBounds:[super editingRectForBounds:bounds] withInset:_inset];
}

- (CGRect)clearButtonRectForBounds:(CGRect)bounds {
    return CGRectOffset([super clearButtonRectForBounds:bounds], -_inset.size.width, _inset.origin.y/2 - _inset.size.height/2);
}

@end

* _SomeTextField * öğesinin MRDInsetTextField özel sınıfıyla uç / film şeridi görünümünden geldiği kullanım örneği

[(MRDInsetTextField*)_someTextField setInset:CGRectMake(5, 0, 5, 0)]; // left, top, right, bottom inset

Teşekkür ederim. Yine de kodunuza bir öneri - neden CGRect'i içeride kullandınız, UIEdgeInsets için değil?
sha

2

Bu, diğer örnekler kadar kısa değildir, ancak bu sorunun çözümü için tamamen farklı bir yaklaşım gerektirir. Not: Düzeltme çubuğu hala sol kenarla aynı hizada başlayacaktır, ancak yazıldığında / görüntülendiğinde metin düzgün girintili olacaktır. Bu, yalnızca sol bir kenar boşluğu arıyorsanız ve zaten kullanıyorsanızUITextFieldDelegate metin alanlarınız için , . Hem varsayılan metin niteliklerini hem de yazma niteliklerini ayarlamanız gerekir. Metin alanını oluştururken varsayılan metin niteliklerini ayarlarsınız. Temsilcide ayarlamanız gereken yazma özellikleri. Ayrıca bir yer tutucu kullanıyorsanız, bunu da aynı kenar boşluğuna ayarlamak istersiniz. Tamamen koyarsanız böyle bir şey elde edersiniz.

İlk önce UITextFieldsınıfta bir kategori oluşturun .

//  UITextField+TextAttributes.h

#import <UIKit/UIKit.h>

@interface UITextField (TextAttributes)

- (void)setIndent:(CGFloat)indent;

@end


//  UITextField+TextAttributes.m
#import "UITextField+TextAttributes.h"

@implementation UITextField (TextAttributes)

- (void)setTextAttributes:(NSDictionary*)textAttributes indent:(CGFloat)indent
{
    if (!textAttributes) return;

    NSMutableParagraphStyle *paragraphStyle = [textAttributes objectForKey:NSParagraphStyleAttributeName];
    paragraphStyle.firstLineHeadIndent = indent;
    paragraphStyle.headIndent = indent;
}

- (void)setIndent:(CGFloat)indent
{
   [self setTextAttributes:self.defaultTextAttributes indent:indent];
   [self setTextAttributes:self.typingAttributes indent:indent];
}

@end

Ardından, yerleştirilmiş tutucular kullanıyorsanız, aynı girintiyi ayarlayan ilişkilendirilmiş bir yer tutucu kullandığınızdan emin olun. Aşağıdaki gibi uygun özelliklere sahip varsayılan bir ilişkilendirilmiş sözlük oluşturun:

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.firstLineHeadIndent = 7;
paragraphStyle.headIndent = 7;
NSDictionary *placeholderAttributes = [NSDictionary dictionaryWithObjectsAndKeys: paragraphStyle, NSParagraphStyleAttributeName, nil];

Ardından, yukarıdaki kategoriyi içe aktarın ve bir metin alanı oluşturduğunuzda varsayılan girintiyi ayarlayın, temsilci seçin ve yukarıda tanımlanan varsayılan yer tutucu niteliklerini kullanın. Örneğin:

UITextField *textField = [[UITextField alloc] init];
textField.indent = 7;
textField.delegate = self;
textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"Placeholder Text" attributes:placeholderAttributes];

Son olarak, delegede, textFieldDidBeginEditingyöntemi uygulayın, şöyle:

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    textField.indent = 7;
}

defaultTextAttributesİçerdiği varsayım NSMutableParagraphStyleoldukça tehlikelidir .. MutableCop tüm bu kopya.
Ben Sinclair

1

Ben normalde alt sınıf kaçınmak deneyin ama zaten varsa bu çalışır:

// add a property 
@property (nonatomic) UIEdgeInsets edgeInsets;

// and override:

- (CGRect)textRectForBounds:(CGRect)bounds
{
    return [super textRectForBounds:UIEdgeInsetsInsetRect(bounds, self.edgeInsets)];
}

- (CGRect)editingRectForBounds:(CGRect)bounds
{
    return [super editingRectForBounds:UIEdgeInsetsInsetRect(bounds, self.edgeInsets)];
}

Alt sınıflardan kaçınmanızın bir nedeni var mı? Bu ise geçerli bir tasarım paradigması.
Stunner

1

Alt sınıfa ihtiyaç duymayan başka bir çözüm atmak için:

UITextField *txtField = [UITextField new];
txtField.borderStyle = UITextBorderStyleRoundedRect;

// grab BG layer
CALayer *bgLayer = txtField.layer.sublayers.lastObject;
bgLayer.opacity = 0.f;

// add new bg view
UIView *bgView = [UIView new];
bgView.backgroundColor = [UIColor whiteColor];
bgView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
bgView.userInteractionEnabled = NO;

[txtField addSubview: bgView];
[txtField sendSubviewToBack: bgView];

Orijinal UITextField Sabit UITextField

İOS 7 ve iOS 8 ile test edildi. Her ikisi de çalışıyor. Yine de Apple'ın UITextField'ın katman hiyerarşisini değiştirmesi, işleri kötü bir şekilde bozuyor olabilir.


1

Aşağıda, her ikisi de özelleştirilebilir eklerle Arayüz Oluşturucu'da ayarlanmış bir leftView (özel simge) ve özel bir temizle düğmesi içeren kapsamlı bir Swift yanıtı bulunmaktadır.

import UIKit

@IBDesignable
class InsetTextField: UITextField {
@IBInspectable var leftInset:CGFloat = 0
@IBInspectable var rightInset:CGFloat = 0
@IBInspectable var icon:UIImage? { didSet {
    let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 16, height: 16))
    imageView.image = icon
    self.leftView = imageView
    self.leftViewMode = .Always
} }

@IBInspectable var clearButton:UIImage? { didSet {
    let button = UIButton(type: .Custom)
    button.setImage(clearButton, forState: .Normal)
    button.addTarget(self, action: "clear", forControlEvents: UIControlEvents.TouchUpInside)
    button.frame = CGRect(x: 0, y: 0, width: 18, height: 18)
    self.rightView = button
    self.rightViewMode = .WhileEditing
} }

func clear() {
    self.text = ""
}

override func leftViewRectForBounds(bounds: CGRect) -> CGRect {
    var height:CGFloat = 0
    var width:CGFloat = 0
    if let leftView = self.leftView {
        height = leftView.bounds.height
        width = leftView.bounds.width
    }

    return CGRect(x: leftInset, y: bounds.height/2 - height/2, width: width, height: height)
}

override func rightViewRectForBounds(bounds: CGRect) -> CGRect {
    var height:CGFloat = 0
    var width:CGFloat = 0
    if let rightView = self.rightView {
        height = rightView.bounds.height
        width = rightView.bounds.width
    }

    return CGRect(x: bounds.width - width - rightInset, y: bounds.height/2 - height/2, width: width, height: height)
}

}

1

Gerçekten çalışan ve tüm vakaları kapsayan bir çözüm:

  • Kullanmalı mıyım offsetBydeğil insetBy.
  • Ayrıca orijinal almak için süper işlevini çağırmalısınız Rect.
  • Sınırlar hatalı. orijinal X, Y'yi dengelemeniz gerekir. Sınırlar sıfır, X, Y'ye sahiptir.
  • Orijinal x, y, örneğin UITextField öğesinin leftView ayarını yaparken sıfırdan farklı olabilir.

Örneklem:

override func textRect(forBounds bounds: CGRect) -> CGRect {
    return super.textRect(forBounds: bounds).offsetBy(dx: 0.0, dy: 4)
}


override func editingRect(forBounds bounds: CGRect) -> CGRect {
    return super.editingRect(forBounds: bounds).offsetBy(dx: 0.0, dy: 4)
}

0

Yalnızca TOP ve LEFT girintisini değiştirmek istiyorsanız

// yer tutucu konumu

- (CGRect)textRectForBounds:(CGRect)bounds {

CGRect frame = bounds;
frame.origin.y = 3;
 frame.origin.x = 5;
bounds = frame;
return CGRectInset( bounds , 0 , 0 );
}

// metin konumu

- (CGRect)editingRectForBounds:(CGRect)bounds {

CGRect frame = bounds;
frame.origin.y = 3;
 frame.origin.x = 5;
bounds = frame;
return CGRectInset( bounds , 0 , 0 );
}

-1

Alt sınıf olmadan hızlı çözüm ve ayrıca denetlenebilir

extension UITextField {
    @IBInspectable var textInsets: CGPoint {
            get {
                return CGPoint.zero
            }
            set {
                layer.sublayerTransform = CATransform3DMakeTranslation(newValue.x, newValue.y, 0);
            }
        }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.