I have been building this chat and I am stuck in something that I can't figure out yet.
我一直在做这个聊天,我被困在一个我还不知道的事情上。
I have been unsuccessfully trying to align the same view left or right according to the scenario but I haven't gotten the desired result yet.
我一直试图根据场景将相同的视图向左或向右对齐,但没有成功,但我还没有得到预期的结果。
Basically, I built the cell in interface builder and pinned to the left and made its width and height variable according to the contents of the labels inside.
基本上,我在interface builder中构建了单元格,并将其固定在左侧,并根据内部标签的内容来设置其宽度和高度变量。
What I have been trying to do is reusing the same cell and align to the right when the I am the one sending the message (yellow) because by default it will be aligned to the left when others send me a message (gray) see the following image for illustration:
我一直在做的是重复使用相同的单元格,当I是发送消息的那个人(黄色)时向右对齐,因为默认情况下,当其他人向我发送消息(灰色)时,它将向左对齐,请参见下面的图片来说明:
What I want is:
我想要的是:
others messages--------
其他消息- - - - - - - - - -
--------------my message
- - - - - - - - - - - - - - - -我的信息
To accomplish this, and under TroyT's suggestion, I activated and deactivated the leading/trailing constraints according to my needs.
为了实现这一目标,在TroyT的建议下,我根据自己的需要激活并停用了前导/后导限制。
So what I did was.
我所做的是。
On my UITableViewCell Class, I created two @IBoulets for my two constraints like so:
在我的UITableViewCell类中,我为我的两个约束创建了两个@ iboulet:
@IBOutlet var bubbleViewLeading: NSLayoutConstraint!
@IBOutlet var bubbleViewLeading:NSLayoutConstraint !
@IBOutlet var bubbleViewTrailing: NSLayoutConstraint!
@IBOutlet var bubbleViewTrailing:NSLayoutConstraint !
Later, in my tableViewController on the method cellForRowAtIndexPAth , I activate or deactivate one of the constraints according to my needs doing the following.
后来,在我的tableViewController中,在方法cellForRowAtIndexPAth中,我根据需要执行以下操作,激活或停用其中一个约束。
cell.bubbleViewTrailing.active = true cell.bubbleViewLeading.active = false
cell.bubbleViewTrailing。= true cell.bubbleViewLeading活跃。积极= false
or the opposite
或者是相反的
cell.bubbleViewTrailing.active = false cell.bubbleViewLeading.active = true
cell.bubbleViewTrailing。= false cell.bubbleViewLeading活跃。积极= true
where the constraint set to "True" is set to 0. As I mentioned before, this work well for all cells except the first one.
其中,将约束设置为“True”设置为0。正如我之前提到的,这对除第一个单元外的所有单元都适用。
I tried several things like:
我尝试了几件事:
However, none of these methods affect the constraints on the first cell but I can easily change everything else like the cell background or the text alignment in a label within the cell. It just the constraint that will not change for that first time that I use the cell. Even when I scroll down past the boundaries of the screen to "force" the cell reuse, the first cell becomes fixed:
但是,这些方法都不会影响第一个单元格上的约束,但是我可以很容易地更改单元格背景或单元格内标签中的文本对齐。它只是第一次使用单元格时不会改变的约束。甚至当我向下滚动屏幕边界以“强制”单元格重用时,第一个单元格也变得固定:
I have been trying to figure this one out for days with little success. Hence, I decided to put a bounty on this question.
我一直试着把这一天弄清楚,但收效甚微。因此,我决定悬赏这个问题。
1
What you explain makes little sense to me, but if it is happening only with the first row, then I would try forcing the layout to redraw by doing:
你的解释对我来说没有什么意义,但是如果它只发生在第一行,那么我将尝试通过以下操作来迫使布局重新绘制:
cell.setNeedsLayout() cell.layoutIfNeeded()
cell.layoutIfNeeded cell.setNeedsLayout()()
from the cellForRowAtIndexPath
从cellForRowAtIndexPath
BTW, I think a better approach would be to register 2 different cells, and create them both in IB. This approach will keep your code shorter and will allow you to modify not only the trailing/leading but also colors, fonts or whatever you need. You give them 2 different IDs, but keep the same implementation class, and you just deque the one you need on your cellForRowAtIndexPath
.
顺便说一句,我认为更好的方法是注册两个不同的单元格,并在IB中创建它们。这种方法将使您的代码更短,不仅允许您修改尾随/引导,还可以修改颜色、字体或任何您需要的东西。您给它们两个不同的id,但是保持相同的实现类,并且您只需要在cellForRowAtIndexPath上做一个您需要的。
Keeping a different cell per style is the standard way to do these things with IB.
每个样式都保留一个不同的单元格是处理IB的标准方法。
1
removeConstraint:
is deprecated, in favor of using the active
property instead (or NSLayoutConstraint
's deactivateConstraints:
). While removeConstraint:
still usually works, combining that with setting your constraints' active
property makes this worse. Either use all activate and deactivate (preferred) or use add and remove.
removeConstraint:已弃用,改为使用活动属性(或NSLayoutConstraint的反激活约束:)。虽然removeConstraint:仍然正常工作,但是结合设置约束的活动属性会使情况变得更糟。要么使用所有激活和停用(首选),要么使用添加和删除。
So instead of cell.removeConstraint:
, use this:
而不是细胞。removeConstraint:用这个:
cell.bubbleViewTrailing.active = false
One thing I may note is that your leading and trailing is reversed. Leading is on the left and trailing is on the right, except for right-to-left localization.
有一件事我可能会注意到,你的领先和落后是颠倒的。前导在左边,尾在右边,除了从右到左定位。
0
Here is the Custom ChatMessageCell
that I have implemented for you in which I have applied programmatically constrains using the KVConstraintExtensionsMaster library to apply constraints that I have implemented.
下面是我为您实现的自定义ChatMessageCell,其中我使用kvconstraintextensmaster库以编程方式约束应用我实现的约束。
I have update the leading & trailing constraints Constant value instead of activate/deactivate constraint or remove/add constraint.
我更新了引导和跟踪约束常量值,而不是激活/停用约束或删除/添加约束。
I hope this may help you.
我希望这能对你有所帮助。
Put below code in ChatMessageCell.h
header file
在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
Put below code in ChatMessageCell.m
file
在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
Put the below code in the viewDidLoad method ofyour ViewController is:
在视图控制器的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;
Now implement UITableView DataSource in your 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;
}