UITextField에 텍스트 삽입?


답변:


628

재정의 -textRectForBounds:하면 자리 표시 자 텍스트의 삽입 만 변경됩니다. 편집 가능한 텍스트의 삽입을 변경하려면 재정의해야합니다.-editingRectForBounds:

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

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

10
이 솔루션은 CGRectInset (bounds, 9, 0)의 반환 값을 사용했지만 저에게 효과적이었습니다. 또한 textRectForBounds, editingRectForBounds 및 placeholderRectForBounds에이 값을 설정해야했습니다.
RyJ 2019

2
이 솔루션은 clearButton과 잘 작동하지 않습니다. TextField 안의 텍스트는 버튼을 오버레이합니다.
Piotr

위의 메소드를 재정의하면에있는 경우 스크롤 속도가 느려질 것이라고 생각 UITextField합니다 UIScrollView.
Bharat Dodeja

2
ClearButton을 배치하려면 - (CGRect)clearButtonRectForBounds:(CGRect)bounds { return CGRectMake(x, y, w, h); } 여기를 클릭하십시오 : stackoverflow.com/questions/5361369/…
Miros

22
CGRectInset (bounds, 10, 10)을 호출하기 전에 [super textRectForBounds : bounds] 및 [super editingRectForBounds : bounds]를 호출하는 것이 좋습니다. 이것은 명확한 버튼 오버레이 문제를 해결합니다.
mrvincenzo

294

나는 그것을 통해 할 수 있었다 :

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

물론 QuartzCore를 가져 와서 프로젝트에 프레임 워크를 추가해야합니다.


38
창의력을 위해 +1이지만 약간 문제가 있지만 텍스트 필드 내부의 삭제 버튼도 움직입니다.
Nikita

2
모든 하위 레이어의 배열 인 myTextField.layer.sublayers를 수행 할 수 있습니다 .UIImageView <-경우 X가 이미지라고 가정합니다. 또는 아마도 UIButton ... 또는 각 루프를 철저히 반복하여 볼 수 있습니다 어느 것이 어느 서브 뷰에 속하는지 ... myfield.layer.sublayer 모든 서브 레이어를 변환하여 X 버튼도 움직입니다.
chuthan20

이 솔루션은 저에게 효과적이지 않습니다. 왼쪽과 위쪽 여백 만 설정할 수 있지만 오른쪽과 아래쪽은 설정할 수 없습니다. UITextField오른쪽의 내용과 겹칩니다.
Bharat Dodeja

2
이것은 서브 클래 싱이없는 최상의 솔루션이며 화면에 불필요한 불필요한 뷰를 배치 할 필요가 없습니다! +1!
Rambatino

1
@ jeet.chanchawat이 사진의 오른쪽에있는 X 버튼 .. developer.apple.com/library/content/documentation/…
chuthan20

169

왼쪽 여백이 필요하면 다음을 시도하십시오.

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;

그것은 나를 위해 작동합니다. 이것이 도움이되기를 바랍니다.


17
이것은 서브 클래스를 작성하는 것보다 삽입을 얻는 것보다 훨씬 쉽고 왼쪽에 임의의 뷰를 추가 할 수 있습니다 (rightView를 사용하여 오른쪽에 무언가를 넣을 수도 있습니다). 허용 된 답변 IMHO보다 낫습니다.
Kenny Grant

4
+1 쉽고 서브 클래 싱이 없으며 텍스트 필드 속성 ( '해킹'이 아닌)과 함께 작동하도록 설계되었습니다.
So Over It

세 번째 줄은 leftView.backgroundColor = textField.backgroundColor;... 그 훌륭한 솔루션 이외의 것입니다 ... 감사합니다 (:
Aviel Gross

azdev의 대답만큼 우아하고 철저하지는 않지만 일반적이고 간단한 사례에 대한 훌륭한 솔루션입니다!
렘브란트 Q. 아인슈타인

1
하나의 텍스트 상자가 필요한 경우가 아니라면 서브 클래 싱을 통해이 답변보다 많은 시간을 절약 할 수 있습니다.
Crake

168

UITextField에서 파생 된 클래스에서이 두 가지 이상의 메서드를 재정의하십시오.

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

추가 컨텐츠가없는 경우 다음과 같이 간단 할 수 있습니다.

return CGRectInset(bounds , 10, 10);

UITextField는 재정의 할 수있는 몇 가지 위치 지정 방법을 제공합니다.


2
예, editingRectForBounds를 재정의하지 않으면 텍스트 필드의 왼쪽 상단에서 편집 할 때 텍스트가 표시됩니다. -(CGRect) editingRectForBounds : (CGRect) 바운드 {return CGRectInset (bounds, 10, 10); }
Mark W

1
editingRectForBounds 메소드를 다음과 같이 통합하기 위해 답변을 편집했습니다.
ıɾuǝʞ

5
이것은 나에게 끔찍한 해킹처럼 보인다-당신은 또한 무시해야 할 것입니다- (CGRect)borderRectForBounds:(CGRect)bounds; - (CGRect)placeholderRectForBounds:(CGRect)bounds; - (CGRect)clearButtonRectForBounds:(CGRect)bounds; - (CGRect)leftViewRectForBounds:(CGRect)bounds; - (CGRect)rightViewRectForBounds:(CGRect)bounds;
Zorayr

98

어떻게 약 @IBInspectable, @IBDesignable신속 클래스입니다.

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

스토리 보드에서 볼 수 있습니다.

여기에 이미지 설명을 입력하십시오

업데이트-스위프트 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에 대한 효과가 바람직하지 않다는 것을 알았습니다. 텍스트의 rect를 축소하고 싶지 않고 오히려 필드의 기준선을 향해 조금 내리고 싶지 않습니다. 구현을 다음과 같이 조정했습니다.let rect = CGRect(x: bounds.minX, y: bounds.minY + insetY, width: bounds.width, height: bounds.height) return CGRectInset(rect , insetX , 0)
Chris Wagner

1
요 자리 '재정의 FUNC의 placeholderRectForBounds 사용하는 경우 그리고 이것도 추가 (범위 : CGRect을) -> CGRect {반환 CGRectInset (경계, insetX, insetY)}`
RameshVel

이상하게도 (insets in textRect/ editingRect)는 텍스트가 보이는 rect에 넘칠 때 스크롤 성능 (iOS 12 이상)에 영향을 미칩니다. 15의 삽입으로 스크롤을 멈 춥니 다.
Ixx

29

명확한 버튼이 있으면 허용 된 답변이 효과가 없습니다. 우리는 또한 앞으로 전화하여 Apple이 변화하는 것을 막아야 super합니다.

따라서 텍스트가 지우기 버튼과 겹치지 않게하려면 super먼저 '기본'값을 가져온 다음 필요에 따라 조정 해 보겠습니다 .

이 코드는 텍스트 필드의 위쪽, 왼쪽 및 아래쪽에 10px 삽입을 추가합니다.

@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

참고 : UIEdgeInsetsMake는 top , left , bottom , right 순서로 매개 변수를 사용합니다 .


사용 textRectForBounds:editingRectForBounds:방법 이없는 clearButtonRectForBounds: 아이폰 OS 7+이 나를 위해 일에.
Stunner 2016 년

clearButtonRectForBounds:지우기 버튼을 약간 왼쪽으로 조금씩 움직입니다. 당신은 그것을 떠나고 싶을 수도 있습니다. 내 텍스트 필드는 어두운 배경에 있었고 지우기 버튼에는 오른쪽에 약간의 추가 패딩이 필요했습니다.
Chris Nolet 2016 년

이상하게도 텍스트가 보이는 rect에 넘치면 스크롤 성능 (iOS 12 이상)에 영향을 미칩니다. 15의 삽입으로 스크롤을 멈 춥니 다.
Ixx

22

스위프트 솔루션을 공급할 것이라고 생각했습니다.

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

스위프트 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
잊지 마세요 override func placeholderRectForBounds(bounds: CGRect) -> CGRect { return CGRectInset(bounds, inset, inset) }
Eugene Braginets

스위프트 3에서는 'CGRect.insetBy ()'메소드를 사용해야합니다
Den

1
iOS 11에서 적어도 재정의 textRectForBounds하면 자리 표시 자에도 영향을 미치므로 자리 표시 자 재정의를 추가하면 자리 표시자가 10pt 더 추가됩니다. 그것이 당신이 찾고있는 것이라면, 👍🏼, 그렇지 않다면, 알아 두는 것이 좋습니다.
DesignatedNerd

이상하게도 텍스트가 보이는 rect에 넘치면 스크롤 성능 (iOS 12 이상)에 영향을 미칩니다. 15의 삽입으로 스크롤을 멈 춥니 다.
Ixx

14

사용하는 textRectForBounds:것이 올바른 방법입니다. 나는 이것을 서브 클래스에 싸서 간단하게 사용할 수 있습니다 textEdgeInsets. SSTextField를 참조하십시오 .


SSToolkit 포드를 가져 오기 위해 cocoapod를 사용하는 것과 함께이 방법은 훌륭하게 작동합니다. 이것이 가장 쉬운 방법이라고 생각합니다.
Chris

고마워 크리스! 도움이 되셨 다니 다행입니다.
Sam Soffes

14

빠른

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

이상하게도 텍스트가 보이는 rect에 넘치면 스크롤 성능 (iOS 12 이상)에 영향을 미칩니다. 15의 삽입으로 스크롤을 멈 춥니 다.
Ixx

12

더 쉬운 솔루션을 찾는 사람들에게.

UITextField내부를 추가하십시오 UIView. 텍스트 필드 주위의 삽입을 시뮬레이션하려면 왼쪽으로 10px를 유지하고 너비는보기보다 20px 작습니다. 텍스트 필드 주위의 둥근 모서리 테두리의 경우 뷰의 테두리를 사용하십시오.

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

2
솔직히 UITextField 뒤에 UIView를 두는 것이 가장 좋고 가장 간단한 솔루션입니다. UITextField를 투명하고 완성하십시오. UITextView와 정렬했습니다. 삽입 된 약 6 픽셀로 밝혀졌습니다. 서브 클래스를 만드는 것보다 훨씬 쉽고 유연합니다 ...
n13

이 방법의 문제점은 스크롤 막대가 나타나는 위치입니다.
Doug Amos

@DougAmos 무슨 스크롤바? 당신은 UITextView아마 언급하고 있습니까?
의미 문제

12

leftView를 설정하여 UITextField에 텍스트 삽입을 설정할 수 있습니다.

이처럼 :

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
아이콘을 위해 왼쪽보기를 사용해야 할 때도 작동하지 않습니다
Reaper

@Reaper이 방법은 이미지에도 적용됩니다. 원하는 패딩 양을 이미지 프레임의 너비에 추가하고 contentmode를 center로 설정하십시오. imageView.contentMode = UIViewContentMode.Center imageView.frame = CGRectMake(0.0, 0.0, imageView.image!.size.width + 16.0, imageView.image!.size.height)
Andy

이것은 너무 해키입니다. 삽입을 설정하기위한 textRectForBounds 메소드가 이미 있습니다
Gerald

12

빠른

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

1
이것은 정말 저렴하고 쉬운 해결 방법입니다. 감사!
shnaz 2016 년

11

UITextField에 패딩을 추가하는 좋은 방법은 UITextField를 서브 클래스로 만들고 edgeInsets 속성을 추가하는 것입니다. 그런 다음 edgeInsets를 설정하면 UITextField가 그에 따라 그려집니다. 사용자 정의 leftView 또는 rightView 세트에서도 올바르게 작동합니다.

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

좋은 대답입니다. 잃어버린 재산을 공급합니다 :-)
phatmann

6

스위프트 3 / 인터페이스 빌더에서 디자인 가능 / 수평 및 수직 곤충 분리 / 즉시 사용 가능

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

용법:

용법

&

여기에 이미지 설명을 입력하십시오


5

나는 조금 더 긴 textView 뒤에 UIView를 만든 IB 에서이 작업을 수행했습니다. textField 배경색이 clear로 설정되어 있습니다. 여기에 이미지 설명을 입력하십시오


5

서브 클래스를 수행하지 않고 내가 찾은 가장 빠른 방법입니다.

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

스위프트에서 :

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

4

다음은 Swift 3으로 작성된 동일한 서브 클래스 UITextField입니다. 이전 버전의 Swift와는 상당히 다릅니다.

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

또한 한쪽의 삽입을 제어하려는 경우 다음과 같은 작업을 수행 할 수도 있습니다. 왼쪽 삽입 만 조정하는이 특정 예제는 UITextField 위에 이미지를 배치하지만 사용자가 텍스트 필드 내에있는 것처럼 보이게하려면 유용합니다.

    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

스위프트 4.2 버전 :

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

}

이상하게도 텍스트가 보이는 rect에 넘치면 스크롤 성능 (iOS 12 이상)에 영향을 미칩니다. 15의 삽입으로 스크롤을 멈 춥니 다.
Ixx

3

텍스트 필드를 텍스트의 하위 클래스로 만들고 메서드를 UITextField재정 의하여 텍스트 필드 내에서 텍스트의 위치를 ​​조정할 수 있습니다 -textRectForBounds:.


3

UITextField@Adam Waite가 지적했듯이 이미 메소드를 구현하기 때문에 서브 클래스를 작성해야합니다 . 다음은 repo 카테고리 에서 사용 가능한 팩토리 메소드를 표시하는 빠른 확장입니다 .

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

}

답변의 링크가 작동하지 않습니다. 업데이트 할 수 있습니까?
WendiKidd

URL을 @WendiKidd 고정
크리스토퍼 Pickslay

2

왼쪽, 위쪽, 오른쪽 및 아래쪽 삽입 및 명확한 버튼 위치를 지원하는 UITextField를 서브 클래 싱했습니다.

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 *가 MRDInsetTextField 사용자 정의 클래스가있는 펜촉 / 스토리 보드보기에서 제공되는 사용 예

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

감사합니다. 코드에 대한 한 가지 제안-왜 UIEdgeInsets가 아닌 inset에 CGRect를 사용 했습니까?
sha

2

이것은 다른 예만큼 짧지는 않지만이 문제를 해결하기 위해 완전히 다른 접근법을 취합니다. 캐럿은 여전히 ​​왼쪽 가장자리로 플러시되기 시작하지만 입력 / 표시 할 때 텍스트가 제대로 들여 쓰기됩니다. 왼쪽 여백을 찾고 이미 사용중인 경우 서브 클래 싱없이 작동합니다UITextFieldDelegate 텍스트 필드에 합니다. 기본 텍스트 속성과 입력 속성을 모두 설정해야합니다. 텍스트 필드를 만들 때 기본 텍스트 속성을 설정합니다. 델리게이트에서 설정해야하는 입력 속성입니다. 자리 표시자를 사용하는 경우에도 동일한 여백을 설정하려고합니다. 그것을 모두 넣으면 이와 같은 것을 얻을 수 있습니다.

먼저 UITextField수업 에서 카테고리를 만듭니다 .

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

그런 다음 자리 표시자를 사용하는 경우 지정된 자리 표시 자 설정을 동일한 들여 쓰기로 설정해야합니다. 다음과 같이 적절한 속성으로 기본 속성 사전을 작성하십시오.

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

그런 다음 위 카테고리를 가져오고 텍스트 필드를 작성할 때마다 기본 들여 쓰기, 위임을 설정하고 위에 정의 된 기본 플레이스 홀더 속성을 사용하십시오. 예를 들면 다음과 같습니다.

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

마지막으로 델리게이트 textFieldDidBeginEditing에서 다음과 같이 메소드를 구현하십시오 .

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

가정 defaultTextAttributes포함은 NSMutableParagraphStyle.. 내가 차라리 mutableCopy이 모든 것을 아주 위험하다.
벤 싱클레어

1

나는 일반적으로 서브 클래스 화를 피하려고 시도하지만 이미 가지고 있다면 작동합니다.

// 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)];
}

서브 클래 싱을 피하는 이유는 무엇입니까? 그것은 이다 유효한 디자인 패러다임.
Stunner 2016 년

1

서브 클래 싱이 필요없는 다른 솔루션을 던지려면 :

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];

원본 UITextField 고정 UITextField

iOS 7 및 iOS 8에서 테스트되었습니다. 여전히 Apple이 UITextField의 계층 구조를 수정하여 문제를 심각하게 망칠 가능성이 있습니다.


1

다음은 사용자 정의 가능한 삽입물이있는 인터페이스 빌더에서 설정된 leftView (사용자 정의 아이콘) 및 사용자 정의 지우기 단추를 포함하는 포괄적 인 Swift 답변입니다.

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

실제로 작동하고 모든 경우를 다루는 솔루션 :

  • 사용 offsetBy하지 않아야 insetBy합니다.
  • 원본을 얻으려면 super 함수를 호출해야합니다 Rect.
  • 경계가 잘못되었습니다. 원래 X, Y를 오프셋해야합니다. 경계는 X, Y를 0으로 갖습니다.
  • 예를 들어 UITextField의 leftView를 설정할 때 원본 x, y는 0이 아닐 수 있습니다.

견본:

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

TOP 및 LEFT 들여 쓰기 만 변경하려면

// 자리 표시 자 위치

- (CGRect)textRectForBounds:(CGRect)bounds {

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

// 텍스트 위치

- (CGRect)editingRectForBounds:(CGRect)bounds {

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

-1

서브 클래스가없고 검사 가능한 빠른 솔루션

extension UITextField {
    @IBInspectable var textInsets: CGPoint {
            get {
                return CGPoint.zero
            }
            set {
                layer.sublayerTransform = CATransform3DMakeTranslation(newValue.x, newValue.y, 0);
            }
        }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.