境界線をUITextField
の下の部分だけにしたいのですが。しかし、私たちがどのようにしてそれを底辺に保つことができるのか私は知りません。
教えてください。
結局、私はこれをするもう一つの方法を見つけました、それはより単純で便利です。しかし唯一の条件はUITextField
が自動レイアウトを含まなければならないということです。
ここではVFL(Visual Formatting Language)を使用しています。これにより、任意のUIControl
に1行追加できます。
ヘルパーメソッド
このヘルパーメソッドは、グローバルヘルパークラス(私はグローバルクラスメソッドを使用しました)に追加することも、同じView Controller(インスタンスメソッドを使用)に追加することもできます。
typedef enum : NSUInteger {
LINE_POSITION_TOP,
LINE_POSITION_BOTTOM
} LINE_POSITION;
- (void) addLineToView:(UIView *)view atPosition:(LINE_POSITION)position withColor:(UIColor *)color lineWitdh:(CGFloat)width {
// Add line
UIView *lineView = [[UIView alloc] init];
[lineView setBackgroundColor:color];
[lineView setTranslatesAutoresizingMaskIntoConstraints:NO];
[view addSubview:lineView];
NSDictionary *metrics = @{@"width" : [NSNumber numberWithFloat:width]};
NSDictionary *views = @{@"lineView" : lineView};
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[lineView]|" options: 0 metrics:metrics views:views]];
switch (position) {
case LINE_POSITION_TOP:
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[lineView(width)]" options: 0 metrics:metrics views:views]];
break;
case LINE_POSITION_BOTTOM:
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[lineView(width)]|" options: 0 metrics:metrics views:views]];
break;
default: break;
}
}
使用法
[self addLineToView:self.textField atPosition:LINE_POSITION_TOP withColor:[UIColor darkGrayColor] lineWitdh:0.5];
Swiftを使用している場合
ヘルパーメソッド
enum LINE_POSITION {
case LINE_POSITION_TOP
case LINE_POSITION_BOTTOM
}
func addLineToView(view : UIView, position : LINE_POSITION, color: UIColor, width: Double) {
let lineView = UIView()
lineView.backgroundColor = color
lineView.translatesAutoresizingMaskIntoConstraints = false // This is important!
view.addSubview(lineView)
let metrics = ["width" : NSNumber(value: width)]
let views = ["lineView" : lineView]
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[lineView]|", options:NSLayoutFormatOptions(rawValue: 0), metrics:metrics, views:views))
switch position {
case .LINE_POSITION_TOP:
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[lineView(width)]", options:NSLayoutFormatOptions(rawValue: 0), metrics:metrics, views:views))
break
case .LINE_POSITION_BOTTOM:
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[lineView(width)]|", options:NSLayoutFormatOptions(rawValue: 0), metrics:metrics, views:views))
break
default:
break
}
}
使用法
self.addLineToView(view: textField, position:.LINE_POSITION_BOTTOM, color: UIColor.darkGray, width: 0.5)
プログラムでUITextField
オブジェクトを作成すれば、この答えは完璧に機能します。
注: StoryboardでUITextField
オブジェクトが作成された場合は、Storyboard Attributes InspectorでBorder Style
プロパティをNone
に設定してください。
次の変数textField
は、下罫線が設定されるUITextField
コントロールのオブジェクトです。
Swift code:
let border = CALayer()
let width = CGFloat(2.0)
border.borderColor = UIColor.darkGray.cgColor
border.frame = CGRect(x: 0, y: textField.frame.size.height - width, width: textField.frame.size.width, height: textField.frame.size.height)
border.borderWidth = width
textField.layer.addSublayer(border)
textField.layer.masksToBounds = true
Objective C Code:
CALayer *border = [CALayer layer];
CGFloat borderWidth = 2;
border.borderColor = [UIColor darkGrayColor].CGColor;
border.frame = CGRectMake(0, textField.frame.size.height - borderWidth, textField.frame.size.width, textField.frame.size.height);
border.borderWidth = borderWidth;
[textField.layer addSublayer:border];
textField.layer.masksToBounds = YES;
Xamarin code:
var border = new CALayer();
nfloat width = 2;
border.BorderColor = UIColor.Black.CGColor;
border.Frame = new CoreGraphics.CGRect(0, textField.Frame.Size.Height - width, textField.Frame.Size.Width, textField.Frame.Size.Height);
border.BorderWidth = width;
textField.Layer.AddSublayer(border);
textField.Layer.MasksToBounds = true;
多くのユーザーは自動レイアウトに問題があり、一部の人はUITextFieldの境界をレンダリングできませんでした。これが解決策です:
その時よりもviewDidLoad()
メソッドで以下のコードを書いた場合、あなたはtextFieldのフレームを取得できないでしょう。そのため、そのボーダーは正しくレンダリングされません。
枠線の正しいフレームを取得するには、viewDidLayoutSubviews()
をオーバーライドしてその中にコードを書きます。
すべてのサブビューがビューにロードされた後に呼び出されるviewDidLayoutSubviews()
メソッド。
このメソッドが複数回呼び出され、それがViewControllerのライフサイクルの一部ではないことを忘れないでください。したがって、これを使用するときは注意してください。
あなたがフレームを知らずにを事前に行いたい場合、サブクラス化せずにそして自動レイアウトなし:
Swift 4.x/Swift 3.x
extension UITextField {
func setBottomBorder() {
self.borderStyle = .none
self.layer.backgroundColor = UIColor.white.cgColor
self.layer.masksToBounds = false
self.layer.shadowColor = UIColor.gray.cgColor
self.layer.shadowOffset = CGSize(width: 0.0, height: 1.0)
self.layer.shadowOpacity = 1.0
self.layer.shadowRadius = 0.0
}
}
フレームが正しいことを確認せずに、どこからでもyourTextField.setBottomBorder()
として呼び出します。
結果は次のようになります。
以下に示すように、UITextField
のサブクラスを作成できます。
class TextField : UITextField {
override var tintColor: UIColor! {
didSet {
setNeedsDisplay()
}
}
override func draw(_ rect: CGRect) {
let startingPoint = CGPoint(x: rect.minX, y: rect.maxY)
let endingPoint = CGPoint(x: rect.maxX, y: rect.maxY)
let path = UIBezierPath()
path.move(to: startingPoint)
path.addLine(to: endingPoint)
path.lineWidth = 2.0
tintColor.setStroke()
path.stroke()
}
}
これらの解決策のどれも本当に私の期待に応えませんでした。常に手動で境界線を設定したくないので、サブクラス TextFieldにしたかったのです。私もしたかった境界色を変更する例えばエラーの場合だからここにAnchors
と私の解決策です:
class CustomTextField: UITextField {
var bottomBorder = UIView()
override func awakeFromNib() {
// Setup Bottom-Border
self.translatesAutoresizingMaskIntoConstraints = false
bottomBorder = UIView.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
bottomBorder.backgroundColor = UIColor(rgb: 0xE2DCD1) // Set Border-Color
bottomBorder.translatesAutoresizingMaskIntoConstraints = false
addSubview(bottomBorder)
bottomBorder.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
bottomBorder.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
bottomBorder.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
bottomBorder.heightAnchor.constraint(equalToConstant: 1).isActive = true // Set Border-Strength
}
}
----オプション----
色を変更するには、次のようにsthをCustomTextField Class
に追加します。
@IBInspectable var hasError: Bool = false {
didSet {
if (hasError) {
bottomBorder.backgroundColor = UIColor.red
} else {
bottomBorder.backgroundColor = UIColor(rgb: 0xE2DCD1)
}
}
}
そして、CustomTextFieldのインスタンスを作成した後にError呼び出しをトリガーします。
textField.hasError = !textField.hasError
それが誰かに役立つことを願っています;)
extension UITextField {
func setBottomBorder(color:String) {
self.borderStyle = UITextBorderStyle.None
let border = CALayer()
let width = CGFloat(1.0)
border.borderColor = UIColor(hexString: color)!.cgColor
border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: self.frame.size.height)
border.borderWidth = width
self.layer.addSublayer(border)
self.layer.masksToBounds = true
}
}
そして、これを実行してください。
yourTextField.setBottomBorder(color: "#3EFE46")
このエクステンションをクラス外で作成し、widthをあなたが望む任意のborderWidthで置き換えることができます。
Swift 4
extension UITextField
{
func setBottomBorder(withColor color: UIColor)
{
self.borderStyle = UITextBorderStyle.none
self.backgroundColor = UIColor.clear
let width: CGFloat = 1.0
let borderLine = UIView(frame: CGRect(x: 0, y: self.frame.height - width, width: self.frame.width, height: width))
borderLine.backgroundColor = color
self.addSubview(borderLine)
}
}
オリジナル
extension UITextField
{
func setBottomBorder(borderColor: UIColor)
{
self.borderStyle = UITextBorderStyle.None
self.backgroundColor = UIColor.clearColor()
let width = 1.0
let borderLine = UIView(frame: CGRectMake(0, self.frame.height - width, self.frame.width, width))
borderLine.backgroundColor = borderColor
self.addSubview(borderLine)
}
}
そして、これをあなたのviewDidLoadに追加してください。
yourTextField.setBottomBorder(UIColor.blackColor())
これは基本的にテキストフィールドの下部にその色のビューを追加します。
目標C
[txt.layer setBackgroundColor: [[UIColor whiteColor] CGColor]];
[txt.layer setBorderColor: [[UIColor grayColor] CGColor]];
[txt.layer setBorderWidth: 0.0];
[txt.layer setCornerRadius:12.0f];
[txt.layer setMasksToBounds:NO];
[txt.layer setShadowRadius:2.0f];
txt.layer.shadowColor = [[UIColor blackColor] CGColor];
txt.layer.shadowOffset = CGSizeMake(1.0f, 1.0f);
txt.layer.shadowOpacity = 1.0f;
txt.layer.shadowRadius = 1.0f;
スウィフト
txt.layer.backgroundColor = UIColor.white.cgColor
txt.layer.borderColor = UIColor.gray.cgColor
txt.layer.borderWidth = 0.0
txt.layer.cornerRadius = 5
txt.layer.masksToBounds = false
txt.layer.shadowRadius = 2.0
txt.layer.shadowColor = UIColor.black.cgColor
txt.layer.shadowOffset = CGSize.init(width: 1.0, height: 1.0)
txt.layer.shadowOpacity = 1.0
txt.layer.shadowRadius = 1.0
以下のコードサンプルをご覧ください。
Swift 4:
@IBDesignable class DesignableUITextField: UITextField {
let border = CALayer()
@IBInspectable var borderColor: UIColor? {
didSet {
setup()
}
}
@IBInspectable var borderWidth: CGFloat = 0.5 {
didSet {
setup()
}
}
func setup() {
border.borderColor = self.borderColor?.cgColor
border.borderWidth = borderWidth
self.layer.addSublayer(border)
self.layer.masksToBounds = true
}
override func layoutSubviews() {
super.layoutSubviews()
border.frame = CGRect(x: 0, y: self.frame.size.height - borderWidth, width: self.frame.size.width, height: self.frame.size.height)
}
}
Swift 3の場合拡張機能を作成してビュークラスの後に追加できます。
extension UITextField
{
func setBottomBorder(borderColor: UIColor)
{
self.borderStyle = UITextBorderStyle.none
self.backgroundColor = UIColor.clear
let width = 1.0
let borderLine = UIView()
borderLine.frame = CGRect(x: 0, y: Double(self.frame.height) - width, width: Double(self.frame.width), height: width)
borderLine.backgroundColor = borderColor
self.addSubview(borderLine)
}
}
私がしたのは、UITextFieldの拡張機能を作成し、Designerの編集可能なプロパティを追加することでした。このプロパティを任意の色に設定すると、境界線(下部)がその色に変更されます(他の境界線をなしに設定)。
これもプレースホルダーのテキストの色を変更する必要があるので、私はまたそれを拡張子に追加しました。
extension UITextField {
@IBInspectable var placeHolderColor: UIColor? {
get {
return self.placeHolderColor
}
set {
self.attributedPlaceholder = NSAttributedString(string:self.placeholder != nil ? self.placeholder! : "", attributes:[NSForegroundColorAttributeName: newValue!])
}
}
@IBInspectable var bottomBorderColor: UIColor? {
get {
return self.bottomBorderColor
}
set {
self.borderStyle = UITextBorderStyle.None;
let border = CALayer()
let width = CGFloat(0.5)
border.borderColor = newValue?.CGColor
border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: self.frame.size.height)
border.borderWidth = width
self.layer.addSublayer(border)
self.layer.masksToBounds = true
}
}
}
これは@IBInspectable付きのSwift3コードです。
新しいファイルを作成します。Cocoa Touch Class Swiftファイル
import UIKit
extension UIView {
@IBInspectable var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.masksToBounds = newValue > 0
}
}
@IBInspectable var borderWidth: CGFloat {
get {
return layer.borderWidth
}
set {
layer.borderWidth = newValue
}
}
@IBInspectable var borderColor: UIColor? {
get {
return UIColor(cgColor: layer.borderColor!)
}
set {
layer.borderColor = newValue?.cgColor
}
}
@IBInspectable var leftBorderWidth: CGFloat {
get {
return 0.0 // Just to satisfy property
}
set {
let line = UIView(frame: CGRect(x: 0.0, y: 0.0, width: newValue, height: bounds.height))
line.translatesAutoresizingMaskIntoConstraints = false
line.backgroundColor = UIColor(cgColor: layer.borderColor!)
line.tag = 110
self.addSubview(line)
let views = ["line": line]
let metrics = ["lineWidth": newValue]
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "|[line(==lineWidth)]", options: [], metrics: metrics, views: views))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[line]|", options: [], metrics: nil, views: views))
}
}
@IBInspectable var topBorderWidth: CGFloat {
get {
return 0.0 // Just to satisfy property
}
set {
let line = UIView(frame: CGRect(x: 0.0, y: 0.0, width: bounds.width, height: newValue))
line.translatesAutoresizingMaskIntoConstraints = false
line.backgroundColor = borderColor
line.tag = 110
self.addSubview(line)
let views = ["line": line]
let metrics = ["lineWidth": newValue]
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "|[line]|", options: [], metrics: nil, views: views))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[line(==lineWidth)]", options: [], metrics: metrics, views: views))
}
}
@IBInspectable var rightBorderWidth: CGFloat {
get {
return 0.0 // Just to satisfy property
}
set {
let line = UIView(frame: CGRect(x: bounds.width, y: 0.0, width: newValue, height: bounds.height))
line.translatesAutoresizingMaskIntoConstraints = false
line.backgroundColor = borderColor
line.tag = 110
self.addSubview(line)
let views = ["line": line]
let metrics = ["lineWidth": newValue]
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "[line(==lineWidth)]|", options: [], metrics: metrics, views: views))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[line]|", options: [], metrics: nil, views: views))
}
}
@IBInspectable var bottomBorderWidth: CGFloat {
get {
return 0.0 // Just to satisfy property
}
set {
let line = UIView(frame: CGRect(x: 0.0, y: bounds.height, width: bounds.width, height: newValue))
line.translatesAutoresizingMaskIntoConstraints = false
line.backgroundColor = borderColor
line.tag = 110
self.addSubview(line)
let views = ["line": line]
let metrics = ["lineWidth": newValue]
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "|[line]|", options: [], metrics: nil, views: views))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[line(==lineWidth)]|", options: [], metrics: metrics, views: views))
}
}
func removeborder() {
for view in self.subviews {
if view.tag == 110 {
view.removeFromSuperview()
}
}
}
}
そして、以下のコードでファイルを置き換えてください、そうすればあなたはこのようなストーリーボード属性インスペクターでオプションを得るでしょう。
楽しい :)
**ここでmyTFはMT TEXT FIELDのアウトレットです**
let border = CALayer()
let width = CGFloat(2.0)
border.borderColor = UIColor.darkGray.cgColor
border.frame = CGRect(x: 0, y: self.myTF.frame.size.height - width, width: self.myTF.frame.size.width, height: self.myTF.frame.size.height)
border.borderWidth = width
self.myTF.layer.addSublayer(border)
self.myTF.layer.masksToBounds = true
下の境界線用に1つの画像を作成し、それをUITextFieldの背景に設定できます。
yourTextField.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"yourBorderedImageName"]];
または、borderStyleをnoneに設定し、lineの画像をtextfieldと正確に同じ長さにします。
更新コード:
Swift 5.
extension UITextField {
func addUnderline() {
let layer = CALayer()
layer.backgroundColor = #colorLiteral(red: 0.6666666865, green: 0.6666666865, blue: 0.6666666865, alpha: 1)
layer.frame = CGRect(x: 0.0, y: self.frame.size.height - 1.0, width: self.frame.size.width, height: 1.0)
self.clipsToBounds = true
self.layer.addSublayer(layer)
self.setNeedsDisplay()} }
このfuncをviewDidLayoutSubviews()で呼び出します
override func viewDidLayoutSubviews() {
textField.addUnderline()
}
注:このメソッドはviewDidLayoutSubviews()でのみ動作します
ビューの場合:(最も推奨)UIView extension
を使用して、すべてのタイプのUIView
サブクラス(view、textfiled、labelなど)で機能します。
よりシンプルで便利です。ただし、唯一の条件はview
に自動レイアウトが含まれている必要があります。
extension UIView {
enum Line_Position {
case top
case bottom
}
func addLine(position : Line_Position, color: UIColor, height: Double) {
let lineView = UIView()
lineView.backgroundColor = color
lineView.translatesAutoresizingMaskIntoConstraints = false // This is important!
self.addSubview(lineView)
let metrics = ["width" : NSNumber(value: height)]
let views = ["lineView" : lineView]
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[lineView]|", options:NSLayoutConstraint.FormatOptions(rawValue: 0), metrics:metrics, views:views))
switch position {
case .top:
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[lineView(width)]", options:NSLayoutConstraint.FormatOptions(rawValue: 0), metrics:metrics, views:views))
break
case .bottom:
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[lineView(width)]|", options:NSLayoutConstraint.FormatOptions(rawValue: 0), metrics:metrics, views:views))
break
}
}
}
使用方法
// UILabel
self.lblDescription.addLine(position: .bottom, color: UIColor.blue, height: 1.0)
// UITextField
self.txtArea.addLine(position: .bottom, color: UIColor.red, height: 1.0)