2009-05-12 32 views
6

Tôi cần di chuyển văn bản mà người dùng đã nhập vào một dòng lớn UITextView thành một nhỏ hơn (nhưng vẫn còn nhiều dòng) UITextView *. Nếu người dùng đã nhập nhiều văn bản hơn sẽ hiển thị ở chế độ xem nhỏ hơn, tôi muốn cắt bớt văn bản sao cho văn bản phù hợp với tất cả văn bản (cắt ngắn) hiển thị. (Không phải số lớn UITextView cũng không nhỏ hơn nên cuộn.)Độ dài chuỗi với phông chữ nhất định để phù hợp với UITextView

Cách tốt nhất để làm điều này là gì?

Tôi có thể sử dụng vòng lặp, rút ​​ngắn chuỗi ký tự mỗi lần, sau đó sử dụng NSString 's sizeWithFont: constrainedToSize: lineBreakMode: để tìm hiểu chiều cao chuỗi ngắn hơn cần, và sau đó so sánh với chiều cao mà tôi có sẵn trong UITextView, kết thúc vòng lặp khi chuỗi phù hợp - nhưng điều đó có vẻ chậm và khó xử. Phải có cách tốt hơn.

Tôi muốn chỉ nói đích đến UITextView để cắt bớt thành viên displayText của nó khi nó hiển thị nó trên màn hình, nhưng tôi đã không thể tìm cách để làm điều đó.

* Thêm ngữ cảnh về điều này, từ nhận xét tôi đã thực hiện bên dưới:

Tôi có ứng dụng ngang. Tôi thay đổi cách bố trí của chế độ xem tùy thuộc vào ảnh mà người dùng chọn. Nếu đó là ảnh phong cảnh, chú thích nhỏ hơn - chỉ là một dòng ở cuối ảnh. Nếu cô ấy chọn ảnh chân dung, thì có rất nhiều không gian tôi có thể sử dụng cho chú thích ở bên cạnh ảnh, vì vậy chú thích lớn hơn.

Nếu người dùng thay đổi hướng ảnh của mình từ dọc sang ngang, thì tôi muốn cắt bớt văn bản và sau đó cho phép cô ấy chỉnh sửa văn bản sao cho phù hợp. Tôi chỉ có thể zap nó, nhưng tôi muốn bảo vệ nó để giảm thiểu đánh máy của cô ấy.

Trả lời

3

Tôi đã viết phương thức đệ quy và API công cộng sau đây để làm điều này đúng cách. Yếu tố lừa đảo xấu xí là chủ đề của this question.

#define kFudgeFactor 15.0 
#define kMaxFieldHeight 9999.0 

// recursive method called by the main API 
-(NSString*) sizeStringToFit:(NSString*)aString min:(int)aMin max:(int)aMax 
{ 
if ((aMax-aMin) <= 1) 
    { 
    NSString* subString = [aString substringToIndex:aMin]; 
    return subString; 
    } 

int mean = (aMin + aMax)/2; 
NSString* subString = [aString substringToIndex:mean]; 

CGSize tallerSize = CGSizeMake(self.frame.size.width-kFudgeFactor,kMaxFieldHeight); 
CGSize stringSize = [subString sizeWithFont:self.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap]; 

if (stringSize.height <= self.frame.size.height) 
    return [self sizeStringToFit:aString min:mean max:aMax]; // too small 
else  
     return [self sizeStringToFit:aString min:aMin max:mean];// too big 
} 

-(NSString*)sizeStringToFit:(NSString*)aString 
{ 

CGSize tallerSize = CGSizeMake(self.frame.size.width-kFudgeFactor,kMaxFieldHeight); 
CGSize stringSize = [aString sizeWithFont:self.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap]; 

// if it fits, just return 
if (stringSize.height < self.frame.size.height) 
    return aString; 

// too big - call the recursive method to size it  
NSString* smallerString = [self sizeStringToFit:aString min:0 max:[aString length]]; 
return smallerString; 
} 
+0

mã này là tuyệt vời, cảm ơn, nhưng tôi đã tìm thấy hai tình huống trong đó nó không thành công: 1) nếu bạn có rất nhiều không gian trên chuỗi 2) "<" trong dòng "if (stringSize.height SpaceDog

1

Tôi khuyên bạn nên thực hiện một cách tiếp cận hơi khác và xem liệu bạn có thể sử dụng UILabel thay vì UITextView nhỏ hơn hay không.

UILabels có thể được thiết lập thành nhiều dòng giống như UITextView thông qua thuộc tính numberOfLines của chúng.

UILabels cũng có thuộc tính lineBreakMode và tôi tin rằng giá trị mặc định của thuộc tính đó sẽ thực hiện hiệu ứng cắt chính xác mà bạn đang tìm kiếm.

+1

Nhưng tôi không nghĩ rằng UILabels có thể chỉnh sửa được, phải không? Tôi muốn người dùng có thể nhập văn bản trong cả hai trường này. (Đặc biệt một khi tôi đã cắt ngắn nó - văn bản có lẽ sẽ không có ý nghĩa.) –

+0

Bạn đúng UILabels không thể chỉnh sửa. Tôi đoán bạn đã stumped tôi cho bây giờ. Nói chung, tôi tự hỏi trải nghiệm người dùng sẽ là gì khi chỉnh sửa UITextView nhỏ hơn của bạn. Người dùng có thể chỉnh sửa tất cả văn bản hoặc chỉ phần không bị cắt bớt không? Nếu người dùng có thể chỉnh sửa tất cả văn bản, người dùng có thể cho biết rằng các chỉnh sửa của họ có hiệu lực như thế nào nếu chúng bị cắt bớt sau khi phiên chỉnh sửa của bạn kết thúc? Vì những lý do này, tôi có thể cân nhắc việc giữ chế độ xem nhỏ hơn dưới dạng tóm tắt chỉ đọc của văn bản. –

+0

Cần thêm một chút thông tin. Tôi có một ứng dụng phong cảnh. Điều gì xảy ra là tôi thay đổi bố cục của chế độ xem tùy thuộc vào ảnh mà người dùng chọn. Nếu đó là ảnh phong cảnh, chú thích nhỏ hơn - chỉ là một dòng ở cuối ảnh. Nếu họ chọn ảnh chân dung, thì có rất nhiều không gian tôi có thể sử dụng cho chú thích ở bên cạnh ảnh, do đó chú thích lớn hơn. Nếu người dùng thay đổi hướng ảnh của mình từ dọc sang ngang, thì tôi muốn cắt bớt văn bản và sau đó cho phép anh ấy thay đổi nó để có ý nghĩa. –

1

Tôi nghĩ rằng Jonathan là trên một cái gì đó về UILabel ...

Vì vậy, người dùng hoàn tất việc chỉnh sửa UITextView, bạn sẽ có được chuỗi văn bản và vượt qua nó để UILabel. Bạn thay đổi alpha của UITextView thành 0 và/hoặc xóa nó khỏi superview. Có thể lưu trữ văn bản đầy đủ không được cắt ngắn trong một thanh ivar.

UILabels không "có thể chỉnh sửa", tuy nhiên bạn có thể phát hiện một liên lạc bằng UILabel (hoặc giám sát). Khi bạn phát hiện cảm ứng trên UILabel, bạn chỉ cần khôi phục UITextView ẩn và khôi phục chuỗi bạn đã lưu.

Đôi khi SDK là một nỗi đau, nhưng nó hầu như luôn thắng cuộc chiến. Nhiều lần, tốt hơn là điều chỉnh thiết kế của bạn thành các quy ước UIKit

2

Đây không phải là một sự cố nhưng nó cung cấp một khởi đầu tốt cho việc tính toán.

Nếu bạn sử dụng số sizeWithFont: constrainedToSize: lineBreakMode: của NSString, bạn sẽ nhận được chiều cao theo chiều dọc cho văn bản của mình. Nếu bạn chia cho chiều cao hàng đầu của phông chữ, bạn sẽ nhận được số dòng trong toàn bộ chuỗi. Chia [Số lượng NSString] cho số đó cho bạn một số xấp xỉ về số ký tự trên mỗi dòng.Điều này giả định chuỗi là đồng nhất và sẽ không chính xác nếu ai đó gõ (ví dụ) 'iiiiiiiiiii ... "như được chọn cho" MMMMMMMMM ... ".

Bạn cũng có thể chia hộp giới hạn của bạn theo chiều cao của phông chữ có liên quan là độ cao leading lấy số dòng phù hợp trong khung giới hạn của bạn.

Nhân ký tự trên mỗi dòng bằng số dòng cung cấp cho bạn một điểm khởi đầu cho việc tìm kiếm văn bản phù hợp.

bạn có thể tính toán lợi nhuận cho lỗi trong hình này bằng cách thực hiện tính toán tương tự cho các chuỗi 'iiiiii ...' và "MMMMMM ... '".

+0

Đồng ý, đây là một cách tiếp cận tốt, và như vậy là làm một băm nhị phân trên chiều dài chuỗi bằng cách sử dụng phương pháp trên. Tôi vẫn hy vọng có một cách tốt hơn, nhưng tôi có cảm giác bây giờ không có. –

+0

Giải pháp là Chuyển phát nhanh. Cố định phông chữ rộng, không có môn toán ... –

+0

@Tristan, chỉ khi bạn bỏ qua khoảng trống khi gói. Nó sẽ là một vấn đề đơn giản hơn mặc dù. –

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