ios - UITextField के लिए टेक्स्ट इन्सेट?




cocoa-touch (18)

मैं UITextField के पाठ को इन्सेट करना चाहता हूं।

क्या यह संभव है?


UITextField में पैडिंग जोड़ने का एक अच्छा तरीका UITextField को उपclass करना है और एक एजइन्स संपत्ति जोड़ें। फिर आप एजइन्स सेट करते हैं और UITextField तदनुसार तैयार किया जाएगा। यह कस्टम बाएं व्यू या दाएं दृश्य सेट के साथ भी सही तरीके से कार्य करेगा।

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

UITextField से व्युत्पन्न कक्षा में, कम से कम इन दो विधियों को ओवरराइड करें:

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

यदि आपके पास कोई अतिरिक्त सामग्री नहीं है तो यह उतना आसान हो सकता है:

return CGRectInset(bounds , 10, 10);

UITextField कई पोजिशनिंग विधियों को प्रदान करता है जिन्हें आप ओवरराइड कर सकते हैं।


आप बाएं दृश्य को सेट करके 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;

उपclass और भी निरीक्षण के बिना त्वरित समाधान

extension UITextField {
    @IBInspectable var textInsets: CGPoint {
            get {
                return CGPoint.zero
            }
            set {
                layer.sublayerTransform = CATransform3DMakeTranslation(newValue.x, newValue.y, 0);
            }
        }
}

एक और समाधान में फेंकने के लिए जिसमें उप-वर्गीकरण की आवश्यकता नहीं है:

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

आईओएस 7 और आईओएस 8 के साथ परीक्षण किया। दोनों काम कर रहे हैं। फिर भी ऐप्पल को UITextField की परत पदानुक्रम को बुरी तरह खराब करने के लिए संशोधित करने का मौका हो सकता है।


मैं आमतौर पर सबक्लासिंग से बचने की कोशिश करता हूं लेकिन यह काम करता है यदि आप पहले से ही हैं:

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

मैंने 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 कस्टम क्लास के साथ nib / storyboard दृश्य से आता है

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

मैंने आईबी में ऐसा किया जहां मैंने टेक्स्टव्यू के पीछे एक यूआईवीव बनाया जो थोड़ी देर तक था। टेक्स्टफिल्ड पृष्ठभूमि रंग को साफ़ करने के लिए सेट करें।


यदि आपके पास एक स्पष्ट बटन है, तो स्वीकृत उत्तर आपके लिए काम नहीं करेगा। 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 क्रम में पैरामीटर लेता है: ऊपर , बाएं , नीचे , दाएं


यदि आपको केवल बाएं हाशिए की आवश्यकता है, तो आप इसे आजमा सकते हैं:

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;

इससे मेरा काम बनता है। मुझे उम्मीद है कि यह मदद कर सकता है।


यह किसी भी उप-वर्ग के बिना मैंने पाया सबसे तेज़ तरीका है:

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

यह बेतुका है कि आपको उप-वर्ग करना है, क्योंकि UITextField पहले से ही विधियों को लागू करता है, क्योंकि @ एडम वाइट बताते हैं। यहां एक त्वरित विस्तार है जो एक कारखाने विधि का खुलासा करता है, जो हमारी श्रेणियों में भी उपलब्ध है रेपो :

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

}

यहां स्विफ्ट 3 में लिखे गए एक ही उप-वर्गीकृत यूआईटीएक्स्टफिल्ड हैं। यह स्विफ्ट के पूर्व संस्करणों से काफी अलग है, जैसा कि आप देखेंगे:

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

लोगों के लिए, जो एक आसान समाधान की तलाश में हैं।

UIView अंदर UITextField जोड़ें। टेक्स्ट फ़ील्ड के आस-पास एक इन्सेट अनुकरण करने के लिए मैं 10 पीएक्स बाएं रखता हूं और चौड़ाई दृश्य से 20px कम होती है। टेक्स्टफील्ड के चारों ओर एक गोल कोने सीमा के लिए, दृश्य की सीमा का उपयोग करें

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

स्विफ्ट 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)
}
}

उपयोग:

और


-textRectForBounds: केवल प्लेसहोल्डर टेक्स्ट के -textRectForBounds: को बदल देगा। संपादन योग्य पाठ के -editingRectForBounds: को बदलने के लिए, आपको ओवरराइड करने की आवश्यकता है -editingRectForBounds:

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

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

तीव्र

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

मई 2017 तक एक्सकोड 8.3.1 के लिए स्विफ्ट 3 संस्करण:

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




uitextfield