2014-10-09 14 views
18

Tôi cố gắng để áp dụng NSAttributedString phong cách để một UITextField sau khi xử lý một mục văn bản mới, tổ hợp phím bằng cách gõ phím. Vấn đề là bất cứ lúc nào tôi thay thế văn bản con trỏ sẽ nhảy vào cuối mỗi thay đổi. Dưới đây là cách tiếp cận hiện tại của tôi ...Format UITextField văn bản mà không cần phải di chuyển con trỏ đến cuối

Tiếp nhận và thay đổi văn bản hiển thị ngay lập tức (cùng một vấn đề áp dụng khi tôi trả về false và làm việc thay thế văn bản bằng tay)

func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {   
    let range:NSRange = NSRange(location: range.location, length: range.length) 
    let newString = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string); 
    return true 
} 

tôi đăng ký thông báo UITextFieldTextDidChangeNotification. Điều này kích hoạt kiểu dáng. Khi văn bản được thay đổi, tôi thay thế nó (NSString) với phiên bản đã định dạng (NSAttributedString) bằng cách sử dụng một hàm định dạng() nào đó.

func textFieldTextDidChangeNotification(userInfo:NSDictionary) { 
    var attributedString:NSMutableAttributedString = NSMutableAttributedString(string: fullString) 
    attributedString = format(textField.text) as NSMutableAttributedString 
    textField.attributedText = attributedString 
} 

Tạo kiểu hoạt động tốt như thế này. Tuy nhiên sau mỗi lần thay thế văn bản, con trỏ nhảy tới cuối chuỗi. Làm cách nào để tắt hành vi này hoặc di chuyển con trỏ trở lại vị trí bắt đầu chỉnh sửa theo cách thủ công? … Hoặc là có một giải pháp tốt hơn để tạo kiểu cho văn bản trong khi chỉnh sửa?

Trả lời

31

Cách để thực hiện công việc này là lấy vị trí của con trỏ, cập nhật nội dung trường và sau đó thay thế con trỏ đến vị trí ban đầu của nó. Tôi không chắc chắn về tương đương chính xác trong Swift, nhưng sau đây là cách tôi sẽ làm điều đó trong Obj-C.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 
{ 
    UITextPosition *beginning = textField.beginningOfDocument; 
    UITextPosition *cursorLocation = [textField positionFromPosition:beginning offset:(range.location + string.length)]; 

    textField.text = [textField.text stringByReplacingCharactersInRange:range withString:string]; 

    /* MAKE YOUR CHANGES TO THE FIELD CONTENTS AS NEEDED HERE */ 

    // cursorLocation will be (null) if you're inputting text at the end of the string 
    // if already at the end, no need to change location as it will default to end anyway 
    if(cursorLocation) 
    { 
     // set start/end location to same spot so that nothing is highlighted 
     [textField setSelectedTextRange:[textField textRangeFromPosition:cursorLocation toPosition:cursorLocation]]; 
    } 

    return NO; 
} 
+0

Ồ, hoàn hảo. Nó hoạt động như thế. Cảm ơn – Bernd

8

Đây là một câu hỏi cũ, nhưng tôi đã có một vấn đề tương tự và giải quyết nó với Swift sau:

// store the current cursor position as a range 
var preAttributedRange: NSRange = textField.selectedRange 
// apply attributed string 
var attributedString:NSMutableAttributedString = NSMutableAttributedString(string: fullString) 
attributedString = format(textField.text) as NSMutableAttributedString 
textField.attributedText = attributedString 
// reapply the range 
textField.selectedRange = preAttributedRange 

Nó hoạt động trong bối cảnh ứng dụng của tôi, hy vọng nó hữu ích cho một ai đó!

+0

điều này làm việc kỳ diệu, cảm ơn rất nhiều, bởi vì các giải pháp đánh dấu ở trên đã không làm việc cho tôi trên một số trường hợp. – jpincheira

2

Đây là mã hoạt động nhanh chóng 2. Hãy tận hưởng!

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { 
    let beginnig: UITextPosition = textField.beginningOfDocument 

    if let txt = textField.text { 
     textField.text = NSString(string: txt).stringByReplacingCharactersInRange(range, withString: string) 
    } 

    if let cursorLocation: UITextPosition = textField.positionFromPosition(beginnig, offset: (range.location + string.characters.count)) { 
     textField.selectedTextRange = textField.textRangeFromPosition(cursorLocation, toPosition: cursorLocation) 
    } 

    return false 
} 

Lưu ý rằng "nếu để" cuối cùng phải luôn ở cuối mã.

+0

Là con trỏ 'UITextPosition *LocationLocation = [textLượng vị tríFromPosition: bắt đầu offset: (range.location + string.length)];' không cần thiết nữa? – Daniel

7

Cảm ơn @ Stonz2 bằng mã trong Mục tiêu-C. Nó hoạt động như một say mê! Tôi đã sử dụng nó trong dự án Swift của mình. Cùng một mã trong Swift:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { 

    let positionOriginal = textField.beginningOfDocument 
    let cursorLocation = textField.positionFromPosition(positionOriginal, offset: (range.location + NSString(string: string).length)) 

    /* MAKE YOUR CHANGES TO THE FIELD CONTENTS AS NEEDED HERE */ 

    if(cursorLocation != nil) { 
     textField.selectedTextRange = textField.textRangeFromPosition(cursorLocation!, toPosition: cursorLocation!) 
    } 
    return false 
} 
+1

Trong trường hợp của tôi, tôi cần đoạn mã này trong textView: ShouldChangeTextInRange, tôi chỉ thay thế "textField" -> "textView" và "string" -> "text" và nó hoạt động ra khỏi hộp. Cảm ơn! – Vitalii

Các vấn đề liên quan