使UITextField具有静态和属性前缀 [英] Make UITextField which has a static and attributed prefix

查看:82
本文介绍了使UITextField具有静态和属性前缀的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想制作一个UITextField,它具有一个静态前缀,并且用户不能进行编辑或删除,同时还具有浅灰色的字体颜色. /p>

文本字段的可编辑部分应始终以黑色显示.

下面是一个示例:

从本质上讲,它是用于输入用户名的,具有恒定前缀的域.


我已经尝试将textFieldShouldCleartextField:shouldChangeCharactersInRange:replacementString:委托方法与NSMutableAttributedString一起使用,但是根本无法破解它:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSMutableAttributedString *text = [textField.attributedText mutableCopy];

    [text addAttribute:NSForegroundColorAttributeName value:[UIColor grayColor] range:NSMakeRange(0, 7)];

    if (textField.text.length > 7)
    {    
        [text addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(7, textField.attributedText.length - 7)];
    }
    [text addAttribute:NSFontAttributeName value:[UIFont gothamFontForSize:textField.font.pointSize andWeight:kGothamLight] range:NSMakeRange(0, textField.attributedText.length)];


    return range.location > 6;
}

- (BOOL)textFieldShouldClear:(UITextField *)textField
{
    NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:@"kombit\\"];
    [text addAttribute:NSForegroundColorAttributeName value:[UIColor grayColor] range:NSMakeRange(0, 7)];
    [text addAttribute:NSFontAttributeName value:[UIFont gothamFontForSize:textField.font.pointSize andWeight:kGothamLight] range:NSMakeRange(0, text.length)];
    textField.attributedText = text;

    [textField setSelectedTextRange:[textField textRangeFromPosition:[textField endOfDocument] toPosition:[textField endOfDocument]]];

    return NO;
}

我确定有人已经做了类似的事情.

解决方案

下面的代码从您的永久文本中创建一个属性字符串,将其涂成灰色,然后将其添加到文本字段中.然后在shouldChangeCharactersInRange:中进行范围比较以确定该范围是否在应由"kombit \"占据的区域内,如果不是,则将黑色属性传递回文本字段.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.textField setDelegate:self];

    NSString *fixedString = @"kombit\\";
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:fixedString];

    [attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor lightGrayColor] range:NSMakeRange(0, fixedString.length)];

    [self.textField setAttributedText:attributedString];
}

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSRange substringRange = [textField.text rangeOfString:@"kombit\\"];

    if (range.location >= substringRange.location && range.location < substringRange.location + substringRange.length) {
        return NO;
    }

    NSMutableAttributedString *attString = [textField.attributedText mutableCopy];

    [attString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(substringRange.length, textField.text.length - substringRange.length)];

    [textField setAttributedText:attString];

    return YES;
}

好吧,这不是我曾期望的那样痛苦的事情,坦率地说,我很尴尬地发布了这段代码,因为它确实很脏,但是它的确比以前做得更好

我最终要做的是创建一个属性,以引用BOOL来保存是否应更新文本(以阻止递归),并在文本字段的UIControlEventEditingChanged控制事件中添加一个目标,以在发生以下情况时获得回调进行编辑.

然后,由于某种原因,似乎没有一种正常的方法可以在这里工作,所以我将调用"signals"移动到文本字段的末尾,方法是在调用resignFirstResponder之后直接放置对成为firstResponder的调用,而且令人惊讶的是,这几乎可以正常工作.我尚未发现文本大小略有变化的问题,但这只是添加其他属性以匹配所需字体大小的问题

抱歉,在解决这个问题上我无济于事,这是一个很奇怪的问题.我通常不愿意提出这个建议,但是在花了很多时间尝试做一些琐碎的事情之后,我开始认为NSAttributedString中存在一些错误.无论如何,请让我知道这段代码是否最终将您引向答案,我对解决方案真的很感兴趣.

@property (weak, nonatomic) IBOutlet UITextField *textField;
@property (nonatomic, assign) BOOL shouldUpdateAttributes;



- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.textField setDelegate:self];
    [self.textField setSpellCheckingType:UITextSpellCheckingTypeNo];
    [self setShouldUpdateAttributes:YES];


    NSString *fixedString = @"kombit\\ ";
    [self.textField setText:fixedString];

    [self.textField addTarget:self action:@selector(textFieldDidChangeText:) forControlEvents:UIControlEventEditingChanged];
    [self textFieldDidChangeText:self.textField];
}

- (void)textFieldDidChangeText:(UITextField *)sender
{
    if (self.shouldUpdateAttributes) {
        [self setShouldUpdateAttributes:NO];

        NSString *fixedString = @"kombit\\ ";

        NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:sender.text];

        [attributedString setAttributes:@{NSForegroundColorAttributeName: [UIColor lightGrayColor]} range:NSMakeRange(0, fixedString.length)];
        [attributedString setAttributes:@{NSForegroundColorAttributeName: [UIColor blackColor]} range:NSMakeRange(fixedString.length, sender.text.length - fixedString.length)];

        [sender setAttributedText:attributedString];
        [sender resignFirstResponder];
        [sender becomeFirstResponder];
    }
}


- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    [self setShouldUpdateAttributes:YES];
    NSString *fixedString = @"kombit\\";
    NSRange substringRange = [textField.text rangeOfString:fixedString];

    if (range.location >= substringRange.location && range.location < substringRange.location + substringRange.length) {
        return NO;
    }

    return YES;
}

I would like to make a UITextField, which has a static prefix and that the user cannot edit or delete, which at the same time is also attributed with a light gray font color.

The editable part of the text field should always be shown in black color.

An example is given below:

It is essentially for typing in a user name, with a constantly prefixed domain.


I have already tried using the textFieldShouldClear and textField:shouldChangeCharactersInRange:replacementString: delegate methods together with NSMutableAttributedString, but simply haven't been able to crack it:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSMutableAttributedString *text = [textField.attributedText mutableCopy];

    [text addAttribute:NSForegroundColorAttributeName value:[UIColor grayColor] range:NSMakeRange(0, 7)];

    if (textField.text.length > 7)
    {    
        [text addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(7, textField.attributedText.length - 7)];
    }
    [text addAttribute:NSFontAttributeName value:[UIFont gothamFontForSize:textField.font.pointSize andWeight:kGothamLight] range:NSMakeRange(0, textField.attributedText.length)];


    return range.location > 6;
}

- (BOOL)textFieldShouldClear:(UITextField *)textField
{
    NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:@"kombit\\"];
    [text addAttribute:NSForegroundColorAttributeName value:[UIColor grayColor] range:NSMakeRange(0, 7)];
    [text addAttribute:NSFontAttributeName value:[UIFont gothamFontForSize:textField.font.pointSize andWeight:kGothamLight] range:NSMakeRange(0, text.length)];
    textField.attributedText = text;

    [textField setSelectedTextRange:[textField textRangeFromPosition:[textField endOfDocument] toPosition:[textField endOfDocument]]];

    return NO;
}

I am certain that someone has already done something similar.

解决方案

The code below creates an attributed string out of your permanent text, colors it gray, and adds it to a textfield. Then in shouldChangeCharactersInRange: a range comparison is done to determine whether or not the range is within the area that should be occupied by "kombit\", and if it isn't, a black coloring attribute is passed back to the text field.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.textField setDelegate:self];

    NSString *fixedString = @"kombit\\";
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:fixedString];

    [attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor lightGrayColor] range:NSMakeRange(0, fixedString.length)];

    [self.textField setAttributedText:attributedString];
}

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSRange substringRange = [textField.text rangeOfString:@"kombit\\"];

    if (range.location >= substringRange.location && range.location < substringRange.location + substringRange.length) {
        return NO;
    }

    NSMutableAttributedString *attString = [textField.attributedText mutableCopy];

    [attString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(substringRange.length, textField.text.length - substringRange.length)];

    [textField setAttributedText:attString];

    return YES;
}

EDIT:

Okay, this isn't something I would have ever expected to be this big of a pain, and frankly I'm embarrassed to post this code because it's really dirty, but it does seem to be doing the job better than before.

What I ended up doing was creating a property to reference a BOOL to hold whether or not the text should be updates (to block the recursion) and adding a target to the text field's UIControlEventEditingChanged control event to get a callback when editing occurred.

Then, because for some reason none of the normal ways of doing this seem to be working here, I'm moving the "cursor" to the end of the text field by placing a call to becomeFirstResponder directly after a call to resignFirstResponder, and surprisingly this is pretty much working. There is an issue with the text size changing slightly that I have yet to identify, but it should just be a matter of adding additional attributes to match the font size you want

Sorry I couldn't be any more help in solving this, it is quite the curious problem. And I usually hate to suggest this, but after spending so much time trying to do something that should be trivial I'm starting to think there's something buggy going on in NSAttributedString. Anyway, let me know if this code eventually leads you to the answer, I'd be really interested in the solution.

@property (weak, nonatomic) IBOutlet UITextField *textField;
@property (nonatomic, assign) BOOL shouldUpdateAttributes;



- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.textField setDelegate:self];
    [self.textField setSpellCheckingType:UITextSpellCheckingTypeNo];
    [self setShouldUpdateAttributes:YES];


    NSString *fixedString = @"kombit\\ ";
    [self.textField setText:fixedString];

    [self.textField addTarget:self action:@selector(textFieldDidChangeText:) forControlEvents:UIControlEventEditingChanged];
    [self textFieldDidChangeText:self.textField];
}

- (void)textFieldDidChangeText:(UITextField *)sender
{
    if (self.shouldUpdateAttributes) {
        [self setShouldUpdateAttributes:NO];

        NSString *fixedString = @"kombit\\ ";

        NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:sender.text];

        [attributedString setAttributes:@{NSForegroundColorAttributeName: [UIColor lightGrayColor]} range:NSMakeRange(0, fixedString.length)];
        [attributedString setAttributes:@{NSForegroundColorAttributeName: [UIColor blackColor]} range:NSMakeRange(fixedString.length, sender.text.length - fixedString.length)];

        [sender setAttributedText:attributedString];
        [sender resignFirstResponder];
        [sender becomeFirstResponder];
    }
}


- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    [self setShouldUpdateAttributes:YES];
    NSString *fixedString = @"kombit\\";
    NSRange substringRange = [textField.text rangeOfString:fixedString];

    if (range.location >= substringRange.location && range.location < substringRange.location + substringRange.length) {
        return NO;
    }

    return YES;
}

这篇关于使UITextField具有静态和属性前缀的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆