Como estilizar o UITextview para gostar do campo de texto Rect arredondado?


170

Estou usando uma exibição de texto como compositor de comentários.

No inspetor de propriedades, não consigo encontrar nada como uma propriedade de estilo de borda para poder usar um retângulo arredondado, algo como UITextField.

Portanto, a pergunta é: como posso estilizar um UITextViewlike a UITextFieldcom um retângulo arredondado?


1
Você não pode usar UITextFielde simplesmente desligar userInteractionEnabled?
jowie

Respostas:


285

Não há um estilo implícito que você precise escolher; isso envolve escrever um pouco de código usando a QuartzCoreestrutura:

//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;

Funciona apenas no OS 3.0 e superior, mas acho que agora é a plataforma de fato.


47
Eu encontrei adicionando o seguinte top o código acima faz com que a borda pareça muito perto de um UITextField. [textView.layer setBorderColor: [[[UIColor greyColor] colorWithAlphaComponent: 0.5] CGColor]]; [textView.layer setBorderWidth: 2.0];
Rob

12
Certifique-se de ter: #import <QuartzCore / QuartzCore.h>. Tive problemas porque não importei o QuartzCore
austen

1
Para n00bs como eu, digno de nota: colocar esse código em viewDidLoad não em initWithNibName :-)
Brian Colavito

1
Você pode simplesmente usar um UITextFieldcom a borderStylepropriedade definida como UITextBorderStyleRoundedRect- veja meu post abaixo.
jowie

5
O iOS 7 - borderWidth de 1.0 e alpha de .2 funciona com o estilo padrão.
Kalel Wade

77

esse código funcionou bem para mim:

    [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
Eu diria que 5px está mais próximo dos campos de texto, mas a cor cinza desta resposta é melhor que a resposta selecionada.
Peter DeWeese 15/09

2
Claro que você precisa adicionar o QuartzCore Framework para esta resposta e importá-lo por #import <QuartzCore / QuartzCore.h> #
lukaswelte

36

Versão Swift 3

Após configurar a visualização de texto no construtor de interface.

@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
}

Versão 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
O problema é que não está exatamente cinza. A cor do quadro do UITextField é um pouco diferente.
Makalele

1
Fazendo .borderWidth = 0,7 faz com que pareça mais perto de estilo atual I ver em iOS 11.
Chris Amelinckx

28

Editar: você precisa importar

#import <QuartzCore/QuartzCore.h>

para usar o raio do canto.

Tente isso funcionará com certeza

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

Como Rob descobriu, definindo se você deseja que a cor da borda seja semelhante, UITextFieldentão você precisa alterar a largura da borda para 2.0 e a cor para cinza adicionando a seguinte linha

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

2
Fiquei me perguntando por que isso não estava funcionando. Obrigado pela denúncia sobre o QuartzCore.
Echilon

23

Eu queria o negócio real, então adicionei UIImageViewcomo uma sub-visualização do arquivo UITextView. Isso corresponde à borda nativa em um UITextField, incluindo o gradiente de cima para baixo:

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];

Estas são as imagens que eu uso:

insira a descrição da imagem aqui insira a descrição da imagem aqui


2
Eu acho que você também precisa dizer ao textView ter UITextBorderStyle Nenhum se você não tiver que já está definido no XCode
superlogical

1
Eu reenviei as imagens png
Ben Packard

5
Não é bom, o plano de fundo se move à medida que você rola o UITextView. Acho que vou ter que colocar tudo em um UIView pai.
Oliver Pearmain 28/02

1
Excelente. Isso parece ótimo: D
Sune Trudslev 16/09

12

Uma solução é adicionar um UITextField abaixo do UITextView , tornar o UITextViewplano de fundo transparente e desativar qualquer interação do usuário no UITextField. Em seguida, no código, mude o UITextFieldquadro com algo parecido

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

Você terá exatamente a mesma aparência de um campo de texto.

E como sugerido por Jon , você deve inserir esse código [UIViewController viewDidLayoutSubviews]no iOS 5.0 ou superior.


1
Isso era tão simples e parece exatamente como eu queria. Acabei de corresponder o quadro do UITextField ao UITextView: CGRect frame = self.myTextView.frame; frame.size.height + = 2; self.myTextField.frame = quadro;
Página

1
Resposta adorável. Limpo e simples. Coloque o código viewDidLayoutSubviews:(iOS 5.0 ou superior).
9133 Jon

1
Bom, este foi o soln com quem fui no final. Observe que ele não funcionou até que eu usei o comentário de Jon re: viewDidLayoutSubviews:
daver

1
Este foi o mais rápido e parece o melhor.
Weston

5

Para obter o melhor efeito, você deve usar uma imagem de plano de fundo personalizada (extensível). É também assim que a UITextFieldborda arredondada da linha é desenhada.


4

Uma maneira que encontrei para fazer isso sem programação é tornar o fundo do campo de texto transparente e, em seguida, colocar um botão Rect Round atrás dele. Altere as configurações do botão para desativá-lo e desmarque a Disable adjusts imagecaixa de seleção.


4

Você pode conferir minha biblioteca chamada DCKit .

Você seria capaz de fazer uma exibição de texto de canto arredondado (assim como o campo de texto / botão / sem formatação UIView) Interface Builderdiretamente:

DCKit: UITextView delimitado

Ele também possui muitos outros recursos úteis, como campos de texto com validação, controles com bordas, bordas tracejadas, vistas de círculo e linha fina etc.


4

Eu sei que já existem muitas respostas para essa, mas realmente não achei nenhuma delas suficiente (pelo menos em Swift). Eu queria uma solução que fornecesse a mesma borda exata que um UITextField (não uma aproximada que pareça mais ou menos agora, mas uma que seja exatamente igual e sempre será exatamente igual). Eu precisava usar um UITextField para fazer backup do UITextView para o segundo plano, mas não queria criar isso separadamente todas as vezes.

A solução abaixo é um UITextView que fornece seu próprio UITextField para a borda. Esta é uma versão reduzida da minha solução completa (que adiciona suporte de "espaço reservado" ao UITextView de maneira semelhante) e foi publicada aqui: 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

Uma maneira que encontrei para fazer isso sem programação é tornar o fundo do campo de texto transparente e, em seguida, colocar um botão Rect Round atrás dele. Altere as configurações do botão para desativá-lo e desmarque a caixa de seleção Desativar ajusta a imagem.

Tentei o código Quartzcore e constatei que ele causava atraso no meu antigo 3G (eu uso para testes). Não é um grande problema, mas se você quiser ser o mais inclusivo possível para diferentes ios e hardware, recomendo a resposta de Andrew_L acima - ou faça suas próprias imagens e aplique de acordo.



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

Você pode criar um campo de texto que não aceita eventos em cima de uma exibição de texto como esta:

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;

Ou apenas faça um campo de texto no construtor de interfaces. Em seguida, defina a altura no código (já que o criador da interface não permite). CGRect frameRect = self.textField.frame; frameRect.size.height = 50; self.textField.frame = frameRect;
Audub 10/03

2

Se você deseja manter o código do seu controlador limpo, pode subclassificar o UITextView como abaixo e alterar o nome da classe no 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

Aqui está a minha solução:

- (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

Eu não acho que isso é possível. mas você pode fazer UITableView(agrupado) com 1 seção e 1 célula vazia e usá-lo como um contêiner para o seu UITextView.


0

Esta é uma pergunta antiga, e eu também fui procurado por esta resposta. A resposta de luvieeres está 100% correta e mais tarde Rob adicionou algum código. Isso é excelente, mas encontrei um terceiro em outra pergunta. que me parece muito útil. Eu não apenas procurei por aparência semelhante , mas também por suporte a UITextFieldvárias UITextViewlinhas. ChatInputSample satisfeito ambos. É por isso que acho que esse terceiro pode ser útil para outras pessoas. Também graças a Timur, ele mencionou esse código aberto aqui .


0

No iOS7, o seguinte corresponde perfeitamente à borda UITextField (pelo menos aos meus olhos):

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

Não há necessidade de importar nada de especial.

Graças a @uvieere e @hanumanDev cujas respostas vão quase lá :)


-1

Que tal apenas:

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

pergunta é sobre textview.
Azik Abdullah

Desculpe - desencadeie uma resposta feliz da pilha. Estaria interessado em saber por que eles não poderiam simplesmente usar um UITextFieldcom userInteractionEnableddefinido como NO.
jowie

O campo de texto não suporta múltiplas linhas
Azik Abdullah

Entendido. Obrigado por esclarecer
jowie
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.