Как стилизовать UITextview как текстовое поле Rounded Rect?

170

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

В инспекторе свойств я не могу найти ничего похожего на свойство стиля границы, чтобы я мог использовать закругленный прямоугольник, что-то вроде UITextField.

Итак, вопрос: Как я могу стилизацию UITextViewвроде UITextFieldс закругленным прямоугольником?

harshalb
источник
1
Не могли бы вы не использовать UITextFieldи просто выключить userInteractionEnabled?
Джоуи

Ответы:

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;

Это работает только на OS 3.0 и выше, но я думаю, что теперь это де-факто платформа в любом случае.

luvieere
источник
47
Я обнаружил, что добавление следующей вершины кода выше делает границу очень похожей на UITextField. [textView.layer setBorderColor: [[[UIColor grayColor] colorWithAlphaComponent: 0.5] CGColor]]; [textView.layer setBorderWidth: 2.0];
Роб
12
Убедитесь, что у вас есть: #import <QuartzCore / QuartzCore.h>. У меня были проблемы, потому что я не импортировал QuartzCore
austen
1
Для n00bs, как я, стоит отметить: поместите этот код в viewDidLoad, а НЕ в initWithNibName :-)
Брайан Колавито
1
Вы можете просто использовать UITextFieldс borderStyleнабором свойств к UITextBorderStyleRoundedRect- см мой пост ниже.
Джоуи
5
iOS 7 - borderWidth 1.0 и alpha .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];
hanumanDev
источник
4
Я бы сказал, что 5px ближе к текстовым полям, но серый цвет этого ответа лучше, чем выбранный ответ.
Питер ДеВиз
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 немного отличается.
Makalele
1
Если сделать .borderWidth = 0.7, это будет выглядеть ближе к текущему стилю, который я вижу в iOS 11.
Крис Амелинккс,
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.
Echilon
23

Я хотел реальную сделку, поэтому я добавлю UIImageViewв качестве подпредставления UITextView. Это соответствует родной границе на a 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 = frame;
Буйен Брайан,
1
Прекрасный ответ. Чисто и просто. Вставьте код в viewDidLayoutSubviews:(iOS 5.0+).
Джон
1
Хорошо, это был soln, с которым я пошел в конце. Обратите внимание, что это не сработало, пока я не использовал комментарий Джона re: viewDidLayoutSubviews:
daver
1
Это было самым быстрым и выглядит лучше всего.
Уэстон
5

Для лучшего эффекта вы должны использовать пользовательское (растягиваемое) фоновое изображение. Это также, как UITextFieldнарисована округленная граница.

kennytm
источник
4

Один из способов сделать это без программирования - сделать фон текстового поля прозрачным, а затем поместить круглую кнопку Rect позади него. Обязательно измените настройки кнопки, чтобы отключить ее, и снимите Disable adjusts imageфлажок.

Andrew_L
источник
4

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

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

DCKit: ограниченный UITextView

У этого также есть много других полезных функций, таких как текстовые поля с проверкой, элементы управления с границами, пунктирные границы, представления круга и линии роста волос и т. Д.

Андрей Гордеев
источник
4

Я знаю, что на этот вопрос уже есть много ответов, но я не нашел ни одного из них достаточным (по крайней мере, в Swift). Я хотел решение, которое предоставило бы ту же самую точную границу, что и 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);
    }        
}
BobDickinson
источник
3

Один из способов сделать это без программирования - сделать фон текстового поля прозрачным, а затем поместить круглую кнопку Rect позади него. Обязательно измените настройки кнопки, чтобы отключить ее, и снимите флажок «Отключить настройки изображения».

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

Apple Jooce
источник
3

Есть отличное фоновое изображение, идентичное UITextViewиспользуемому для отправки текстовых сообщений в приложении Сообщения iPhone. Вам понадобится Adobe Illustrator, чтобы получить и изменить его. iphone UI векторные элементы

ma11hew28
источник
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;
Nate
источник
Или просто сделайте текстовое поле в конструкторе интерфейса. Затем установите высоту в коде (так как интерфейсный конструктор не позволит вам). CGRect frameRect = self.textField.frame; frameRect.size.height = 50; self.textField.frame = frameRect;
2013 года
2

Если вы хотите, чтобы ваш код контроллера был чистым, вы можете создать подкласс UITextView, как показано ниже, и изменить имя класса в Интерфейсном Разработчике.

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

Это старый вопрос, и я также искал ответ на этот вопрос. Ответ Лювьера на 100% правильный, и позже Роб добавил код. Это отлично, но я нашел стороннюю компанию в ответе на другие вопросы, которая мне кажется очень полезной. Я не только искал подобный взгляд на UITextFieldболее UITextView, я также искал многострочную поддержку. ChatInputSample удовлетворяет оба. Вот почему я думаю, что эта третья сторона может быть полезна для других. Также благодаря Тимуру он упомянул этот открытый исходный код здесь .

Sumon
источник
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];
jowie
источник
вопрос по поводу textview.
Азик Абдулла
Извините - вызвать счастливый стековый ответ. Было бы интересно узнать, почему они не могут просто использовать UITextFieldс userInteractionEnabledустановленным на NO.
Джоуи
Textfield не поддерживает несколько строк
Азик Абдулла
понят. Спасибо за разъяснение
Джоуи