以编程方式更改视图以左对齐或右对齐

Changing a view programmatically to align left or right

我一直在建立这个聊天室,但我被困在一些我还无法弄清楚的事情上。

我一直试图根据场景向左或向右对齐相同的视图,但没有成功,但我还没有得到想要的结果。

基本上,我在界面生成器中构建单元格并将其固定在左侧,并根据内部标签的内容使其宽度和高度可变。

我一直在尝试做的是重复使用同一个单元格并在我发送消息(黄色)时向右对齐,因为默认情况下当其他人向我发送消息时它会向左对齐(灰色)参见下图:

我想要的是:

其他留言--------

----------------我的留言

为此,在 TroyT 的建议下,我根据需要激活和停用了 leading/trailing 约束。

所以我所做的是。

  1. 在我的 UITableViewCell Class 上,我为我的两个约束创建了两个 @IBoulet,如下所示:

    @IBOutlet var bubbleViewLeading: NSLayoutConstraint!

    @IBOutlet var bubbleViewTrailing: NSLayoutConstraint!

  2. 稍后,在我的 tableViewController 方法 cellForRowAtIndexPAth 中,我根据需要执行以下操作来激活或停用其中一个约束。

cell.bubbleViewTrailing.active = true cell.bubbleViewLeading.active = false

或相反

cell.bubbleViewTrailing.active = false cell.bubbleViewLeading.active = true

其中设置为 "True" 的约束设置为 0。正如我之前提到的,这适用于除第一个单元格之外的所有单元格。

  1. 这部分有效,因为出于某种原因它不会影响第一行并且两个约束都保持激活状态,因此该行会像这样在 tableview 的宽度上拉伸:.

我尝试了几种方法,例如:

但是,none 这些方法会影响第一个单元格的约束,但我可以轻松更改其他所有内容,例如单元格背景或单元格内标签中的文本对齐方式。这只是我第一次使用单元格时不会改变的约束。即使当我向下滚动到屏幕边界 "force" 单元格重用时,第一个单元格也会固定:

几天来我一直在努力解决这个问题,但收效甚微。因此,我决定悬赏这个问题。

removeConstraint: 已弃用,建议使用 active 属性(或 NSLayoutConstraint's deactivateConstraints:). While removeConstraint: still usually works, combining that with setting your constraints' active 属性 使情况变得更糟。要么使用全部激活和停用(首选),要么使用添加和删除。

所以不要使用 cell.removeConstraint:,而是使用:

cell.bubbleViewTrailing.active = false

我可能注意到的一件事是您的前导和尾随颠倒了。开头在左边,结尾在右边,除了从右到左的本地化。

你解释的内容对我来说意义不大,但如果它只发生在第一行,那么我会尝试通过执行以下操作强制重绘布局:

cell.setNeedsLayout() cell.layoutIfNeeded()

来自 cellForRowAtIndexPath

顺便说一句,我认为更好的方法是注册 2 个不同的单元格,然后在 IB 中创建它们。这种方法将使您的代码更短,并且不仅可以修改 trailing/leading,还可以修改颜色、字体或任何您需要的内容。你给了他们 2 个不同的 ID,但保持相同的实现 class,你只需要在你的 cellForRowAtIndexPath.

上 deque 你需要的那个

为每种样式保留不同的单元格是使用 IB 执行这些操作的标准方法。

这是我为您实现的自定义 ChatMessageCell,我在其中使用 KVConstraintExtensionsMaster 库以编程方式应用约束以应用我已实现的约束。

我更新了前导和尾随约束常量值,而不是 activate/deactivate 约束或 remove/add 约束。

希望对您有所帮助。

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

typedef NS_ENUM(NSUInteger, Type) {
    TypeSender,
    TypeReceiver,
};

@interface ChatMessageCell : UITableViewCell

@property (assign, nonatomic) Type cellType;
@property (strong, nonatomic) UIView *msgBackgroundView;
@property (strong, nonatomic) UILabel *messageLabel;

@end

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

#import "ChatMessageCell.h"
#import "KVConstraintExtensionsMaster.h"

@implementation ChatMessageCell

- (void)awakeFromNib {
    [super awakeFromNib];
    // Initialization code
}

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self createAndConfigureViewHierarchy];
    }    
    return self;
}

- (void)createAndConfigureViewHierarchy
{
    _msgBackgroundView = [UIView prepareNewViewForAutoLayout];
    [self.contentView addSubview:_msgBackgroundView];

    _msgBackgroundView.backgroundColor = [UIColor clearColor];
    [_msgBackgroundView.layer setCornerRadius:6.0];

    _labelMessage = [UILabel prepareNewViewForAutoLayout];
    [_labelMessage setLineBreakMode:NSLineBreakByTruncatingTail];
    [_labelMessage setNumberOfLines:0];
    [_labelMessage setTextAlignment:NSTextAlignmentLeft];
    [_labelMessage setTextColor:[UIColor whiteColor]];
    self.labelMessage.backgroundColor = [UIColor clearColor];

    [_msgBackgroundView addSubview:_labelMessage];

    [self applyConstraints];
}

-(void)applyConstraints
{
    // now applying the constraints by using KVConstraintExtensionsMaster library
    CGFloat padding = 8.0;

    // adding Top and Bottom contraints of _msgBackgroundView
    [_msgBackgroundView applyTopAndBottomPinConstraintToSuperviewWithPadding:padding];

    // adding leading and trailing contraints of _msgBackgroundView
    [_msgBackgroundView applyLeadingAndTrailingPinConstraintToSuperviewWithPadding:padding];

    // adding Top and Bottom contraints of _msgBackgroundView
    [_labelMessage applyTopAndBottomPinConstraintToSuperviewWithPadding:padding];

    // adding leading and trailing contraints of _msgBackgroundView
    [_labelMessage applyLeadingAndTrailingPinConstraintToSuperviewWithPadding:padding];

}

-(void)setCellType:(Type)cellType
{
    switch (cellType) {
        case TypeSender:
        {
            [_msgBackgroundView setBackgroundColor:[UIColor redColor]];
            [_labelMessage setTextAlignment:NSTextAlignmentRight];

            // this method will change the Leading Pin Constraint Constant value by 100.0
            [_msgBackgroundView applyLeadingPinConstraintToSuperviewWithPadding:100.0];

            // this method will increase the Leading Pin Constraint Constant value with proper ratio only iPad
            [_msgBackgroundView updateAppliedConstraintConstantValueForIpadByAttribute:NSLayoutAttributeLeading];
            break;
        }

        case TypeReceiver:
        {
            [_msgBackgroundView setBackgroundColor:[UIColor redColor]];
            [_labelMessage setTextAlignment:NSTextAlignmentLeft];

            // this method will change the Trailing Pin Constraint Constant value by 100.0
            [_msgBackgroundView applyTrailingPinConstraintToSuperviewWithPadding:100.0];

            // this method will increase the Leading Pin Constraint Constant value with proper ratio only iPad
            [_msgBackgroundView updateAppliedConstraintConstantValueForIpadByAttribute:NSLayoutAttributeTrailing];
            break;
        }
    }

    [self.contentView setNeedsLayout];
    [self.contentView updateModifyConstraints];
}

-(void)prepareForReuse
{
    // this method will change the Leading And Trailing Pin Constraints Constant value by 8.0
    [_msgBackgroundView applyLeadingAndTrailingPinConstraintToSuperviewWithPadding:8.0];
    [super prepareForReuse];
}

@end

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

[self.tableView registerClass:ChatMessageCell.class forCellReuseIdentifier:@"KVChatMessageCell"];
self.tableView.rowHeight = UITableViewAutomaticDimension;
/* any estimated height but must be more than 2 */
self.tableView.estimatedRowHeight = 44.0;

现在在您的 ViewController

中实现 UITableView 数据源
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section{
    return messages.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath{
    static NSString *cellIdentifier = @"KVChatMessageCell";

    ChatMessageCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    [cell.labelMessage setText:messages[indexPath.row]];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    if (indexPath.row%2 == 0) {
       // here all even cell are the sender type
        [cell setCellType:TypeSender];
    }
    else {
       // here all odd cell are the Receiver type
        [cell setCellType:TypeReceiver];
    }

    return cell;
}