Як стилізувати UITextview, щоб подобатися текстове поле округлого прямої?


170

Я використовую перегляд тексту як композитор коментарів.

В інспекторі властивостей я не можу знайти нічого подібного до властивості стилю кордону, щоб я міг використовувати закруглену пряму, щось подібне UITextField.

Отже, питання полягає в тому, як я можу створити стиль UITextViewтипу « UITextFieldзакруглена пряма»?


1
Не могли б ви не використати UITextFieldта просто вимкнути userInteractionEnabled?
jowie

Відповіді:


285

Немає неявного стилю, який потрібно вибрати, він включає написання трохи коду за допомогою QuartzCoreфреймворку:

//first, you
#import <QuartzCore/QuartzCore.h>

//.....

//Here I add a UITextView in code, it will work if it's added in IB too
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(50, 220, 200, 100)];

//To make the border look very close to a UITextField
[textView.layer setBorderColor:[[[UIColor grayColor] colorWithAlphaComponent:0.5] CGColor]];
[textView.layer setBorderWidth:2.0];

//The rounded corner part, where you specify your view's corner radius:
textView.layer.cornerRadius = 5;
textView.clipsToBounds = YES;

Він працює лише на ОС 3.0 і вище, але я думаю, зараз це де-факто платформа.


47
Я знайшов додавання наступного верхнього коду до вищевказаного коду, щоб межа виглядала дуже близькою до UITextField. [textView.layer setBorderColor: [[[UIColor greyColor] colorWithAlphaComponent: 0,5] CGColor]]; [textView.layer setBorderWidth: 2.0];
Роб

12
Обов’язково: #import <QuartzCore / QuartzCore.h>. У мене були проблеми , тому що я не імпортував QuartzCore
Остен

1
Для n00bs, як я, варте зауваження: помістіть цей код у viewDidLoad НЕ в initWithNibName :-)
Брайан Колавіто

1
Ви можете просто використовувати UITextFieldз borderStyleнабором властивостей до UITextBorderStyleRoundedRect- см мій пост нижче.
jowie

5
iOS 7 - borderWidth 1,0 та альфа .2 працює зі стилем за замовчуванням.
Калель Вейд

77

цей код добре працював для мене:

    [yourTextView.layer setBackgroundColor: [[UIColor whiteColor] CGColor]];
    [yourTextView.layer setBorderColor: [[UIColor grayColor] CGColor]];
    [yourTextView.layer setBorderWidth: 1.0];
    [yourTextView.layer setCornerRadius:8.0f];
    [yourTextView.layer setMasksToBounds:YES];

4
Я б сказав, що 5px ближче до текстових полів, але сірий колір цієї відповіді краще, ніж обрана відповідь.
Peter DeWeese

2
Звичайно, вам потрібно додати QuartzCore Framework для цієї відповіді та імпортувати її до #import <QuartzCore / QuartzCore.h>
lukaswelte

36

Версія Swift 3

Після налаштування подання тексту в конструкторі інтерфейсів.

@IBOutlet weak var textView: UITextView!

override func viewDidLoad() {
    super.viewDidLoad()
    textView.layer.cornerRadius = 5     
    textView.layer.borderColor = UIColor.gray.withAlphaComponent(0.5).cgColor
    textView.layer.borderWidth = 0.5  
    textView.clipsToBounds = true
}

Версія Swift 2.2

@IBOutlet weak var textView: UITextView!

override func viewDidLoad() {
    super.viewDidLoad()
    textView.layer.cornerRadius = 5     
    textView.layer.borderColor = UIColor.grayColor().colorWithAlphaComponent(0.5).CGColor
    textView.layer.borderWidth = 0.5  
    textView.clipsToBounds = true
}

1
Проблема в тому, що вона не сіра точно. Колір кадру UITextField дещо відрізняється.
Макалеле

1
Здійснення .borderWidth = 0,7 робить його ближче до сучасного стилю, який я бачу на iOS 11.
Chris Amelinckx

28

Редагувати. Вам потрібно імпортувати

#import <QuartzCore/QuartzCore.h>

для використання кутового радіуса.

Спробуйте це точно буде працювати

UITextView* txtView = [[UITextView alloc] initWithFrame:CGRectMake(50, 50, 300, 100)];
txtView.layer.cornerRadius = 5.0;
txtView.clipsToBounds = YES;

Як Роб зрозумів, встановивши, якщо ви хочете, щоб колір рамки був подібний, як UITextFieldтоді, вам потрібно змінити ширину межі на 2,0, а колір на сірий, додавши наступний рядок

[textView.layer setBorderColor:[[[UIColor grayColor] colorWithAlphaComponent:0.5] CGColor]]; 
[textView.layer setBorderWidth:2.0];

2
Мені було цікаво, чому це не працює. Дякую за типофф про QuartzCore.
Ехілон

23

Я хотів справжньої угоди, тому додаю UIImageViewяк підвид UITextView. Це відповідає рідній межі а UITextField, включаючи градієнт зверху вниз:

textView.backgroundColor = [UIColor clearColor];
UIImageView *borderView = [[UIImageView alloc] initWithFrame: CGRectMake(0, 0, textView.frame.size.width, textView.frame.size.height)];
borderView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
UIImage *textFieldImage = [[UIImage imageNamed:@"TextField.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(15, 8, 15, 8)];
borderView.image = textFieldImage;
[textField addSubview: borderView];
[textField sendSubviewToBack: borderView];

Це образи, які я використовую:

введіть тут опис зображення введіть тут опис зображення


2
Я думаю, вам також потрібно сказати textView, щоб мати UITextBorderStyle None, якщо ви цього не встановили вже в XCode
суперлогічний

1
Я повторно завантажив png зображення
Бен Пакард

5
Нічого поганого, фон рухається під час прокрутки UITextView. Здогадуюсь, мені доведеться помістити все це у батьківський UIView
Олівер Пірмен,

1
Відмінно. Це виглядає чудово: D
Sune Trudslev

12

Одне рішення - додати поле UITextField під UITextView , зробити UITextViewфон прозорим і відключити будь-яку взаємодію користувача на UITextField. Потім в коді змініть UITextFieldкадр чимось подібним

self.textField.frame = CGRectInset(self.textView.frame, 0, -2);

Ви матимете такий самий вигляд, як і текстове поле.

І як запропонував Джон , вам слід покласти цей фрагмент коду всередині [UIViewController viewDidLayoutSubviews]iOS 5.0+.


1
Це було так просто і виглядає саме так, як я хотів це виглядати. Я щойно узгодив кадр UITextField з UITextView: CGRect frame = self.myTextView.frame; frame.size.height + = 2; self.myTextField.frame = кадр;
Буїн Брайан

1
Прекрасна відповідь. Чисто і просто. Введіть код у viewDidLayoutSubviews:(iOS 5.0+).
Jon

1
Приємно, це був soln, з яким я пішов врешті-решт. Зауважте, що це не спрацювало, поки я не використав коментар Джона re: viewDidLayoutSubviews:
daver

1
Це було найшвидше, і виглядає найкраще.
Вестон

5

Для найкращого ефекту потрібно використовувати власне (розтягується) фонове зображення. Так також UITextFieldнамальована округла межа.


4

Один із способів, який я знайшов, щоб зробити це без програмування, - це зробити текст текстового поля прозорим, а потім розмістити за ним круглу кнопку прямої прямої. Не забудьте змінити налаштування кнопки, щоб відключити її, і зніміть Disable adjusts imageпрапорець.


4

Ви можете перевірити мою бібліотеку під назвою DCKit .

Ви зможете зробити перегляд тексту із закругленим кутом (а також текстове поле / кнопку / простий UIView) Interface Builderбезпосередньо:

DCKit: облямований UITextView

Він також має багато інших корисних функцій, таких як текстові поля з валідацією, елементи керування рамками, пунктирні рамки, перегляд кола та лінії волосся тощо.


4

Я знаю, що на це вже є багато відповідей, але я насправді не знайшов жодної з них достатньою (принаймні у Свіфта). Я хотів рішення, яке забезпечило б таку ж точну межу, як і UITextField (не наближене, яке виглядає так, як зараз виглядає, але таке, яке виглядає саме так і завжди буде виглядати саме так). Мені потрібно було використовувати UITextField для резервного копіювання UITextView для фону, але не хотілося створювати це окремо кожен раз.

Нижче наведено рішення UITextView, яке забезпечує власне UITextField для кордону. Це обрізана версія мого повного рішення (яка додає підтримку UITextView до "заповнення місця" аналогічним чином) та була розміщена тут: https://stackoverflow.com/a/36561236/1227119

// This class implements a UITextView that has a UITextField behind it, where the 
// UITextField provides the border.
//
class TextView : UITextView, UITextViewDelegate
{
    var textField = TextField();

    required init?(coder: NSCoder)
    {
        fatalError("This class doesn't support NSCoding.")
    }

    override init(frame: CGRect, textContainer: NSTextContainer?)
    {
        super.init(frame: frame, textContainer: textContainer);

        self.delegate = self;

        // Create a background TextField with clear (invisible) text and disabled
        self.textField.borderStyle = UITextBorderStyle.RoundedRect;
        self.textField.textColor = UIColor.clearColor();
        self.textField.userInteractionEnabled = false;

        self.addSubview(textField);
        self.sendSubviewToBack(textField);
    }

    convenience init()
    {
        self.init(frame: CGRectZero, textContainer: nil)
    }

    override func layoutSubviews()
    {
        super.layoutSubviews()
        // Do not scroll the background textView
        self.textField.frame = CGRectMake(0, self.contentOffset.y, self.frame.width, self.frame.height);
    }

    // UITextViewDelegate - Note: If you replace delegate, your delegate must call this
    func scrollViewDidScroll(scrollView: UIScrollView)
    {
        // Do not scroll the background textView
        self.textField.frame = CGRectMake(0, self.contentOffset.y, self.frame.width, self.frame.height);
    }        
}

3

Один із способів, який я знайшов, щоб зробити це без програмування, - це зробити текст текстового поля прозорим, а потім розмістити за ним круглу кнопку прямої прямої. Не забудьте змінити налаштування кнопки, щоб відключити її, і зніміть прапорець Відключити налаштування зображення.

Спробував код Quartzcore і виявив, що він спричинив відставання на моєму старому 3G (я використовую для тестування). Не велика проблема, але якщо ви хочете бути максимально інклюзивними для різних ios та апаратних засобів, я рекомендую відповідь Andrew_L вище - або зробіть власні зображення та застосуйте відповідно.


3

Існує чудове фонове зображення, ідентичне UITextViewвикористаному для надсилання текстових повідомлень у додатку Повідомлення iPhone. Щоб отримати та змінити, вам знадобиться Adobe Illustrator. iphone ui елементів векторного


3
#import <QuartzCore/QuartzCore.h>
- (void)viewDidLoad{
  UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(50, 220, 200, 100)];
  textView.layer.cornerRadius = 5;
  textView.clipsToBounds = YES;
  [textView.layer setBackgroundColor: [[UIColor whiteColor] CGColor]];
  [textView.layer setBorderColor: [[UIColor grayColor] CGColor]];
  [textView.layer setBorderWidth: 1.0];
  [textView.layer setCornerRadius:8.0f];
  [textView.layer setMasksToBounds:YES];
  [self.view addSubView:textview];
}

2

Ви можете створити текстове поле, яке не приймає жодних подій поверх перегляду тексту так:

CGRect frameRect = descriptionTextField.frame;
frameRect.size.height = 50;
descriptionTextField.frame = frameRect;
descriptionTextView.frame = frameRect;
descriptionTextField.backgroundColor = [UIColor clearColor];
descriptionTextField.enabled = NO;
descriptionTextView.layer.cornerRadius = 5;
descriptionTextView.clipsToBounds = YES;

Або просто зробіть текстове поле в конструкторі інтерфейсів. Потім встановіть висоту в коді (оскільки розробник інтерфейсу не дозволив вам). CGRect frameRect = self.textField.frame; frameRect.size.height = 50; self.textField.frame = frameRect;
аудиб

2

Якщо ви хочете, щоб ваш код контролера був чистим, ви можете підкласировать UITextView, як показано нижче, та змінити ім'я класу в Interface Builder.

RoundTextView.h

#import <UIKit/UIKit.h>
@interface RoundTextView : UITextView
@end

RoundTextView.m

#import "RoundTextView.h"
#import <QuartzCore/QuartzCore.h>
@implementation RoundTextView
-(id) initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        [self.layer setBorderColor:[[[UIColor grayColor] colorWithAlphaComponent:0.333] CGColor]];
        [self.layer setBorderWidth:1.0];
        self.layer.cornerRadius = 5;
        self.clipsToBounds = YES;
    }
    return self;
}
@end

1

Ось моє рішення:

- (void)viewDidLoad {
    [super viewDidLoad];


    self.textView.text = self.messagePlaceholderText;
    self.textView.layer.backgroundColor = [[UIColor whiteColor] CGColor];
    self.textView.layer.borderColor = [[[UIColor grayColor] colorWithAlphaComponent:0.3] CGColor];
    self.textView.layer.borderWidth = 0.5;
    self.textView.layer.cornerRadius = 5.5f;
    self.textView.layer.masksToBounds = YES;
    self.textView.textColor = [[UIColor grayColor] colorWithAlphaComponent:0.4];
}

- (void)textViewDidBeginEditing:(UITextView *)textView {
    if (textView == self.tvMessage) {
        // Delete placeholder text
        if ([self.textView.text isEqualToString:self.messagePlaceholderText]) {
            self.textView.text = @"";
            self.textView.textColor = [UIColor blackColor];
        }
    }
}

- (void)textViewDidEndEditing:(UITextView *)textView {
    if (textView == self.tvMessage) {
        // Write placeholder text
        if (self.textView.text.length == 0) {
            self.textView.text = self.messagePlaceholderText;
            self.textView.textColor = [[UIColor grayColor] colorWithAlphaComponent:0.4];
        }
    }
}

0

Я не думаю, що це можливо. але ви можете зробити UITableView(згруповано) з 1 секцією та 1 порожньою коміркою і використовувати її як контейнер для свого UITextView.


0

Це старе запитання, і мене також шукали відповіді на ці запитання. Відповідь luvieeres на 100% правильна, і пізніше Роб додав код. Це чудово, але я знайшов третю сторону в іншій відповіді, яка мені здається дуже корисною. Я не тільки шукав подібний погляд на UITextFieldбільш UITextView, я також шукав багаторядкова підтримку. ChatInputSample задовольнили обох. Ось чому я думаю, що ця третя сторона може бути корисною для інших. Крім того, завдяки Тимуру, він говорив про це з відкритим вихідним кодом в тут .


0

У iOS7 наступні межі UITextField відповідають межі (як мінімум, на моє око):

textField.layer.borderColor = [[[UIColor grayColor] colorWithAlphaComponent:0.5] CGColor];
textField.layer.borderWidth = 0.5;
textField.layer.cornerRadius = 5;
textField.clipsToBounds = YES;

Не потрібно імпортувати нічого особливого.

Дякую @uvieere та @hanumanDev, відповіді яких мені майже туди :)


-1

Як щодо:

UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(20, 20, 280, 32)];
textField.borderStyle = UITextBorderStyleRoundedRect;
[self addSubview:textField];

питання про перегляд тексту.
Азік Абдулла

Вибачте - спрацьовує радісна відповідь стека. Було б цікаво дізнатись, чому вони не могли просто використовувати a UITextFieldз userInteractionEnabledset NO.
jowie

Textfield не підтримує декілька рядків
Азік Абдулла

зрозумів. Дякую за уточнення
jowie
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.