Its possible change logic of collectionView: attributedTextForCellTopLabelAtIndexPath: delegate method for show date timestamp not by indexPath.item % 4 == 0? how like in SOMessaging day by day? or whatever?
this coding is for displaying timestamp.
- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView
layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.item % 3 == 0) {
return kJSQMessagesCollectionViewCellLabelHeightDefault;
}
return 0.0f;
}
Current existing logic is displaying same timestamp is duplicated as follow.
Because each JSQMessage
object has a date
property, you can simply compare the date of each message to the date of the previous message.
[thisMessageDate timeIntervalSinceDate:(NSDate *)previousMessageDate]
will give you the difference in seconds. If the difference is greater than, say, a minute (or whatever time interval you desire), then display a timestamp.
This is how I'm doing it:
- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath {
JSQMessage *message = [self.messages objectAtIndex:indexPath.item];
if (indexPath.item == 0) {
return [[JSQMessagesTimestampFormatter sharedFormatter] attributedTimestampForDate:message.date];
}
if (indexPath.item - 1 > 0) {
JSQMessage *previousMessage = [self.messages objectAtIndex:indexPath.item - 1];
if ([message.date timeIntervalSinceDate:previousMessage.date] / 60 > 1) {
return [[JSQMessagesTimestampFormatter sharedFormatter] attributedTimestampForDate:message.date];
}
}
return nil;
}
And then just repeat this logic to make sure the timestamps have the correct heights:
- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView
layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.item == 0) {
return kJSQMessagesCollectionViewCellLabelHeightDefault;
}
if (indexPath.item - 1 > 0) {
JSQMessage *previousMessage = [self.messages objectAtIndex:indexPath.item - 1];
JSQMessage *message = [self.messages objectAtIndex:indexPath.item];
if ([message.date timeIntervalSinceDate:previousMessage.date] / 60 > 1) {
return kJSQMessagesCollectionViewCellLabelHeightDefault;
}
}
return 0.0f;
}
To show timestamp cell only day by day
;
With @cerenali
's answer, we may have problems for dates which have different days but close times. Like:
msgDate1 = 31/03/2016 23:55
msgDate2 = 01/04/2016 00:07
to handle this, i replaced the logic inside if
with:
BOOL checkTime = message.date.year != previousMessage.date.year || message.date.month != previousMessage.date.month || message.date.day != previousMessage.date.day;
and the final code will be:
JSQMessage *message = [self.messages objectAtIndex:indexPath.item];
if (indexPath.item == 0) {
return [[JSQMessagesTimestampFormatter sharedFormatter] attributedTimestampForDate:message.date];
}
if (indexPath.item - 1 > -1) {
JSQMessage *previousMessage = [self.messages objectAtIndex:indexPath.item - 1];
BOOL checkTime = message.date.year != previousMessage.date.year || message.date.month != previousMessage.date.month || message.date.day != previousMessage.date.day;
if (checkTime) {
return [[JSQMessagesTimestampFormatter sharedFormatter] attributedTimestampForDate:message.date];
}
}
Note: I am using DateTools in my project.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With