The most complete Uitextview in iOS history the N ways to implement placeholder placeholder text

Source: Internet
Author: User
Tags uikit
Objective
In iOS development, Uitextfield and Uitextview are the most commonly used text-acceptance classes and text-display controls. Uitextfield and Uitextview Both enter text and can also listen for changes to the text. The difference is that Uitextfield inherits from Uicontrol this abstract class. Uitextview inherits from Uiscrollview this entity class. This causes Uitextview to display content more than one line, and can also scroll like Uiscrollview. And Uitextfield can only display a single line of content. From this angle, Uitextview is superior to Uitextfield in function.
However, as we all know, Uitextfield has a placeholder property, you can set the Uitextfield placeholder text, play a role in prompting the user to input relevant information. However, Uitextview is less fortunate, and Apple has not provided Uitextview with a property similar to placeholder for developers to use. In development, we often encounter both placeholder text, but also can be more than a row to display and scrolling control, simple Uitextfield or uitextview can not meet the needs of this product. For example, most apps on the market now have a user feedback entry, as shown in the following figure (a). Below I will be able to think of the method to sum up, let more developers know, there are so many ways to achieve Uitextview placeholder text.

Method One
1. Use the Uitextview Text property as "placeholder".
2. Clear "placeholder" in the agent method that starts editing.
3. Set "placeholder" according to the criteria in the end edit proxy method.
Features: This method is characterized by the user clicks the Textview,placeholder placeholder text will disappear immediately, the official placeholder is when the system listens to the user input text after placeholder will disappear.
Create TextView
uitextview *textview =[[uitextviewalloc]initwithframe:cgrectmake (20,70,screen.width-40,100)];
textview.backgroundcolor= [Uicolor Whitecolor];
Textview.text = @ "I am placeholder";
Textview.textcolor = [Uicolor graycolor];
Textview.delegate = self;
[Self.view Addsubview:textview];

#pragma mark-uitextviewdelegate
-(void) textviewdidendediting: (Uitextview *) TextView
{
    if ( TextView.text.length < 1) {
        Textview.text = @ "I am placeholder";
        Textview.textcolor = [Uicolor graycolor];
    }
-(void) textviewdidbeginediting: (Uitextview *) TextView
{
    if ([Textview.text isequaltostring:@ " I am placeholder "]) {
        textview.text=@" ";
        Textview.textcolor=[uicolor Blackcolor];
    }
Method Two
1. Create TextView
2. Add a Uilabel child control to the TextView as placeholder
3. Show/Hide Uilabel in the text-changing proxy method
Feature: This method can also implement functions similar to placeholder. Comparison method One, method two can realize dynamic listening text changes, not eject the keyboard immediately clear placeholder, only when the user began to input text. Placeholder will disappear. Similarly, when the user clears the text, the placeholder is displayed again.
#import "WSViewController.h" @interface Wsviewcontroller () <UITextViewDelegate> @property (nonatomic, weak)
Uitextview *textview;
@property (nonatomic, weak) Uilabel *placeholder;
    @end @implementation Wsviewcontroller-(void) viewdidload {[Super viewdidload];
    Do no additional setup after loading the view.
[Self setuptextview]; }//Add TextView-(void) Setuptextview {Uitextview *textview = [[Uitextview alloc] Initwithframe:cgrectmake (S
    Creen_width-2 * 10, 200)];

    Textview.frame = CGRectMake (Ten, Screen_width-2 * 10, 200);
    [Self.view Addsubview:textview];

    Self.textview = TextView;
    Textview.contentinset = Uiedgeinsetsmake (-64, 0, 0, 0);
    Textview.delegate = self;

    [Self setupplaceholder];
    Add a view to the pop-up keyboard to place the Done button that exits the keyboard Uitoolbar * TopView = [[Uitoolbar alloc] Initwithframe:cgrectmake (0, 0, 320, 30)];
    [TopView Setbarstyle:uibarstyledefault]; Uibarbuttonitem * Btnspace = [[Uibarbuttonitem alloc] InitwithbarbutTonsystemitem:uibarbuttonsystemitemflexiblespace target:self Action:nil]; Uibarbuttonitem * Donebutton = [[Uibarbuttonitem alloc] initwithtitle:@ "completed" Style:uibarbuttonitemstyledone target:self
    Action: @selector (Dismisskeyboard)];

    Nsarray * Buttonsarray = [Nsarray arraywithobjects:btnspace, Donebutton, nil];
    [TopView Setitems:buttonsarray];
[TextView Setinputaccessoryview:topview]; ///Add a Uilabel child control to TextView-(void) Setupplaceholder {Uilabel *placeholder = [[Uilabel alloc] Initwithframe:cgrectm
    Ake (2, Screen_width-2 * 15, 200)];

    Self.placeholder = placeholder;
    Placeholder.text = @ "I am placeholder";
    Placeholder.textcolor = [Uicolor Lightgraycolor];
    Placeholder.numberoflines = 0;
    Placeholder.contentmode = Uiviewcontentmodetop;
[Self.textview Addsubview:placeholder];
    } #pragma mark-uitextviewdelegate-(void) Textviewdidchange: (Uitextview *) TextView {if (!textview.text.length) {
    Self.placeHolder.alpha = 1;
       } else { Self.placeHolder.alpha = 0;

}//Turn off keyboard-(void) dismisskeyboard{[Self.textview Resignfirstresponder];} @end
In the same way, we can also use the Uilabel as placeholder text to replace with Uitextfield or Uitextview, also can realize textview with placeholder, in the time is not detailed.

Method 31. Custom Uitextview
2. Add placeholder and Placeholdercolor attributes to Uitextview
3. Rewrite the initWithFrame method
4. Add Notification Monitor text change
5. Rewrite DrawRect: Method
6. Override the set method of the associated property

Features: Compared to the above two methods, this method portability, better scalability, this method, not only willing to freely through our added placeholder property to set the default text, but also through the placeholdercolor we added to set the default text color. In the future, we just have to write a custom uitextview, we can once and for all.

#import <UIKit/UIKit.h> @interface wsplaceholdertextview:uitextview/** Placeholder text */@property (nonatomic, copy) nsstr
ing *placeholder;
/** placeholder text color */@property (nonatomic, strong) Uicolor *placeholdercolor; @end #import "WSPlaceholderTextView.h" @implementation Wsplaceholdertextview-(Instancetype) initWithFrame: (CGRect)
        Frame {if (self = [Super Initwithframe:frame]) {//set default font Self.font = [Uifont systemfontofsize:15];
        Set default Color Self.placeholdercolor = [Uicolor Graycolor]; Use notifications to listen for text changes [[Nsnotificationcenter defaultcenter] addobserver:self selector: @selector (textdidchange:) Name:uitex
    Tviewtextdidchangenotification Object:self];
return self;

}-(void) Textdidchange: (nsnotification *) Note {//will recall DrawRect: method [Self setneedsdisplay];}

-(void) Dealloc {[[Nsnotificationcenter defaultcenter] removeobserver:self];} /** * Each call to DrawRect: Method, will be previously painted things clear/-(void) DrawRect: (cgrect) Rect {//If there is text, directly return, do not need to draw placeholder text if (self.hastext) return;
    attribute Nsmutabledictionary *attrs = [Nsmutabledictionary dictionary];
    Attrs[nsfontattributename] = Self.font;


    Attrs[nsforegroundcolorattributename] = Self.placeholdercolor;
    Draw Text rect.origin.x = 5;
    RECT.ORIGIN.Y = 8;
    Rect.size.width-= 2 * rect.origin.x;
[Self.placeholder Drawinrect:rect Withattributes:attrs];
    }-(void) layoutsubviews {[Super layoutsubviews];
[Self setneedsdisplay];
    #pragma mark-setter-(void) Setplaceholder: (NSString *) placeholder {_placeholder = [placeholder copy];
[Self setneedsdisplay];
    }-(void) Setplaceholdercolor: (Uicolor *) placeholdercolor {_placeholdercolor = Placeholdercolor;
[Self setneedsdisplay];
    }-(void) SetFont: (Uifont *) font {[Super Setfont:font];
[Self setneedsdisplay];
    }-(void) SetText: (NSString *) text {[Super Settext:text];
[Self setneedsdisplay];
   }-(void) Setattributedtext: (nsattributedstring *) Attributedtext { [Super Setattributedtext:attributedtext];
[Self setneedsdisplay]; } @end

Method four
1. Custom Uitextview
2. Add placeholder and Placeholdercolor properties to Uitextview
3. Override initWithFrame Method
4. Overriding DrawRect: Method
5. To override the set method of a related property
Feature: This method is similar to the method three, but does not use the notice to listen for the text change, needs to cooperate with textviewdidchanged: This text changes the proxy method to use.

#import <UIKit/UIKit.h> @interface wstextview:uitextview/** placeholder text/@property (nonatomic,copy) NSString *placehol
Der
/** placeholder text color */@property (Nonatomic,strong) Uicolor *placeholdercolor; @end #import "WSTextView.h" @implementation Wstextview-(Instancetype) initWithFrame: (CGRect) Frame {if (self = [sup
        ER initwithframe:frame]) {self.font = [Uifont systemfontofsize:15];
        Self.placeholdercolor = [Uicolor Lightgraycolor];
    Self.placeholder = @ "Please enter content";
return self;
//Only override Drawrect:if for you perform custom drawing.
An empty implementation adversely affects performance during.
    -(void) DrawRect: (cgrect) Rect {//Drawing code nsmutabledictionary *attrs = [Nsmutabledictionary dictionary];
    Attrs[nsfontattributename] = Self.font;
    Attrs[nsforegroundcolorattributename] = Self.placeholdercolor;
[Self.placeholder drawinrect:cgrectmake (0, 0, self.frame.size.width, self.frame.size.height) withattributes:attrs];The///Layout child controls need to be redrawn-(void) layoutsubviews {[Super layoutsubviews];
[Self setneedsdisplay];
    The Set Method-(void) Setplaceholder: (NSString *) placeholder {_placeholder = placeholder) need to be rewritten when the property needs to be redrawn.
[Self setneedsdisplay];
    }-(void) Setplaceholdercolor: (Uicolor *) placeholdercolor {_placeholdercolor = Placeholdercolor;
[Self setneedsdisplay];
    }-(void) SetFont: (Uifont *) font {[Super Setfont:font];
[Self setneedsdisplay];
    }-(void) SetText: (NSString *) text {[Super Settext:text]; if (text.length) {//because it is in the text changed proxy method to determine whether to display placeholder, and the way to set text by code does not call the text change proxy method,
        So this is based on whether the text is not NULL to determine whether to display placeholder.
    Self.placeholder = @ "";
} [self setneedsdisplay];
    }-(void) Setattributedtext: (nsattributedstring *) Attributedtext {[Super Setattributedtext:attributedtext];
    if (attributedtext.length) {Self.placeholder = @ "";
} [self setneedsdisplay]; } @end
The application of the time need to cooperate with Uitextview text change Agent method
#import "ViewController.h" #import "WSTextView.h" @interface Viewcontroller () <UITextViewDelegate>//@property (

Nonatomic,weak) Wstextview *textview;
    @end @implementation Viewcontroller-(void) viewdidload {[Super viewdidload];
Do no additional setup after loading the view, typically from a nib.
    }-(void) didreceivememorywarning {[Super didreceivememorywarning];
Dispose of any of the can is recreated. }-(void) Touchesbegan: (Nsset<uitouch *> *) touches withevent: (Uievent *) Event {Wstextview *textview = [[WSText
    View Alloc] Initwithframe:cgrectmake (A, self.view.frame.size.width, 30)];
    Textview.placeholder = @ "WS";
    Textview.delegate = self;
    [Self.view Addsubview:textview]; Textview.text = @ "Try not to call the text change Agent method";
    Proxy methods that do not invoke text changes textview.attributedtext = [[Nsattributedstring alloc] initwithstring:@ "Rich Text"];
Self.textview = TextView; } #pragma mark-uitextviewdelegate-(void) Textviewdidchange: (Wstextview * TextView//Here, the proxy method parameter type is directly changed to the custom Wstextview type, in order to be able to use the custom placeholder property, eliminates the pass to the controller Wstextview type attribute such step.
    {if (Textview.hastext) {//TextView.text.length Textview.placeholder = @ "";
    else {Textview.placeholder = @ "WS"; }} @end
Method Five
Through runtime, we find that there is a private member variable named "_placeholderlabel" inside the Uitextview. As you know, Objective-c has no absolute private variables, because we can access the private variables through KVC.
Feature: This approach is more tricky than the 4 methods above, although Apple officials did not give us developers similar placeholder properties, but by running, we traversed a placeholderlabel private variable. This method is easy to understand and the amount of code is low, and it is recommended that you use this method.
#import "ViewController.h" #import <objc/runtime.h> #import <objc/message.h> @interface viewcontroller () @
  End @implementation Viewcontroller-(void) viewdidload {[Super viewdidload];
    By running, it is found that Uitextview has a private variable called "_placeholderlabel" unsigned int count = 0;

    Ivar *ivars = Class_copyivarlist ([Uitextview class], &count);
        for (int i = 0; i < count; i++) {Ivar Ivar = ivars[i];
        const char *name = Ivar_getname (Ivar);
        NSString *objcname = [NSString stringwithutf8string:name];
    NSLog (@ "%d:%@", i,objcname);
} [self Setuptextview]; }-(void) Setuptextview {Uitextview *textview = [[Uitextview alloc] Initwithframe:cgrectmake (0, [UIScreen mains
    Creen].bounds.size.width, 100];
    [TextView Setbackgroundcolor:[uicolor Greencolor]];
    [Self.view Addsubview:textview];
    _placeholderlabel Uilabel *placeholderlabel = [[Uilabel alloc] init];
    Placeholderlabel.text = @ "Please enter content"; Placeholderlabel.nUmberoflines = 0;
    Placeholderlabel.textcolor = [Uicolor Lightgraycolor];
    [Placeholderlabel SizeToFit];
    [TextView Addsubview:placeholderlabel];
    Same font textview.font = [Uifont systemfontofsize:13.f];
    Placeholderlabel.font = [Uifont systemfontofsize:13.f];
[TextView setvalue:placeholderlabel forkey:@ "_placeholderlabel"]; } @end


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.