Skip to content
This repository has been archived by the owner on Aug 14, 2019. It is now read-only.

Commit

Permalink
attempting to fix menu controller
Browse files Browse the repository at this point in the history
  • Loading branch information
jessesquires committed Aug 31, 2014
1 parent 9ed3f97 commit 8c9201e
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 89 deletions.
104 changes: 103 additions & 1 deletion JSQMessagesViewController/Controllers/JSQMessagesViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ - (void)jsq_configureMessagesViewController;
- (NSString *)jsq_currentlyComposedMessageText;

- (void)jsq_handleDidChangeStatusBarFrameNotification:(NSNotification *)notification;
- (void)jsq_didReceiveMenuWillShowNotification:(NSNotification *)notification;

- (void)jsq_updateKeyboardTriggerPoint;
- (void)jsq_setToolbarBottomLayoutGuideConstant:(CGFloat)constant;
Expand Down Expand Up @@ -272,6 +273,13 @@ - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrie
[self.collectionView.collectionViewLayout invalidateLayoutWithContext:[JSQMessagesCollectionViewFlowLayoutInvalidationContext context]];
}

#pragma mark - UIResponder

- (BOOL)canBecomeFirstResponder
{
return YES;
}

#pragma mark - Messages view controller

- (void)didPressSendButton:(UIButton *)button
Expand Down Expand Up @@ -464,11 +472,28 @@ - (CGSize)collectionView:(UICollectionView *)collectionView

#pragma mark - Collection view delegate

- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}

- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
if (action == @selector(copy:)) {
return YES;
}

return NO;
}

- (void)collectionView:(JSQMessagesCollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
if (action == @selector(copy:)) {
id<JSQMessageData> messageData = [self collectionView:collectionView messageDataForItemAtIndexPath:indexPath];
[[UIPasteboard generalPasteboard] setString:[messageData text]];
}
}

#pragma mark - Collection view delegate flow layout

- (CGSize)collectionView:(JSQMessagesCollectionView *)collectionView
Expand Down Expand Up @@ -590,6 +615,74 @@ - (void)jsq_handleDidChangeStatusBarFrameNotification:(NSNotification *)notifica
}
}

- (void)jsq_didReceiveMenuWillShowNotification:(NSNotification *)notification
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIMenuControllerWillShowMenuNotification
object:nil];

UIMenuController *menu = [notification object];
[menu setMenuVisible:NO animated:NO];

CGRect menuFrame = [self.view convertRect:menu.menuFrame toView:nil];

NSLog(@"MENU FRAME = %@", NSStringFromCGRect(menu.menuFrame));

// UIView *v = [[UIView alloc] initWithFrame:menuFrame];
// v.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.5];
// [self.view addSubview:v];

NSUInteger intersectedItem = NSNotFound;

for (JSQMessagesCollectionViewCell *eachCell in [self.collectionView visibleCells]) {
CGRect eachCellFrame = [self.collectionView convertRect:eachCell.frame toView:nil];

if (CGRectIntersectsRect(menuFrame, eachCellFrame)) {
intersectedItem = [self.collectionView indexPathForCell:eachCell].item;

NSLog(@"INTERSECT = %d", intersectedItem);
}
}

if (intersectedItem + 1 >= [self.collectionView numberOfItemsInSection:0]) {
NSLog(@"RETURN ");

[menu setMenuVisible:YES animated:YES];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(jsq_didReceiveMenuWillShowNotification:)
name:UIMenuControllerWillShowMenuNotification
object:nil];

return;
}

if (intersectedItem != NSNotFound) {
NSIndexPath *nextIndexPath = [NSIndexPath indexPathForItem:intersectedItem + 1 inSection:0];

NSLog(@"FOUND = %@", nextIndexPath);

JSQMessagesCollectionViewCell *selectedCell = (JSQMessagesCollectionViewCell *)[self.collectionView cellForItemAtIndexPath:nextIndexPath];

CGRect selectedCellFrame = [self.collectionView convertRect:selectedCell.frame toView:nil];

CGRect finalFrame = CGRectMake(selectedCellFrame.origin.x,
selectedCellFrame.origin.y + CGRectGetHeight(selectedCell.messageBubbleTopLabel.frame) + CGRectGetHeight(selectedCell.cellTopLabel.frame),
selectedCellFrame.size.width,
selectedCellFrame.size.height);

NSLog(@"FINAL = %@", NSStringFromCGRect(finalFrame));

[menu setTargetRect:finalFrame inView:self.view];
[menu setMenuVisible:YES animated:YES];
}

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(jsq_didReceiveMenuWillShowNotification:)
name:UIMenuControllerWillShowMenuNotification
object:nil];
}

#pragma mark - Key-value observing

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
Expand Down Expand Up @@ -797,11 +890,20 @@ - (void)jsq_registerForNotifications:(BOOL)registerForNotifications
selector:@selector(jsq_handleDidChangeStatusBarFrameNotification:)
name:UIApplicationDidChangeStatusBarFrameNotification
object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(jsq_didReceiveMenuWillShowNotification:)
name:UIMenuControllerWillShowMenuNotification
object:nil];
}
else {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationDidChangeStatusBarFrameNotification
object:nil];

[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIMenuControllerWillShowMenuNotification
object:nil];
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,6 @@
*/
@property (weak, nonatomic) UIImageView *avatarImageView;

/**
* Returns the underlying gesture recognizer for long press gestures in the cell.
* This gesture handles the copy action for the cell.
* Access this property when you need to override or more precisely control the long press gesture.
*/
@property (weak, nonatomic, readonly) UILongPressGestureRecognizer *longPressGestureRecognizer;

/**
* Returns the underlying gesture recognizer for tap gestures in the avatarImageView of the cell.
* This gesture handles the tap event for the avatarImageView and notifies the cell's delegate.
Expand Down
94 changes: 13 additions & 81 deletions JSQMessagesViewController/Views/JSQMessagesCollectionViewCell.m
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,10 @@ @interface JSQMessagesCollectionViewCell ()

@property (assign, nonatomic) CGSize avatarViewSize;

@property (weak, nonatomic, readwrite) UILongPressGestureRecognizer *longPressGestureRecognizer;
@property (weak, nonatomic, readwrite) UITapGestureRecognizer *tapGestureRecognizer;

- (void)jsq_handleLongPressGesture:(UILongPressGestureRecognizer *)longPress;
- (void)jsq_handleTapGesture:(UITapGestureRecognizer *)tap;

- (void)jsq_didReceiveMenuWillHideNotification:(NSNotification *)notification;
- (void)jsq_didReceiveMenuWillShowNotification:(NSNotification *)notification;

- (void)jsq_updateConstraint:(NSLayoutConstraint *)constraint withConstant:(CGFloat)constant;

@end
Expand Down Expand Up @@ -112,7 +107,7 @@ - (void)awakeFromNib

self.textView.textColor = [UIColor whiteColor];
self.textView.editable = NO;
self.textView.selectable = YES;
self.textView.selectable = NO;
self.textView.userInteractionEnabled = YES;
self.textView.dataDetectorTypes = UIDataDetectorTypeNone;
self.textView.showsHorizontalScrollIndicator = NO;
Expand All @@ -125,11 +120,6 @@ - (void)awakeFromNib
self.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : [UIColor whiteColor],
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) };

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(jsq_handleLongPressGesture:)];
longPress.minimumPressDuration = 0.4f;
[self addGestureRecognizer:longPress];
self.longPressGestureRecognizer = longPress;

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(jsq_handleTapGesture:)];
[self addGestureRecognizer:tap];
self.tapGestureRecognizer = tap;
Expand All @@ -146,9 +136,6 @@ - (void)dealloc
_messageBubbleImageView = nil;
_avatarImageView = nil;

[_longPressGestureRecognizer removeTarget:nil action:NULL];
_longPressGestureRecognizer = nil;

[_tapGestureRecognizer removeTarget:nil action:NULL];
_tapGestureRecognizer = nil;
}
Expand Down Expand Up @@ -203,6 +190,18 @@ - (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttribut
}
}

- (void)setHighlighted:(BOOL)highlighted
{
[super setHighlighted:highlighted];
self.messageBubbleImageView.highlighted = highlighted;
}

- (void)setSelected:(BOOL)selected
{
[super setSelected:selected];
self.messageBubbleImageView.highlighted = selected;
}

#pragma mark - Setters

- (void)setBackgroundColor:(UIColor *)backgroundColor
Expand Down Expand Up @@ -318,52 +317,8 @@ - (void)jsq_updateConstraint:(NSLayoutConstraint *)constraint withConstant:(CGFl
[self setNeedsUpdateConstraints];
}

#pragma mark - UIResponder

- (BOOL)canBecomeFirstResponder
{
return YES;
}

- (BOOL)becomeFirstResponder
{
return [super becomeFirstResponder];
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
return (action == @selector(copy:));
}

- (void)copy:(id)sender
{
[[UIPasteboard generalPasteboard] setString:self.textView.text];
[self resignFirstResponder];
}

#pragma mark - Gesture recognizers

- (void)jsq_handleLongPressGesture:(UILongPressGestureRecognizer *)longPress
{
if (longPress.state != UIGestureRecognizerStateBegan || ![self becomeFirstResponder]) {
return;
}

UIMenuController *menu = [UIMenuController sharedMenuController];
CGRect targetRect = [self convertRect:self.messageBubbleImageView.bounds fromView:self.messageBubbleImageView];

[menu setTargetRect:CGRectInset(targetRect, 0.0f, 4.0f) inView:self];

self.messageBubbleImageView.highlighted = YES;

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(jsq_didReceiveMenuWillShowNotification:)
name:UIMenuControllerWillShowMenuNotification
object:menu];

[menu setMenuVisible:YES animated:YES];
}

- (void)jsq_handleTapGesture:(UITapGestureRecognizer *)tap
{
CGPoint touchPt = [tap locationInView:self];
Expand All @@ -379,27 +334,4 @@ - (void)jsq_handleTapGesture:(UITapGestureRecognizer *)tap
}
}

#pragma mark - Notifications

- (void)jsq_didReceiveMenuWillHideNotification:(NSNotification *)notification
{
self.messageBubbleImageView.highlighted = NO;

[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIMenuControllerWillHideMenuNotification
object:nil];
}

- (void)jsq_didReceiveMenuWillShowNotification:(NSNotification *)notification
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIMenuControllerWillShowMenuNotification
object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(jsq_didReceiveMenuWillHideNotification:)
name:UIMenuControllerWillHideMenuNotification
object:[notification object]];
}

@end

0 comments on commit 8c9201e

Please sign in to comment.