在iOS 9中,启用重新排序集合视图所需的只是实现moveItenAtIndexPath...
这样......
override func collectionView(collectionView: UICollectionView,
moveItemAtIndexPath sourceIndexPath: NSIndexPath,
toIndexPath destinationIndexPath: NSIndexPath) {
print("sourceIndexPath= \(sourceIndexPath)")
print("destinationIndexPath= \(destinationIndexPath)")
}
但在tvOS中似乎还不够。还需要实现什么来启用重新排序?
以下是视图控制器的代码......
import UIKit
class ReorderableCollectionViewController: UICollectionViewController {
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numbers.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CellReuseIdentifier", forIndexPath: indexPath) as! CustomCollectionViewCell
cell.backgroundColor = UIColor.yellowColor()
let number = numbers[indexPath.item]
cell.label.text = "\(number)"
return cell
}
override func collectionView(collectionView: UICollectionView,
moveItemAtIndexPath sourceIndexPath: NSIndexPath,
toIndexPath destinationIndexPath: NSIndexPath) {
print("sourceIndexPath= \(sourceIndexPath)")
print("destinationIndexPath= \(destinationIndexPath)")
}
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
print("didUpdateFocusInContext")
coordinator.addCoordinatedAnimations({
if let previousItem = context.previouslyFocusedView as? CustomCollectionViewCell {
previousItem.backgroundColor = UIColor.yellowColor()
}
if let nextItem = context.nextFocusedView as? CustomCollectionViewCell {
nextItem.backgroundColor = UIColor.redColor()
}
}, completion: nil)
}
}
答案 0 :(得分:1)
我无法使用内置方法来启用collectionview / tableview单元格的重新排序。但是,自定义解决方案始终是一个选项。在我目前的项目中,我有聚焦细胞和突出细胞的概念。我还有一个单独的按钮来触发突出显示的单元格的移动。此外,我希望有一个类似于主屏幕的行为,其中长按钮也会触发移动。以下是实现结果所需的大部分代码片段:
该类继承自UIView,并且UICollectionView连接到playlistCollection属性。
核心思想:视图具有重新排序状态的特殊标志。触发此标志后,将阻止所有焦点更改。如果焦点即将移动到另一个单元格 - 交换当前聚焦的单元格与用户试图关注的单元格。否则不要做任何事情(这样焦点永远不会离开集合视图,除非它处于正常状态)。
其他选项:您也可以在模型中交换数据并重新加载单元格,而不是交换单元格。这样做的好处是你可以更快地通过列表移动选定的单元格(以滚动列表的速度),但重新加载2个单元格会导致轻微的延迟,因此我决定使用我当前的解决方案。如果你想尝试这个解决方案,必须将触发单元格更改的代码从shouldUpdateFocusInContext移动到didUpdateFocusInContext,并且只能禁止在collectionview之外移动的焦点更改(而不是所有焦点更改)。
希望这有帮助。
_pressureGestureRecognizer会覆盖应用程序可访问的所有远程按钮的默认行为(菜单,播放/暂停,点击),因此只有在视图处于重新排序状态时才会启用它。
@implementation PlaylistView {
int _highlightedCell;
UILongPressGestureRecognizer *_longPressGestureRecognizer;
UITapGestureRecognizer *_pressGestureRecognizer;
BOOL _isBeingReordered;
NSMutableArray *_data;
}
@synthesize isBeingReordered = _isBeingReordered;
- (void)setup {
_isBeingReordered = NO;
_data = [[NSMutableArray alloc] initWithCapacity:20];
for (int i = 0; i < 20; i++)
{
[_data addObject:[NSString stringWithFormat:@"Temp %i", i]];
}
_longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressed:)];
[self.playlistCollection addGestureRecognizer:_longPressGestureRecognizer];
_pressGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(pressed:)];
_pressGestureRecognizer.allowedPressTypes = @[@(UIPressTypeMenu), @(UIPressTypeSelect), @(UIPressTypePlayPause)];
[self.playlistCollection addGestureRecognizer:_pressGestureRecognizer];
_pressGestureRecognizer.enabled = NO;
}
- (void)pressed:(UITapGestureRecognizer *)gesture {
if (!_isBeingReordered)
return;
_isBeingReordered = NO;
_pressGestureRecognizer.enabled = NO;
}
- (void)longPressed:(UILongPressGestureRecognizer *)gesture {
if (_isBeingReordered)
return;
_isBeingReordered = YES;
_pressGestureRecognizer.enabled = YES;
}
- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator {
[super didUpdateFocusInContext:context withAnimationCoordinator:coordinator];
if ([context.nextFocusedView isKindOfClass:[PlaylistCell class]]) {
if (_isBeingReordered)
{
NSLog(@"This should never happen.");
}
else
{
int nextIdx = [self.playlistCollection indexPathForCell:context.nextFocusedView].row;
if (nextIdx != _highlightedCell) {
PlaylistCell *prevCell = [self.playlistCollection cellForItemAtIndexPath:[NSIndexPath indexPathForItem:_highlightedCell inSection:0]];
if ([prevCell highlighted])
prevCell.highlighted = NO;
}
_highlightedCell = nextIdx;
}
}
}
- (void)moveCellFromRow:(int)artwork offset:(int)offset {
if (artwork + offset >= 0 && artwork + offset <= [_data count] - 1)
{
[self.playlistCollection performBatchUpdates:^{
[self.playlistCollection moveItemAtIndexPath:[NSIndexPath indexPathForItem:artwork inSection:0] toIndexPath:[NSIndexPath indexPathForItem:artwork + offset inSection:0]];
[self.playlistCollection moveItemAtIndexPath:[NSIndexPath indexPathForItem:artwork + offset inSection:0] toIndexPath:[NSIndexPath indexPathForItem:artwork inSection:0]];
_highlightedCell += offset;
//if there are certain elements in the cells that are position dependant, this is the right time to change them
//because these cells are not reloaded by default (for example you have idx displayed in your cell... the cells will swap but idxs won't by default)
} completion:^(BOOL finished) {
NSString *temp = _data[artwork + offset];
_data[artwork + offset] = _data[artwork];
_data[artwork] = temp;
}];
}
}
- (BOOL)collectionView:(UICollectionView *)collectionView shouldUpdateFocusInContext:(UICollectionViewFocusUpdateContext *)context {
if (_isBeingReordered)
{
//code only supports vertical reording.
if (context.focusHeading == UIFocusHeadingDown)
{
[self moveCellFromRow:_highlightedCell offset:1];
}
else if (context.focusHeading == UIFocusHeadingUp)
{
[self moveCellFromRow:_highlightedCell offset:-1];
}
return NO;
}
return YES;
}
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
//i have a custom code to handle highlights
return NO;
}
@end