Swift 中带有下拉菜单的自定义 UITableViewCell

Custom UITableViewCell with drop-down in Swift

我想用 XIB 实现自定义 UITableViewCellHere是图纸。 主视图 shows/hides 附加视图右侧的按钮。我有两个问题:

  1. 如何隐藏附加视图?我认为一种可能性是将附加 UIView 框架中的高度设置为零。有没有更好的选择?

  2. 附加视图中的按钮(在本例中为 1-5)应该动态显示。有两组数据:一组用于左侧(按钮 1-3),另一组用于右侧(按钮 4-5)。左边按钮的高度是固定的,比方说每个 70px。应调整右侧按钮的高度,使右侧按钮的总高度与左侧总高度相同。考虑到这些规则,如何动态添加按钮?

按钮将在运行时添加。例如有两个数组:

var leftButtons:[String] = ["button1label", “button2label“, "button3label"]

var rightButtons:[String] = ["button4label", "button5label"]

假设我稍后在运行期间"button6label"添加到leftButtonsleftView/rightView 的大小以及这些视图中按钮的大小应该进行调整。同样,左侧尺寸上每个按钮的高度是固定的。

您可以使用具有自动高度的 UITableViewCells 来执行此操作。 这允许您使用约束来确定单元格的高度。

要使其正常工作:

  • 添加以下行以打开自动高度:

    tableView.rowHeight = UITableViewAutomaticDimension tableView.estimatedRowHeight = 160.0 // 近似的单元格高度。

  • 使用约束使单元格的内容向外推以便内容决定单元格的高度。
  • 在代码中使用 IBOutlet 向附加视图添加高度限制。将此约束的constant属性设置为0,并将附加视图的.hidden属性设置为true以隐藏附加视图。
  • 为了更好 opening/closing,更改 UIView 动画块中的约束 constant 属性。

首先,您应该在自定义 UITableViewCell 上添加 ContainerView 视图,现在在 ContainerView - leading , trailing, top & bottom to superView 上添加约束,所有约束都为 priority 999

现在您应该在 ContainerView 上添加两个视图,一个是 mainView,另一个是 additionView

并在 mainView 上添加约束 - 导致 superView,顶部到 superView,尾随 superView 和高度约束(比如 70)。

现在在 mainView 中添加 textfieldshow/hide button 并在 textFieldshow/hide button 上应用约束。

textField 约束 - leading to superViewtop to superViewbottom to superViewHorizontal spacing between textField & show/hide button.

show/hide 按钮约束 - top to superViewbottom to superViewtrailing to superView 和宽度约束。

此处mainView配置正确。所以现在让我们配置 additionView

您应该在 additionView 中添加两个新视图,一个是 leftView,另一个是 leftView & rightView 上的 rightView & add constraints

leftView 约束 - leading to superView, top to superView, bottom to superView, Horizontal spacing between leftView & rightView, equal width and width constraints of leftView to rightView.

rightView 约束 - trailing to superView, top to superView&bottom to superView 这里是你的 Interface Builder Designing completed 所以现在我们需要在运行时管理左右视图上的按钮。为此,您必须制作一个名为 VerticalContainerView 的客户类,它将管理按钮的垂直分布。

我使用 KVConstraintExtensionsMaster 库创建了 VerticalContainerView 以应用我已实现的约束。

将以下代码放入 VerticalContainerView.h 头文件

#import <UIKit/UIKit.h>

@interface VerticalContainerView : UIView
-(void)configureButtonsbyNames:(NSArray<__kindof NSString *>*)names isDistribuated:(BOOL)isDistributed;
@end

将以下代码放入 VerticalContainerView.m 文件

#import "VerticalContainerView.h"
#import "KVConstraintExtensionsMaster.h"

@implementation VerticalContainerView

-(void)configureButtonsbyNames:(NSArray<__kindof NSString *>*)names isDistribuated:(BOOL)isDistributed
{
    /* Just Two steps to Apply\Add constraints by programatically */
    /* Step 1 create & configure the view hierarchy for constraint first. */
    /* Step 2 Apply the constraints */

    CGFloat space  = 0.0;
    CGFloat height = 70.0;

    UIButton *previousContentButton = nil;
    NSInteger count  = names.count;

    for (NSInteger i = 0; i < count; i++)
    {
        UIButton *contentButton = [UIButton prepareNewViewForAutoLayout];
        if (i&1) {
            [contentButton setBackgroundColor:[UIColor greenColor]];
        }else{
            [contentButton setBackgroundColor:[UIColor purpleColor]];
        }

        [contentButton setTag:i];
        [contentButton setTitle:names[i] forState:UIControlStateNormal];
        [self addSubview:contentButton];

        [contentButton applyLeadingAndTrailingPinConstraintToSuperviewWithPadding:space];

        if (!isDistributed) {
            [contentButton applyHeightConstraint:height];
        }

        if (i == 0) // for first
        {
            [contentButton applyTopPinConstraintToSuperviewWithPadding:space];
        }
        else if (i == count-1) // for last
        {
            if (isDistributed) {
                [previousContentButton applyConstraintFromSiblingViewAttribute:NSLayoutAttributeHeight toAttribute:NSLayoutAttributeHeight ofView:contentButton spacing:space];
            }

            [previousContentButton applyConstraintFromSiblingViewAttribute:NSLayoutAttributeBottom toAttribute:NSLayoutAttributeTop ofView:contentButton spacing:space];
            [contentButton applyBottomPinConstraintToSuperviewWithPadding:space];
        }
        else
        {
            if (isDistributed) {
                [previousContentButton applyConstraintFromSiblingViewAttribute:NSLayoutAttributeHeight toAttribute:NSLayoutAttributeHeight ofView:contentButton spacing:space];
            }

            [previousContentButton applyConstraintFromSiblingViewAttribute:NSLayoutAttributeBottom toAttribute:NSLayoutAttributeTop ofView:contentButton spacing:space];
        }

        previousContentButton = contentButton;
    }

}

@end

现在创建一个名为 CustomCell 的自定义单元格并将下面的代码放入 CustomCell.h 头文件

#import "VerticalContainerView.h"

@interface CustomCell : UITableViewCell
@property (weak, nonatomic) IBOutlet VerticalContainerView *leftVerticalContainerView;
@property (weak, nonatomic) IBOutlet VerticalContainerView *rightVerticalContainerView;
@end

将以下代码放入 CustomCell.m 文件。

#import "CustomCell.h"

@implementation CustomCell

-(void)prepareForReuse
{
    // here you have to remove the all the buttons from left and right veiw becuase
    // Every cell can have distinct number buttons on left and right view.

    for (UIView *subView in self.leftVerticalContainerView.subviews) {
        [subView removeFromSuperview];
    }
    for (UIView *subView in self.leftVerticalContainerView.subviews) {
        [subView removeFromSuperview];
    }

    [super prepareForReuse];

}

@end

现在我们的 CustomCell 在 Interface Builder

Identity inspector editor 的帮助下更改 UITableViewCell Class

也在Interface Builder

Identity inspector editor的帮助下,我们的VerticalContainerView改变了left and right View Class

现在为 leftVerticalContainerView & rightVerticalContainerView

连接我们的 CusromCell 的 IBOutlet

将下面的代码放在你的 ViewController 的 viewDidLoad 方法中是:

tableView.rowHeight = UITableViewAutomaticDimension;
/* any estimated height but must be more than 2, but it should be more estimated */
tableView.estimatedRowHeight = 210.0;
tableView.delegate = self;
tableView.dataSource = self;

// if you created cell from `.xib` is called CustomCell.xib,then you have to register that cell with table.
//    UINib *nib = [UINib nibWithNibName:@"CustomCell" bundle:nil];
//    [tableView registerNib:nib forCellReuseIdentifier:@"YouCellIdentifier"];

现在在您的 ViewController

中实施 UITableView DataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section{
    return 10;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath{

    static NSString *cellIdentifier = @"CustomCell";
    CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    if (indexPath.row%2 == 0) {
        // this is fixed height constraints
        [cell.leftVerticalContainerView configureButtonsbyNames:@[@"button1",@"button2",@"button3"] isDistributed:NO];
        // this is distributed height constraints according to left view
        [cell.rightVerticalContainerView configureButtonsbyNames:@[@"button4",@"button5"] isDistributed:YES];
    }
    else{
        // this is fixed height constraints
        [cell.leftVerticalContainerView configureButtonsbyNames:@[@"button1",@"button2",@"button3",@"button4",@"button5"] isDistributed:NO];

        // this is isDistribuated height constraints according to left view
        [cell.rightVerticalContainerView configureButtonsbyNames:@[@"button6",@"button7",@"button8"] isDistributed:YES];
    }

    return cell;
}