Commit 625d6df1 authored by Carola Nitz's avatar Carola Nitz

avoid crash and make collectionview scrollable again

parent d9ef1bf9
......@@ -10,11 +10,12 @@
* Refer to the COPYING file of the official project for license.
*****************************************************************************/
@interface VLCFolderCollectionViewFlowLayout : UICollectionViewFlowLayout
@interface VLCFolderCollectionViewFlowLayout : UICollectionViewFlowLayout <UIGestureRecognizerDelegate>
@property (assign, nonatomic) CGFloat scrollingSpeed;
@property (assign, nonatomic) UIEdgeInsets scrollingTriggerEdgeInsets;
@property (strong, nonatomic, readonly) UIPanGestureRecognizer *panGestureRecognizer;
@property (nonatomic, readonly) UILongPressGestureRecognizer *longPressGestureRecognizer;
@property (nonatomic, readonly) UIPanGestureRecognizer *panGestureRecognizer;
@end
......
......@@ -75,6 +75,7 @@ static NSString * const kLXCollectionViewKeyPath = @"collectionView";
CGPoint _panTranslationInCollectionView;
CADisplayLink *_displayLink;
UIView *_folderView;
BOOL _didPan;
}
@end
......@@ -87,14 +88,23 @@ static NSString * const kLXCollectionViewKeyPath = @"collectionView";
}
- (void)setupCollectionView {
_longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self
action:@selector(handleLongPressGesture:)];
_longPressGestureRecognizer.delegate = self;
_panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self
action:@selector(handlePanGesture:)];
// Links the default long press gesture recognizer to the custom long press gesture recognizer we are creating now
// by enforcing failure dependency so that they doesn't clash.
for (UIGestureRecognizer *gestureRecognizer in self.collectionView.gestureRecognizers) {
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]])
[gestureRecognizer requireGestureRecognizerToFail:_panGestureRecognizer];
if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
[gestureRecognizer requireGestureRecognizerToFail:_longPressGestureRecognizer];
}
}
[self.collectionView addGestureRecognizer:_longPressGestureRecognizer];
_panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self
action:@selector(handlePanGesture:)];
_panGestureRecognizer.delegate = self;
[self.collectionView addGestureRecognizer:_panGestureRecognizer];
// Useful in multiple scenarios: one common scenario being when the Notification Center drawer is pulled down
......@@ -137,7 +147,7 @@ static NSString * const kLXCollectionViewKeyPath = @"collectionView";
- (void)invalidateLayoutIfNecessary {
NSIndexPath *newIndexPath = [self.collectionView indexPathForItemAtPoint:_currentView.center];
NSIndexPath *previousIndexPath = _selectedItemIndexPath;
if ((newIndexPath == nil) || [newIndexPath isEqual:previousIndexPath]) {
_currentView.transform = CGAffineTransformMakeScale(1.1f, 1.1f);
[_folderView removeFromSuperview];
......@@ -152,7 +162,7 @@ static NSString * const kLXCollectionViewKeyPath = @"collectionView";
}
[self.collectionView insertSubview:_folderView atIndex:0];
if (!CGPointEqualToPoint(_folderView.center,cell.center))
if (!CGPointEqualToPoint(_folderView.center,cell.center))
_folderView.frame = cell.frame;
[UIView
......@@ -178,7 +188,7 @@ static NSString * const kLXCollectionViewKeyPath = @"collectionView";
if (direction == oldDirection)
return;
}
[self invalidatesScrollTimer];
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleScroll:)];
......@@ -193,7 +203,7 @@ static NSString * const kLXCollectionViewKeyPath = @"collectionView";
LXScrollingDirection direction = (LXScrollingDirection)[displayLink.LX_userInfo[kLXScrollingDirectionKey] integerValue];
if (direction == LXScrollingDirectionUnknown)
return;
CGSize frameSize = self.collectionView.bounds.size;
CGSize contentSize = self.collectionView.contentSize;
CGPoint contentOffset = self.collectionView.contentOffset;
......@@ -201,33 +211,33 @@ static NSString * const kLXCollectionViewKeyPath = @"collectionView";
// and it would diverge from the view's center resulting in a "cell is slipping away under finger"-bug.
CGFloat distance = rint(self.scrollingSpeed / LX_FRAMES_PER_SECOND);
CGPoint translation = CGPointZero;
switch(direction) {
case LXScrollingDirectionUp: {
distance = -distance;
CGFloat minY = 0.0f;
if ((contentOffset.y + distance) <= minY)
distance = -contentOffset.y;
translation = CGPointMake(0.0f, distance);
} break;
case LXScrollingDirectionDown: {
CGFloat maxY = MAX(contentSize.height, frameSize.height) - frameSize.height;
if ((contentOffset.y + distance) >= maxY)
distance = maxY - contentOffset.y;
translation = CGPointMake(0.0f, distance);
} break;
case LXScrollingDirectionLeft: {
distance = -distance;
CGFloat minX = 0.0f;
if ((contentOffset.x + distance) <= minX)
distance = -contentOffset.x;
translation = CGPointMake(distance, 0.0f);
} break;
case LXScrollingDirectionRight: {
......@@ -242,21 +252,18 @@ static NSString * const kLXCollectionViewKeyPath = @"collectionView";
// Do nothing...
} break;
}
_currentViewCenter = LXS_CGPointAdd(_currentViewCenter, translation);
_currentView.center = LXS_CGPointAdd(_currentViewCenter, _panTranslationInCollectionView);
self.collectionView.contentOffset = LXS_CGPointAdd(contentOffset, translation);
}
- (void)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer {
- (void)handleLongPressGesture:(UILongPressGestureRecognizer *)gestureRecognizer {
//keeps the controller from dragging while not in editmode
if (!((VLCPlaylistViewController *)self.delegate).isEditing) return;
switch (gestureRecognizer.state) {
switch(gestureRecognizer.state) {
case UIGestureRecognizerStateBegan: {
NSIndexPath *currentIndexPath = [self.collectionView indexPathForItemAtPoint:[gestureRecognizer locationInView:self.collectionView]];
_selectedItemIndexPath = currentIndexPath;
UICollectionViewCell *collectionViewCell = [self.collectionView cellForItemAtIndexPath:_selectedItemIndexPath];
......@@ -284,21 +291,58 @@ static NSString * const kLXCollectionViewKeyPath = @"collectionView";
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
_currentView.transform = CGAffineTransformMakeScale(1.1f, 1.1f);
highlightedImageView.alpha = 0.0f;
imageView.alpha = 1.0f;
_currentView.transform = CGAffineTransformMakeScale(1.1f, 1.1f);
highlightedImageView.alpha = 0.0f;
imageView.alpha = 1.0f;
}
completion:^(BOOL finished) {
[highlightedImageView removeFromSuperview];
[highlightedImageView removeFromSuperview];
}];
[self invalidateLayout];
break;
}
} break;
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateEnded: {
if (_didPan) return;
NSIndexPath *currentIndexPath = _selectedItemIndexPath;
if (currentIndexPath) {
_selectedItemIndexPath = nil;
_currentViewCenter = CGPointZero;
UICollectionViewLayoutAttributes *layoutAttributes = [self layoutAttributesForItemAtIndexPath:currentIndexPath];
[UIView
animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
_currentView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
_currentView.center = layoutAttributes.center;
}
completion:^(BOOL finished) {
[_currentView removeFromSuperview];
_currentView = nil;
[self invalidateLayout];
}];
}
} break;
default: break;
}
}
- (void)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer {
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateBegan:
_didPan = YES;
case UIGestureRecognizerStateChanged: {
_panTranslationInCollectionView = [gestureRecognizer translationInView:self.collectionView];
CGPoint viewCenter = _currentView.center = LXS_CGPointAdd(_currentViewCenter, _panTranslationInCollectionView);
[self invalidateLayoutIfNecessary];
switch (self.scrollDirection) {
......@@ -325,16 +369,16 @@ static NSString * const kLXCollectionViewKeyPath = @"collectionView";
}
} break;
}
} break;
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateEnded: {
_didPan = NO;
[_folderView removeFromSuperview];
_folderView = nil;
NSIndexPath *newIndexPath = [self.collectionView indexPathForItemAtPoint:_currentView.center];
NSIndexPath *currentIndexPath = _selectedItemIndexPath;
if (newIndexPath != nil && ![currentIndexPath isEqual:newIndexPath]) {
if (newIndexPath != nil && ![currentIndexPath isEqual:newIndexPath] && ((VLCPlaylistViewController *)self.delegate).isEditing) {
[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
_currentView.transform = CGAffineTransformMakeScale(0.1f, 0.1f);
_currentView.center = [self layoutAttributesForItemAtIndexPath:newIndexPath].center;
......@@ -368,7 +412,7 @@ static NSString * const kLXCollectionViewKeyPath = @"collectionView";
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSArray *layoutAttributesForElementsInRect = [super layoutAttributesForElementsInRect:rect];
for (UICollectionViewLayoutAttributes *layoutAttributes in layoutAttributesForElementsInRect) {
switch (layoutAttributes.representedElementCategory) {
case UICollectionElementCategoryCell: {
......@@ -379,13 +423,12 @@ static NSString * const kLXCollectionViewKeyPath = @"collectionView";
} break;
}
}
return layoutAttributesForElementsInRect;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *layoutAttributes = [super layoutAttributesForItemAtIndexPath:indexPath];
switch (layoutAttributes.representedElementCategory) {
case UICollectionElementCategoryCell: {
[self applyLayoutAttributes:layoutAttributes];
......@@ -394,9 +437,28 @@ static NSString * const kLXCollectionViewKeyPath = @"collectionView";
// Do nothing...
} break;
}
return layoutAttributes;
}
#pragma mark - UIGestureRecognizerDelegate methods
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if ([self.panGestureRecognizer isEqual:gestureRecognizer]) {
return (_selectedItemIndexPath != nil);
}
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if ([self.longPressGestureRecognizer isEqual:gestureRecognizer]) {
return [self.panGestureRecognizer isEqual:otherGestureRecognizer];
}
if ([self.panGestureRecognizer isEqual:gestureRecognizer]) {
return [self.longPressGestureRecognizer isEqual:otherGestureRecognizer];
}
return NO;
}
#pragma mark - Key-Value Observing methods
......
......@@ -41,7 +41,8 @@
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
self.isSelectedView.hidden = !editing;
if ([_mediaObject isKindOfClass:[MLLabel class]] || [_mediaObject.labels count] == 0)
if (!([_mediaObject isKindOfClass:[MLFile class]] && [_mediaObject.labels count] > 0))
[self shake:editing];
[self selectionUpdate];
[self _updatedDisplayedInformationForKeyPath:@"editing"];
......@@ -266,7 +267,7 @@
{
self.titleLabel.text = label.name;
NSUInteger count = label.files.count;
self.subtitleLabel.text = [NSString stringWithFormat:(count == 1) ? NSLocalizedString(@"LIBRARY_TRACKS", @"") : NSLocalizedString(@"LIBRARY_SINGLE_TRACK", @""), count];
self.subtitleLabel.text = [NSString stringWithFormat:(count == 1) ? NSLocalizedString(@"LIBRARY_SINGLE_TRACK", @"") : NSLocalizedString(@"LIBRARY_TRACKS", @""), count];
self.mediaIsUnreadView.hidden = YES;
self.progressView.hidden = YES;
}
......
......@@ -239,7 +239,7 @@
{
self.titleLabel.text = label.name;
NSUInteger count = label.files.count;
self.subtitleLabel.text = [NSString stringWithFormat:(count == 1) ? NSLocalizedString(@"LIBRARY_TRACKS", @"") : NSLocalizedString(@"LIBRARY_SINGLE_TRACK", @""), count];
self.subtitleLabel.text = [NSString stringWithFormat:(count == 1) ? NSLocalizedString(@"LIBRARY_TRACK", @"") : NSLocalizedString(@"LIBRARY_SINGLE_TRACKS", @""), count];
self.mediaIsUnreadView.hidden = YES;
self.progressIndicator.hidden = YES;
}
......
......@@ -53,6 +53,7 @@ static NSString *kDisplayedFirstSteps = @"Did we display the first steps tutoria
VLCFolderCollectionViewFlowLayout *_folderLayout;
LXReorderableCollectionViewFlowLayout *_reorderLayout;
BOOL inFolder;
UILongPressGestureRecognizer *_longPressGestureRecognizer;
}
@property (nonatomic, strong) UITableView *tableView;
......@@ -95,8 +96,8 @@ static NSString *kDisplayedFirstSteps = @"Did we display the first steps tutoria
_collectionView.opaque = YES;
_collectionView.backgroundColor = [UIColor colorWithWhite:.122 alpha:1.];
self.view = _collectionView;
UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(_collectionViewHandleLongPressGesture:)];
[_collectionView addGestureRecognizer:longPressGestureRecognizer];
_longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(_collectionViewHandleLongPressGesture:)];
[_collectionView addGestureRecognizer:_longPressGestureRecognizer];
if (SYSTEM_RUNS_IOS7_OR_LATER)
[_collectionView registerNib:[UINib nibWithNibName:@"VLCFuturePlaylistCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:@"PlaylistCell"];
else
......@@ -224,9 +225,13 @@ static NSString *kDisplayedFirstSteps = @"Did we display the first steps tutoria
MLLabel *folder = (MLLabel*) mediaObject;
inFolder = YES;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
if (_reorderLayout == nil)
_reorderLayout = [[LXReorderableCollectionViewFlowLayout alloc] init];
for (UIGestureRecognizer *recognizer in self.view.gestureRecognizers) {
if (recognizer == _folderLayout.panGestureRecognizer || recognizer == _folderLayout.longPressGestureRecognizer || recognizer == _longPressGestureRecognizer)
[self.collectionView removeGestureRecognizer:recognizer];
}
_reorderLayout = [[LXReorderableCollectionViewFlowLayout alloc] init];
[self.collectionView setCollectionViewLayout:_reorderLayout animated:NO];
_folderLayout = nil;
}
_foundMedia = [[folder.files allObjects] mutableCopy];
self.navigationItem.leftBarButtonItem = [UIBarButtonItem themedBackButtonWithTarget:self andSelector:@selector(backToAllItems:)];
......@@ -905,12 +910,15 @@ static NSString *kDisplayedFirstSteps = @"Did we display the first steps tutoria
/* UIKit doesn't clear the selection automagically if we leave the editing mode
* so we need to do so manually */
if (!editing) {
[self.collectionView addGestureRecognizer:_longPressGestureRecognizer];
NSArray *selectedItems = [self.collectionView indexPathsForSelectedItems];
NSUInteger count = selectedItems.count;
for (NSUInteger x = 0; x < count; x++)
[self.collectionView deselectItemAtIndexPath:selectedItems[x] animated:NO];
}
} else
[self.collectionView removeGestureRecognizer:_longPressGestureRecognizer];
} else {
self.tableView.allowsMultipleSelectionDuringEditing = editing;
[self.tableView setEditing:editing animated:YES];
......@@ -942,10 +950,15 @@ static NSString *kDisplayedFirstSteps = @"Did we display the first steps tutoria
- (IBAction)backToAllItems:(id)sender
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[self.collectionView setCollectionViewLayout:_folderLayout];
//TODO: find better way than creating a new recognizer
UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(_collectionViewHandleLongPressGesture:)];
[_collectionView addGestureRecognizer:longPressGestureRecognizer];
//for some reason the Gesturerecognizer block themselves if not removed manually
for (UIGestureRecognizer *recognizer in self.view.gestureRecognizers) {
if (recognizer == _reorderLayout.panGestureRecognizer || recognizer == _reorderLayout.longPressGestureRecognizer)
[self.collectionView removeGestureRecognizer:recognizer];
}
_folderLayout = [[VLCFolderCollectionViewFlowLayout alloc] init];
[self.collectionView setCollectionViewLayout:_folderLayout animated:NO];
_reorderLayout = nil;
[_collectionView addGestureRecognizer:_longPressGestureRecognizer];
}
inFolder = NO;
UIBarButtonItem *createFolderItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemOrganize target:self action:@selector(createFolder)];
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment