以编程方式更改视图以左对齐或右对齐
Changing a view programmatically to align left or right
我一直在建立这个聊天室,但我被困在一些我还无法弄清楚的事情上。
我一直试图根据场景向左或向右对齐相同的视图,但没有成功,但我还没有得到想要的结果。
基本上,我在界面生成器中构建单元格并将其固定在左侧,并根据内部标签的内容使其宽度和高度可变。
我一直在尝试做的是重复使用同一个单元格并在我发送消息(黄色)时向右对齐,因为默认情况下当其他人向我发送消息时它会向左对齐(灰色)参见下图:
我想要的是:
其他留言--------
----------------我的留言
为此,在 TroyT 的建议下,我根据需要激活和停用了 leading/trailing 约束。
所以我所做的是。
在我的 UITableViewCell Class 上,我为我的两个约束创建了两个 @IBoulet,如下所示:
@IBOutlet var bubbleViewLeading: NSLayoutConstraint!
@IBOutlet var bubbleViewTrailing: NSLayoutConstraint!
稍后,在我的 tableViewController 方法 cellForRowAtIndexPAth 中,我根据需要执行以下操作来激活或停用其中一个约束。
cell.bubbleViewTrailing.active = true
cell.bubbleViewLeading.active = false
或相反
cell.bubbleViewTrailing.active = false
cell.bubbleViewLeading.active = true
其中设置为 "True" 的约束设置为 0。正如我之前提到的,这适用于除第一个单元格之外的所有单元格。
- 这部分有效,因为出于某种原因它不会影响第一行并且两个约束都保持激活状态,因此该行会像这样在 tableview 的宽度上拉伸:.
我尝试了几种方法,例如:
- 使用我的 UITableViewCell class 中的 init 方法来更改约束
- 在我的 UITableViewCell 中更改来自 awakeFromNib 方法的约束
- 使用 Storyboard 左侧第三个选项卡上的 "User Defined Runtime Attributes",添加一个名为 "active" 的键路径,将类型设置为 Bool,并将值设置为 false。
- 当我select故事板中的约束
时,在属性检查器中取消勾选"installed"
但是,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;
}
我一直在建立这个聊天室,但我被困在一些我还无法弄清楚的事情上。
我一直试图根据场景向左或向右对齐相同的视图,但没有成功,但我还没有得到想要的结果。
基本上,我在界面生成器中构建单元格并将其固定在左侧,并根据内部标签的内容使其宽度和高度可变。
我一直在尝试做的是重复使用同一个单元格并在我发送消息(黄色)时向右对齐,因为默认情况下当其他人向我发送消息时它会向左对齐(灰色)参见下图:
我想要的是:
其他留言--------
----------------我的留言
为此,在 TroyT 的建议下,我根据需要激活和停用了 leading/trailing 约束。
所以我所做的是。
在我的 UITableViewCell Class 上,我为我的两个约束创建了两个 @IBoulet,如下所示:
@IBOutlet var bubbleViewLeading: NSLayoutConstraint!
@IBOutlet var bubbleViewTrailing: NSLayoutConstraint!
稍后,在我的 tableViewController 方法 cellForRowAtIndexPAth 中,我根据需要执行以下操作来激活或停用其中一个约束。
cell.bubbleViewTrailing.active = true
cell.bubbleViewLeading.active = false
或相反
cell.bubbleViewTrailing.active = false
cell.bubbleViewLeading.active = true
其中设置为 "True" 的约束设置为 0。正如我之前提到的,这适用于除第一个单元格之外的所有单元格。
- 这部分有效,因为出于某种原因它不会影响第一行并且两个约束都保持激活状态,因此该行会像这样在 tableview 的宽度上拉伸:.
我尝试了几种方法,例如:
- 使用我的 UITableViewCell class 中的 init 方法来更改约束
- 在我的 UITableViewCell 中更改来自 awakeFromNib 方法的约束
- 使用 Storyboard 左侧第三个选项卡上的 "User Defined Runtime Attributes",添加一个名为 "active" 的键路径,将类型设置为 Bool,并将值设置为 false。
- 当我select故事板中的约束 时,在属性检查器中取消勾选"installed"
但是,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
.
为每种样式保留不同的单元格是使用 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;
}