iOS7のUITextfield leftView / rightViewパディング


94

iOS7のUITextFieldのleftViewビューとrightViewビューは、テキストフィールドの境界に非常に近くなっています。

それらのアイテムに(水平)パディングを追加するにはどうすればよいですか?

フレームを変更してみましたが、うまくいきませんでした

uint padding = 10;//padding for iOS7
UIImageView * iconImageView = [[UIImageView alloc] initWithImage:iconImage];    
iconImageView.frame = CGRectMake(0 + padding, 0, 16, 16);
textField.leftView = iconImageView;

UITextBorderStyleNoneを使用したUITextFieldのこのパディングのように、テキストフィールドのテキストにパディングを追加することに興味がないことに注意してください。



1
いいえ、これは、テキストフィールドでleftViewとして表示される画像をインデントすることを求めています。テキスト自体をインデントしません。彼のコードを試してみてください。画像にleftViewを設定すると、パディングなしでテキストフィールドの左端に画像が配置されることがわかります。それは醜く見えます。

回答:


90

私自身これに取り組んでいて、この解決策を使用していました:

- (CGRect) rightViewRectForBounds:(CGRect)bounds {

    CGRect textRect = [super rightViewRectForBounds:bounds];
    textRect.origin.x -= 10;
    return textRect;
}

これにより、iOS 7で画像が端から押し出されるのではなく、画像が右から10だけ移動します。

さらに、これはのサブクラスにありUITextField、次の方法で作成できます。

  1. UITextFieldデフォルトの代わりにのサブクラスである新しいファイルを作成するNSObject
  2. という名前の新しいメソッドを追加し- (id)initWithCoder:(NSCoder*)coderて画像を設定します

    - (id)initWithCoder:(NSCoder*)coder {
        self = [super initWithCoder:coder];
    
        if (self) {
    
            self.clipsToBounds = YES;
            [self setRightViewMode:UITextFieldViewModeUnlessEditing];
    
            self.leftView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"textfield_edit_icon.png"]];
        }
    
        return self;
    }
  3. インポートする必要があるかもしれません #import <QuartzCore/QuartzCore.h>

  4. rightViewRectForBounds上記のメソッドを追加

  5. インターフェイスビルダーで、サブクラス化するTextFieldをクリックし、クラス属性をこの新しいサブクラスの名前に変更します。


これと同じようにIBDesignableを使用する方法?
riddhi 2017年

最新バージョンのかどうかは、2020年の訪問でこれを見ている: stackoverflow.com/a/55041786/6596443を
AKINNUBI ABIOLA SYLVESTER

167

を利用した、はるかに単純なソリューションcontentMode

    arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"down_arrow"]];
    arrow.frame = CGRectMake(0.0, 0.0, arrow.image.size.width+10.0, arrow.image.size.height);
    arrow.contentMode = UIViewContentModeCenter;

    textField.rightView = arrow;
    textField.rightViewMode = UITextFieldViewModeAlways;

Swift 3では

    let arrow = UIImageView(image: UIImage(named: "arrowDrop"))
    if let size = arrow.image?.size {
        arrow.frame = CGRect(x: 0.0, y: 0.0, width: size.width + 10.0, height: size.height)
    }
    arrow.contentMode = UIViewContentMode.center
    self.textField.rightView = arrow
    self.textField.rightViewMode = UITextFieldViewMode.always

1
画像のサイズが正確なフレームと一致しない場合は、center ...の代わりにScaleAspectFitも使用できます。
Mihir Mehta

タイプがInfoLightのときに、UIButtonの例(UIImageViewではなく)を使用しました。
OhadM 2016年

「.center」ではなく「.right」を使用すると、連絡先アプリの検索バーなど、組み込みの検索バーのように見えることがわかりました。投稿していただきありがとうございます。
James Toomey 2017

または、デザインレクリエーションで正確にする必要がある場合は、画像を
.leftに置き

4
これは、iOS 13およびXcode 11 Beta 7では動作しないようです。ただし、iOS 11/12では問題なく動作します。
PatrickDotStar

49

最も簡単な方法は、leftView / righViewにUIViewを追加し、UIViewにImageViewを追加し、UIView内のImageViewの原点を好きな場所に調整することです。これは私にとっては魅力のように機能しました。ほんの数行のコードが必要です

UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 5, 26, 26)];
imgView.image = [UIImage imageNamed:@"img.png"];

UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 32, 32)];
[paddingView addSubview:imgView];
[txtField setLeftViewMode:UITextFieldViewModeAlways];
[txtField setLeftView:paddingView];

UIViewContentMode うまくいきませんが、この答えは魅力のように働きます!
-nigong

14

これはSwiftに最適です。

let imageView = UIImageView(image: UIImage(named: "image.png"))
imageView.contentMode = UIViewContentMode.Center
imageView.frame = CGRectMake(0.0, 0.0, imageView.image!.size.width + 20.0, imageView.image!.size.height)
textField.rightViewMode = UITextFieldViewMode.Always
textField.rightView = imageView

タイプ 'string'の値を予期される引数タイプ 'UIImage?'に変換できません

7

これは私のために働く

UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 20)];
self.passwordTF.leftView = paddingView;
self.passwordTF.leftViewMode = UITextFieldViewModeAlways;

お役に立てれば幸いです。


6

このソリューションは、1行のコードで問題を解決するので気に入っています。

myTextField.layer.sublayerTransform = CATransform3DMakeTranslation(10.0f, 0.0f, 0.0f);

注:QuartzCoreに1行を含めることを検討する場合は、..または2 :)


1
これにより国境も移動します
Softlion、2015

1
しかし、右のパディングの問題は、左のパディングの問題だけでは解決しません
carmen_munich

1
rightView.layer.sublayerTransform = CATransform3DMakeTranslation(-10.0f、0.0f、0.0f)を使用した方が良い結果が得られましたが、メソッドの+1
Thibaud David

これにより、テキストフィールドの[クリア]ボタンも右に移動し、テキストフィールドの端を越えてしまう可能性があることに注意してください。クリアボタンが必要ない場合、これは優れたアプローチです。それ以外の場合は必要ありません。
トムハリントン

4

これを行う最良の方法は、UITextFieldのサブクラスを使用してクラスを作成し、.mファイルで作成することです。

  #import "CustomTextField.h"
  #import <QuartzCore/QuartzCore.h>
  @implementation CustomTextField


- (id)initWithCoder:(NSCoder*)coder 
 {
self = [super initWithCoder:coder];

if (self) {

    //self.clipsToBounds = YES;
    //[self setRightViewMode:UITextFieldViewModeUnlessEditing];

    self.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,15,46)];
    self.leftViewMode=UITextFieldViewModeAlways;
      }

return self;

}

これを行うことにより、ストーリーボードまたはxibに移動し、IDインスペクターをクリックして、UITextfieldをクラスオプションの独自の "CustomTextField"に置き換えます。

注:テキストフィールドの自動レイアウトでパディングを指定するだけの場合、アプリケーションは実行されず、空白の画面のみが表示されます。


4

imageViewまたはimageを操作する代わりに、rightView用にappleが提供するメソッドをオーバーライドできます。

class CustomTextField : UITextField { 

override func rightViewRect(forBounds bounds: CGRect) -> CGRect {
    let offset = 5
    let width  = 20
    let height = width
    let x = Int(bounds.width) - width - offset
    let y = offset
    let rightViewBounds = CGRect(x: x, y: y, width: width, height: height)
    return rightViewBounds
}}

同様に、左側のビューのfuncの下をオーバーライドできます。

override func leftViewRect(forBounds bounds: CGRect) -> CGRect {
    /*return as per requirement*/

}

3

どこかで見つけた...

UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 20)];
paddingView.backgroundColor = [UIColor clearColor];
itemDescription.leftView = paddingView;
itemDescription.leftViewMode = UITextFieldViewModeAlways;

[self addSubview:itemDescription];

4
それは単にテキストにパディングを追加するだけで、それは質問者が探しているものではありません。彼は明確なleftViewを望んでいません。彼は、leftViewとして表示される画像を望んでいます。

画像をpaddingViewに追加するだけです。
Matheus Weber

3

スウィフト5

class CustomTextField: UITextField {
    func invalidate() {
        let errorImage =  UIImageView(image: UIImage(named: "errorImage"))
        errorImage.frame = CGRect(x: 8, y: 8, width: 16, height: 16)
        rightView = UIView(frame: CGRect(x: 0, y: 0, width: 32, height: 32))
        rightView?.addSubview(errorImage)
        rightViewMode = .always
    }
}

次のことを行います。

  • サブクラス UITextField
  • サブクラス化されたテキストフィールド内にinvalidateメソッドを記述します
  • invalidateメソッドで、UIView 画像より大きいサイズを作成します
  • ビュー内に画像を配置します
  • ビューを割り当てる UITextField.rightView

2

ここに1つの解決策があります:

 UIView *paddingTxtfieldView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 42)]; // what ever you want 
 txtfield.leftView = paddingTxtfieldView;
 txtfield.leftViewMode = UITextFieldViewModeAlways;

1

カスタムUITextFieldクラスを作成し、UITextFieldの代わりにそのクラスを使用します。オーバーライド-(CGRect)textRectForBounds:(CGRect)boundsで必要な四角形を設定します

- (CGRect)textRectForBounds:(CGRect)bounds{
     CGRect textRect = [super textRectForBounds:bounds];
     textRect.origin.x += 10;
     textRect.size.width -= 10;
     return textRect;
}

1

以下の例は、たまたまアイコンである左側のビューに水平方向のパディングを追加するためのものUIViewです。テキストフィールドの左側のビューとして使用したいものに同様の方法でパディングを追加できます。

UITextFieldサブクラス内:

static CGFloat const kLeftViewHorizontalPadding = 10.0f;

@implementation TextFieldWithLeftIcon
{
  UIImage *_image;
  UIImageView *_imageView;
}

- (instancetype)initWithFrame:(CGRect)frame image:(UIImage *)image
{
  self = [super initWithFrame:frame];
  if (self) {
    if (image) {
      _image = image;
      _imageView = [[UIImageView alloc] initWithImage:image];
      _imageView.contentMode = UIViewContentModeCenter;
      self.leftViewMode = UITextFieldViewModeAlways;
      self.leftView = _imageView;
    }
  }
  return self;
}

#pragma mark - Layout 

- (CGRect)leftViewRectForBounds:(CGRect)bounds
{
  CGFloat widthWithPadding = _image.size.width + kLeftViewHorizontalPadding * 2.0f;
  return CGRectMake(0, 0, widthWithPadding, CGRectGetHeight(bounds));
}

UITextFieldここではサブクラス化していますが、これが最もクリーンなアプローチだと思います。


1
- (CGRect)rightViewRectForBounds:(CGRect)bounds
{
    return CGRectMake(bounds.size.width - 40, 0, 40, bounds.size.height);
}

UITextFieldがに埋め込まれている場合、サブクラスを使用するUISearchBarようにに指示するにはどうすればよいですか?UISearchBarUITextField
crishoj

1

皆さんの回答に感謝します。驚いたことに、必要なパディングを提供しながら、テキストフィールドに正しいビューの画像を実際に配置した人はいませんでした。その後、AspectFillモードを使用することを考えたところ、奇跡が起こりました。将来の探求者のために、これが私が使ったものです:

UIImageView *emailRightView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 35, 35)];
emailRightView.contentMode = UIViewContentModeScaleAspectFill;
emailRightView.image = [UIImage imageNamed:@"icon_email.png"];
emailTextfield.rightViewMode = UITextFieldViewModeAlways;
emailTextfield.rightView = emailRightView;

私のimageviewのフレームの35は、私のemailTextfieldの高さを表しています。自由に調整してください。


1

私自身もこの問題を抱えていましたが、最も簡単な解決策は、画像を変更して、画像の両側にパディングを追加することです!

私はpng画像を変更して10ピクセルの透明なパディングを追加しましたが、それはうまく機能し、コーディングはまったくありません!


1

leftViewとしてUIImageViewを使用している場合は、次のコードを使用する必要があります。

注意:viewWillAppearまたはviewDidAppearの内部では使用しないでください

-(UIView*)paddingViewWithImage:(UIImageView*)imageView andPadding:(float)padding
{
    float height = CGRectGetHeight(imageView.frame);
    float width =  CGRectGetWidth(imageView.frame) + padding;

    UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)];

    [paddingView addSubview:imageView];

    return paddingView;
}

1

以下に示すように、ViewControllerクラスにカスタムメソッドを作成しました。

- (void) modifyTextField:(UITextField *)textField
{
    // Prepare the imageView with the required image
    uint padding = 10;//padding for iOS7
    UIImageView * iconImageView = [[UIImageView alloc] initWithImage:iconImage];    
    iconImageView.frame = CGRectMake(0 + padding, 0, 16, 16);

    // Set the imageView to the left of the given text field.
    textField.leftView = iconImageView;
    textField.leftViewMode = UITextFieldViewModeAlways;
}

これで(viewDidLoadmethod)内でそのメソッドを呼び出して、そのいずれかにmy TextFieldsを送信し、右と左の両方にパディングを追加し、次のように1行のコードを記述するだけでテキストと背景色を与えることができます。

[self modifyTextField:self.firstNameTxtFld];

これはiOS 7で完全に機能しました。これがiOS 8と9でも動作することを願っています!

ビューを追加しすぎると、ロードするオブジェクトが少し重くなる可能性があることを知っています。しかし、他のソリューションの難しさを気にしたとき、私はこの方法に偏りがあり、この方法を使用することでより柔軟になりました。;)

この回答が他の誰かへの別の解決策を理解するのに役立つか、または役立つことを願っています。

乾杯!


1

これは私が探しているように私のために働きます:

func addImageViewInsideMyTextField() {
    let someView = UIView(frame: CGRect(x: 0, y: 0, width: 40, height: 24))
    let imageView = UIImageView(image: UIImage(named: "accountImage"))
    imageView.frame = CGRect(x: 16, y: 0, width: 24, height: 24)
    imageView.contentMode = .scaleAspectFit
    someView.addSubview(imageView)

    self.myTextField.leftView = someView
    self.myTextField.leftViewMode = .always
}

1

iOS 13とXcode 11以降、これが私たちにとって有効な唯一のソリューションです。

// Init of custom UITextField
override init(frame: CGRect) {
    super.init(frame: frame)

    if let size = myButton.imageView?.image?.size {
        myButton.frame = CGRect(x:0, y: 0, width: size.width, height: size.height)

        let padding: CGFloat = 5
        let container = UIView(frame: CGRect(x:0, y: 0, width: size.width + padding, height: size.height))
        container.addSubview(myButton)

        myButton.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            myButton.topAnchor.constraint(equalTo: container.topAnchor),
            myButton.leftAnchor.constraint(equalTo: container.leftAnchor),
            myButton.bottomAnchor.constraint(equalTo: container.bottomAnchor),
            myButton.rightAnchor.constraint(equalTo: container.rightAnchor, constant: -padding),
        ])

        textField.rightViewMode = .always
        textField.rightView = container
    }
}

上記の答えは私にはうまくいきません、これはうまくいきます
マークディランBメルカド

1

// UITextFieldのRightviewを設定し、swift 4.2TxtPass.rightViewMode = UITextField.ViewMode.always let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 18, height: 18)) imageView.contentMode = UIView.ContentMode.scaleAspectFit let image = UIImage(named: "hidepass") imageView.image = image let rightView = UIView(frame: CGRect(x: 0, y: 0, width: 28, height: 18)) rightView.addSubview(imageView) rightView.contentMode = UIView.ContentMode.left TxtPass.rightView = rightView


0

1つのトリック:UIImageViewを含むUIViewをrightViewとしてUITextFieldに追加します。このUIViewはサイズを大きくする必要があります。UIImageViewをその左側に配置してください。したがって、右からスペースのパディングがあります。

// Add a UIImageView to UIView and now this UIView to UITextField - txtFieldDate
UIView *viewRightIntxtFieldDate = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, 30)]; 
// (Height of UITextField is 30px so height of viewRightIntxtFieldDate = 30px)
UIImageView *imgViewCalendar = [[UIImageView alloc] initWithFrame:CGRectMake(0, 10, 10, 10)];
[imgViewCalendar setImage:[UIImage imageNamed:@"calendar_icon.png"]];
[viewRightIntxtFieldDate addSubview:imgViewCalendar];
txtFieldDate.rightViewMode = UITextFieldViewModeAlways;
txtFieldDate.rightView = viewRightIntxtFieldDate;

0

最も簡単な方法は、TextfieldをCustomではなくRoundRectに変更して、マジックを確認することです。:)


0

Swift2の場合、私は

...
        self.mSearchTextField.leftViewMode = UITextFieldViewMode.Always
        let searchImg = UIImageView(image: UIImage(named: "search.png"))
        let size = self.mSearchTextField.frame.height
        searchImg.frame = CGRectMake(0, 0, size,size)
        searchImg.contentMode = UIViewContentMode.ScaleAspectFit
        self.mSearchTextField.leftView = searchImg
...

0
...
textField.rightView = UIImageView(image: ...)
textField.rightView?.contentMode = .top
textField.rightView?.bounds.size.height += 10
textField.rightViewMode = .always
...

0

シンプルなアプローチ:

textField.rightViewMode = .always
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 25, height: 15))
textField.contentMode = .scaleAspectFit
imageView = UIImage(named: "imageName")
textField.rightView = imageView

注:水平方向のパディングを可能にするには、高さを幅より小さくする必要があります。


0

私はこれが古い投稿であることに気づき、この答えは私のユースケースに少し特有ですが、他の人が同様の解決策を求めている場合に備えて投稿しました。UITextFieldのleftViewまたはrightViewを移動したいのですが、画像を配置せず、ハードコードされた定数を使用しません。

私のUIでは、テキストフィールドのクリアボタンを非表示にし、クリアボタンが配置されていた場所にUIActivityIndi​​catorViewを表示するように求めています。

スピナーをに追加しましたがrightView、そのまま(iOS 13の場合)、20ピクセル右にシフトしclearButtonます。clearButtonとrightViewの位置はAppleによっていつでも変更される可能性があるため、私はマジックナンバーを使用したくありません。UIの設計意図は「クリアボタンがある場所のスピナー」であるため、私の解決策はUITextFieldをサブクラス化してオーバーライドすることrightViewRect(forBounds)でした。

override func rightViewRect(forBounds bounds: CGRect) -> CGRect {

    // Use clearButton's rectangle
    return self.clearButtonRect(forBounds: bounds)
}

以下は実際の例です(sans Storyboard):

//------------------------------------------------------------------------------
class myCustomTextField: UITextField {

    override func rightViewRect(forBounds bounds: CGRect) -> CGRect {

        // Use clearButton rectangle
        return self.clearButtonRect(forBounds: bounds)
    }
}

//------------------------------------------------------------------------------
class myViewController: UIViewController {

    var activityView: UIActivityIndicatorView = {
        let activity = UIActivityIndicatorView()
        activity.startAnimating()
        return activity
    }()

    @IBOutlet weak var searchTextField: myCustomTextField!

    //------------------------------------------------------------------------------
    // MARK: - Lifecycle
    //------------------------------------------------------------------------------
    override func viewDidLoad() {

        super.viewDidLoad()

        searchTextField.rightView = activityView
        searchTextField.rightViewMode = .never // Hide spinner
        searchTextField.clearButtonMode = .never // Hide clear button

        setupUIForTextEntry()
    }

    // ...
    // More code to switch between user text entry and "search progress" 
    // by calling setupUI... functions below
    // ...

    //------------------------------------------------------------------------------
    // MARK: - UI
    //------------------------------------------------------------------------------
    func setupUIForTextEntry() {

        // Hide spinner
        searchTextField.rightViewMode = .never

        // Show clear button
        searchTextField.clearButtonMode = .whileEditing
        searchTextField.becomeFirstResponder()
    }

    //------------------------------------------------------------------------------
    func setupUIForSearching() {

        // Show spinner
        searchTextField.rightViewMode = .always

        // Hide clear button
        searchTextField.clearButtonMode = .never
        searchTextField.resignFirstResponder()
    }

    //------------------------------------------------------------------------------

}

//------------------------------------------------------------------------------
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.