Jak stylizować widok UITextview na polubienie pola tekstowego Rounded Rect?

170

Używam widoku tekstu jako kompozytora komentarzy.

W inspektorze właściwości nie mogę znaleźć nic takiego jak właściwość stylu obramowania, więc mogę użyć zaokrąglonego prostokąta, na przykład UITextField.

A więc pytanie brzmi: jak stylizować UITextViewlike a UITextFieldz zaokrąglonym prostokątem?

harshalb
źródło
1
Nie mógłbyś użyć UITextFieldi po prostu wyłączyć userInteractionEnabled?
jowie

Odpowiedzi:

285

Nie ma żadnego domyślnego stylu, który musisz wybrać, polega na napisaniu fragmentu kodu przy użyciu QuartzCoreframeworka:

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

Działa tylko na OS 3.0 i nowszych, ale myślę, że teraz i tak jest to platforma de facto.

luvieere
źródło
47
Zauważyłem, że dodanie następującego u góry powyższego kodu sprawia, że ​​obramowanie wygląda bardzo blisko UITextField. [textView.layer setBorderColor: [[[UIColor grayColor] colorWithAlphaComponent: 0.5] CGColor]]; [textView.layer setBorderWidth: 2.0];
Rob
12
Upewnij się, że masz: #import <QuartzCore / QuartzCore.h>. Miałem problemy, ponieważ nie importowałem QuartzCore
austen
1
Dla n00bs takich jak ja, godny uwagi: umieść ten kod w widoku DidLoad NOT initWithNibName :-)
Brian Colavito
1
Możesz po prostu użyć a UITextFieldz borderStylewłaściwością ustawioną na UITextBorderStyleRoundedRect- zobacz mój post poniżej.
jowie
5
iOS 7 - borderWidth of 1.0 i alpha of .2 działa z domyślnym stylem.
Kalel Wade
77

ten kod działał dobrze dla mnie:

    [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
źródło
4
Powiedziałbym, że 5px jest bliżej pól tekstowych, ale szary kolor tej odpowiedzi jest lepszy niż zaznaczona odpowiedź.
Peter DeWeese
2
Oczywiście musisz dodać QuartzCore Framework do tej odpowiedzi i zaimportować ją przez #import <QuartzCore / QuartzCore.h>
lukaswelte
36

Wersja Swift 3

Po skonfigurowaniu widoku tekstu w kreatorze interfejsów.

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

Wersja 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
}
Sean McClory
źródło
1
Problem w tym, że nie jest dokładnie szary. Kolor ramki UITextField jest nieco inny.
Makalele
1
Utworzenie .borderWidth = 0,7 sprawia, że ​​wygląda on bliżej obecnego stylu, który widzę na iOS 11.
Chris Amelinckx
28

Edycja: musisz importować

#import <QuartzCore/QuartzCore.h>

do stosowania promienia narożnika.

Spróbuj tego, na pewno zadziała

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

Tak jak Rob to wymyślił, ustawiając, jeśli chcesz, aby kolor obramowania był podobny UITextField, musisz zmienić szerokość obramowania na 2.0, a kolor na szary, dodając następującą linię

[textView.layer setBorderColor:[[[UIColor grayColor] colorWithAlphaComponent:0.5] CGColor]]; 
[textView.layer setBorderWidth:2.0];
Suresh Varma
źródło
2
Zastanawiałem się, dlaczego to nie działa. Dzięki za wskazówkę dotyczącą QuartzCore.
Echilon,
23

Chciałem prawdziwej oferty, więc dodaję UIImageViewjako podrzędny podgląd pliku UITextView. To dopasowuje natywną ramkę na a UITextField, w tym gradient od góry do dołu:

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

Oto obrazy, których używam:

wprowadź opis obrazu tutaj wprowadź opis obrazu tutaj

Ben Packard
źródło
2
Myślę, że musisz również powiedzieć textView, aby miał UITextBorderStyle None, jeśli nie ustawiłeś tego już w XCode
superlogical
1
Ponownie załadowałem obrazy png
Ben Packard
5
Nie dobrze, tło porusza się podczas przewijania UITextView. Chyba będę musiał umieścić to wszystko w nadrzędnym UIView.
Oliver Pearmain
1
Doskonały. Wygląda świetnie: D
Sune Trudslev,
12

Jednym z rozwiązań jest dodanie UITextField poniżej UITextView , ustawienie UITextViewprzezroczystości tła i wyłączenie wszelkich interakcji użytkownika w UITextField. Następnie w kodzie zmień UITextFieldramkę na coś takiego

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

Będziesz mieć dokładnie taki sam wygląd jak pole tekstowe.

Zgodnie z sugestią Jona , powinieneś umieścić ten fragment kodu w [UIViewController viewDidLayoutSubviews]systemie iOS 5.0+.

Phil
źródło
1
To było takie proste i wygląda dokładnie tak, jak chciałem. Właśnie dopasowałem ramkę UITextField do UITextView: CGRect frame = self.myTextView.frame; frame.size.height + = 2; self.myTextField.frame = ramka;
Kupuj Briana
1
Śliczna odpowiedź. Czyste i proste. Umieść kod w viewDidLayoutSubviews:(iOS 5.0+).
Jon
1
Fajnie, to był soln, na który poszedłem w końcu. Zauważ, że to nie zadziałało, dopóki nie użyłem komentarza Jona re: viewDidLayoutSubviews:
daver
1
To było najszybsze i wygląda najlepiej.
Weston
5

Aby uzyskać najlepszy efekt, należy użyć niestandardowego (rozciągliwego) obrazu tła. W ten sposób UITextFieldrysowana jest również zaokrąglona granica.

kennytm
źródło
4

Jednym ze sposobów, w jaki udało mi się to zrobić bez programowania, jest uczynienie tła pola tekstowym przezroczystym, a następnie umieszczenie za nim okrągłego przycisku prostego. Pamiętaj, aby zmienić ustawienia przycisku, aby go wyłączyć, i usuń zaznaczenie Disable adjusts imagepola wyboru.

Andrew_L
źródło
4

Możesz sprawdzić moją bibliotekę o nazwie DCKit .

Byłbyś w stanie zrobić zaokrąglony narożnik widoku tekstu (a także pole tekstowe / przycisk / zwykły UIView) Interface Builderbezpośrednio z:

DCKit: graniczy UITextView

Posiada również wiele innych przydatnych funkcji, takich jak pola tekstowe z walidacją, kontrolki z ramkami, przerywane obramowania, widoki kół i linii tekstu itp.

Andrey Gordeev
źródło
4

Wiem, że jest już wiele odpowiedzi na to pytanie, ale żadna z nich nie była wystarczająca (przynajmniej w Swift). Zależało mi na rozwiązaniu, które zapewnia taką samą dokładną ramkę jak UITextField (nie przybliżone, które wygląda trochę tak, jak wygląda teraz, ale takie, które wygląda dokładnie tak, jak to i zawsze będzie dokładnie tak wyglądać). Musiałem użyć UITextField, aby utworzyć kopię zapasową UITextView dla tła, ale nie chciałem za każdym razem tworzyć tego osobno.

Poniższe rozwiązanie to UITextView, który dostarcza własne UITextField dla obramowania. To jest okrojona wersja mojego pełnego rozwiązania (która dodaje obsługę „symbolu zastępczego” do UITextView w podobny sposób) i została opublikowana tutaj: 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
źródło
3

Jednym ze sposobów, w jaki udało mi się to zrobić bez programowania, jest uczynienie tła pola tekstowym przezroczystym, a następnie umieszczenie za nim okrągłego przycisku prostego. Pamiętaj, aby zmienić ustawienia przycisku, aby go wyłączyć, i usuń zaznaczenie pola wyboru Wyłącz dostosowuje obraz.

Wypróbowałem kod Quartzcore i stwierdziłem, że powoduje on opóźnienia w moim starym 3G (używam do testów). Nie jest to duży problem, ale jeśli chcesz być maksymalnie włączony dla różnych systemów iOS i sprzętu, polecam odpowiedź Andrew_L powyżej - lub stwórz własne obrazy i zastosuj odpowiednio.

Apple Jooce
źródło
3

Istnieje świetny obraz tła, który jest identyczny z UITextViewużywanym do wysyłania wiadomości tekstowych w aplikacji Wiadomości iPhone'a. Będziesz potrzebować programu Adobe Illustrator, aby go pobrać i zmodyfikować. elementy wektorowe iphone ui

ma11hew28
źródło
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];
}
Sonu
źródło
2

Możesz utworzyć pole tekstowe, które nie akceptuje żadnych wydarzeń w górnej części widoku tekstowego, w następujący sposób:

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
źródło
Lub po prostu utwórz pole tekstowe w kreatorze interfejsów. Następnie ustaw wysokość w kodzie (ponieważ kreator interfejsu na to nie pozwoli). CGRect frameRect = self.textField.frame; frameRect.size.height = 50; self.textField.frame = frameRect;
audub
2

Jeśli chcesz zachować czysty kod kontrolera, możesz podklasę UITextView, jak poniżej, i zmienić nazwę klasy w 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
Satoshi Nakajima
źródło
1

Oto moje rozwiązanie:

- (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];
        }
    }
}
Manuel Schmitzberger
źródło
0

Nie sądzę, żeby to było możliwe. ale możesz to zrobić UITableView(pogrupowane) z 1 sekcją i 1 pustą komórką i użyć go jako pojemnika dla twojego UITextView.

Morion
źródło
0

To jest stare pytanie, na które również szukałem odpowiedzi. Odpowiedź Luvieeres jest w 100% poprawna, a później Rob dodał kod. To świetnie, ale w odpowiedzi na inne pytanie znalazłem osobę trzecią, która wydaje mi się bardzo pomocna. Ja nie tylko szukał podobnym wyglądzie UITextFieldnad UITextView, ja też szukał wielowierszowego wsparcia. ChatInputSample spełnia oba te wymagania. Dlatego uważam, że ta strona trzecia może być pomocna dla innych. Również dzięki Timurowi wspomniał tutaj o tym open source .

sumon
źródło
0

W iOS7 następujące elementy idealnie pasują do obramowania UITextField (przynajmniej dla mnie):

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

Nie ma potrzeby importowania niczego specjalnego.

Podziękowania dla @uvieere i @hanumanDev, których odpowiedzi prawie mnie docierają :)

Adrian Toman
źródło
-1

Może po prostu:

UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(20, 20, 280, 32)];
textField.borderStyle = UITextBorderStyleRoundedRect;
[self addSubview:textField];
jowie
źródło
pytanie dotyczy widoku tekstu.
Azik Abdullah
Przepraszam - wywołaj odpowiedź szczęśliwego stosu. Chciałbym wiedzieć, dlaczego nie mogli po prostu użyć UITextFieldz userInteractionEnabledzestawem do NO.
jowie
Textfield nie obsługuje wielu wierszy
Azik Abdullah
zrozumiany. Dzięki za wyjaśnienie
jowie