【问题标题】:Adding UITextFields one below another on button click in a UIScrollView在 UIScrollView 中单击按钮时将 UITextFields 添加到另一个下方
【发布时间】:2020-03-27 03:04:10
【问题描述】:

我有一个带有多个组件的 UIScrollView。我需要以这样一种方式添加 UITextfields,即在点击按钮时,文本字段将在另一个垂直下方添加一个。例如,如果按钮被点击 100 次。应该添加 100 个 uitextfields,此 uitextfield 下方也有组件,因此 uiscrollview 应相应调整其高度。

【问题讨论】:

  • 你试过什么?这一个水平低于另一个是否清晰?????
  • 使用UIStackView 并将每个文本字段添加为排列的子视图。堆栈视图会自动展开,它的约束会自动处理滚动视图内容的大小。
  • sh_khan .sorry 但它是垂直的

标签: ios objective-c uiscrollview uitextfield


【解决方案1】:

注意:使用填充/获取示例代码编辑的原始答案。

这是一个简单的例子。

UIStackView(垂直轴)添加到滚动视图。每次点击按钮,创建一个新的UITextField 并将其添加为堆栈视图的arrangedSubview

堆栈视图会自动垂直扩展,其约束会自动处理滚动视图的内容大小。

  • 新字段将使用占位符字符串进行初始化。
  • 点击“填充字段”按钮会将每个字段的文本设置为示例数据数组中的值。
  • 点击“获取文本”按钮会将每个字段的文本记录到调试控制台。

ViewController.h

//
//  ViewController.h
//
//  Created by Don Mag on 12/3/19.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@end

ViewController.m

//
//  ViewController.m
//
//  Created by Don Mag on 12/3/19.
//

#import "ViewController.h"

@interface ViewController ()

@property (strong, nonatomic) UIButton *theButton;
@property (strong, nonatomic) UIButton *fillButton;
@property (strong, nonatomic) UIButton *getButton;

@property (strong, nonatomic) UIScrollView *theScrollView;
@property (strong, nonatomic) UIStackView *theStackView;

@property (strong, nonatomic) NSMutableArray *theData;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self.view setBackgroundColor:[UIColor whiteColor]];

    // instantiate buttons, scrollView and stackViews

    // adds a new text field
    _theButton = [UIButton new];
    [_theButton setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_theButton setTitle:@"Add Field" forState:UIControlStateNormal];
    [_theButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateHighlighted];
    [_theButton setBackgroundColor:[UIColor redColor]];

    // fills the fields with sample data
    _fillButton = [UIButton new];
    [_fillButton setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_fillButton setTitle:@"Fill Fields" forState:UIControlStateNormal];
    [_fillButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateHighlighted];
    [_fillButton setBackgroundColor:[UIColor redColor]];

    // logs the text of each field to debug console
    _getButton = [UIButton new];
    [_getButton setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_getButton setTitle:@"Get Text" forState:UIControlStateNormal];
    [_getButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateHighlighted];
    [_getButton setBackgroundColor:[UIColor redColor]];

    // scroll view will hold the stack view filled with fields
    _theScrollView = [UIScrollView new];
    [_theScrollView setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_theScrollView setBackgroundColor:[UIColor cyanColor]];

    // stack view to hold the new fields
    _theStackView = [UIStackView new];
    [_theStackView setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_theStackView setAxis:UILayoutConstraintAxisVertical];
    [_theStackView setSpacing:8.0];

    // stack view for buttons
    UIStackView *buttonsStackView = [UIStackView new];
    [buttonsStackView setTranslatesAutoresizingMaskIntoConstraints:NO];
    [buttonsStackView setAxis:UILayoutConstraintAxisHorizontal];
    [buttonsStackView setSpacing:8.0];

    // add buttons to the buttons stack view
    [buttonsStackView addArrangedSubview:_theButton];
    [buttonsStackView addArrangedSubview:_fillButton];
    [buttonsStackView addArrangedSubview:_getButton];

    // add button stack view and scrollView to view
    [self.view addSubview:buttonsStackView];
    [self.view addSubview:_theScrollView];

    // add stackView to scrollView
    [_theScrollView addSubview:_theStackView];

    UILayoutGuide *g = self.view.safeAreaLayoutGuide;
    UILayoutGuide *sg = _theScrollView.contentLayoutGuide;

    [NSLayoutConstraint activateConstraints:@[

        // constrain buttons 20-pts from top, centered horizontally
        [buttonsStackView.topAnchor constraintEqualToAnchor:g.topAnchor constant:20.0],
        [buttonsStackView.centerXAnchor constraintEqualToAnchor:g.centerXAnchor constant:0.0],

        // constrai scrollView 20-pts below button, 20-pts on each side and bottom
        [_theScrollView.topAnchor constraintEqualToAnchor:_theButton.bottomAnchor constant:20.0],
        [_theScrollView.bottomAnchor constraintEqualToAnchor:g.bottomAnchor constant:-20.0],
        [_theScrollView.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:20.0],
        [_theScrollView.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:-20.0],

        // constrain stackView 8-pts on each side
        [_theStackView.topAnchor constraintEqualToAnchor:sg.topAnchor constant:8.0],
        [_theStackView.bottomAnchor constraintEqualToAnchor:sg.bottomAnchor constant:-8.0],
        [_theStackView.leadingAnchor constraintEqualToAnchor:sg.leadingAnchor constant:8.0],
        [_theStackView.trailingAnchor constraintEqualToAnchor:sg.trailingAnchor constant:-8.0],

        // constrain stackView width to scrollView frame width minus 16-pts (for 8-pts on each side)
        [_theStackView.widthAnchor constraintEqualToAnchor:_theScrollView.frameLayoutGuide.widthAnchor constant:-16.0],

        ]
    ];

    [_theButton addTarget:self action:@selector(addTextField:) forControlEvents:UIControlEventTouchUpInside];
    [_fillButton addTarget:self action:@selector(fillFields:) forControlEvents:UIControlEventTouchUpInside];
    [_getButton addTarget:self action:@selector(getFields:) forControlEvents:UIControlEventTouchUpInside];

    // sample data to fill the fields with
    NSString *s = @"This is just random text that will be used to fill the text fields when the fill button is tapped";
    _theData = [s componentsSeparatedByString:@" "].mutableCopy;

}

- (void)fillFields:(id)sender {
    // set the text of each field based on the data array
    NSInteger idx = 0;
    for (UITextField *f in _theStackView.arrangedSubviews) {
        // make sure we don't have more fields than our data array
        if (idx < _theData.count) {
            f.text = _theData[idx++];
        }
    }
}

- (void)getFields:(id)sender {
    // log the text of each field to debug cosole
    for (UITextField *f in _theStackView.arrangedSubviews) {
        NSLog(@"%@", f.text);
    }
}

- (void)addTextField:(id)sender {

    // instantiate a new text field
    UITextField *f = [UITextField new];
    [f setBorderStyle:UITextBorderStyleRoundedRect];
    [f setBackgroundColor:[UIColor whiteColor]];

    // add it to the stack view
    [_theStackView addArrangedSubview:f];

    // set its placeholder text (just to make it easy to see what we're doing)
    [f setPlaceholder:[NSString stringWithFormat:@"Text Field %ld", _theStackView.arrangedSubviews.count]];

    dispatch_async(dispatch_get_main_queue(), ^{

        // auto-scroll to bottom so newly added text field is visible
        CGRect r = CGRectMake(0.0, self.theScrollView.contentSize.height - 1.0, 1.0, 1.0);
        [self.theScrollView scrollRectToVisible:r animated:YES];

    });

}

@end

点击 3 次后的结果:

在足够多的点击后需要滚动:

点击“填写字段”按钮后:

【讨论】:

  • DonMag - 非常感谢你,需要你的更多帮助。如何获取每个文本字段的参考?我想在每个文本字段中添加数据并通过 api 调用发送它们。
  • 好吧,您可以在创建它们时将它们添加到数组中......或者,如果这些是堆栈视图中的唯一元素,请通过 _theStackView.arrangedSubviews 将它们作为数组引用。
  • 我需要在每个文本字段中填写数据。我尝试使用数组,但 textfield.text 始终为零,因为它在每次点击时都会创建新的文本字段。所以无法维护数组。跨度>
  • @DonMag-非常感谢。你是个救世主。
  • @roshan.k - 如果这回答了您的问题,请务必将其标记为“已接受”(为了其他可能遇到它的用户的利益)。
猜你喜欢
  • 1970-01-01
  • 2019-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-22
  • 1970-01-01
相关资源
最近更新 更多