UICollectionView有效拖放 [英] UICollectionView effective drag and drop

查看:183
本文介绍了UICollectionView有效拖放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用UICollectionView来实现UITableView重新排序行为。



让我们调用一个 UItableView电视和一个 UICollectionView CV (以澄清以下解释)



我基本上是想重现拖放电视,但是我没有使用编辑模式,一旦触发长按手势,单元格就可以移动了。我使用CV的移动方法,一切都很好。



我更新了CV的contentOffset属性,以便在用户拖动时处理滚动一个单元格当用户进入顶部和底部的特定rect时,我更新contentOffset和CV滚动。问题是当用户停止移动手指时,手势不会发送任何使滚动停止的更新,只要用户移动手指就重新开始。



这种行为绝对不是自然的,我宁愿继续滚动,直到用户在电视中发布简历。电视拖放经验非常棒,我真的想重现同样的感觉。有没有人知道他们在重新排序时如何管理电视中的滚动?




  • 我尝试使用定时器反复触发滚动操作,只要手势位置在正确的位置,滚动是可怕的,并不是非常有成效(非常缓慢和跳跃)。

  • 我还尝试使用GCD来听另一个线程的手势位置,但结果是最糟糕的。



我没有想到这个,所以如果有人有答案,我会嫁给他!

这是longPress方法的实现:

   - (void)handleLongPress: (UILongPressGestureRecognizer *)sender 
{
ReorganizableCVCLayout * layout =(ReorganizableCVCLayout *)self.collectionView.collectionViewLayout;
CGPoint gesturePosition = [sender locationInView:self.collectionView];
NSIndexPath * selectedIndexPath = [self.collectionView indexPathForItemAtPoint:gesturePosition];

if(sender.state == UIGestureRecognizerStateBegan)
{
layout.selectedItem = selectedIndexPath;
layout.gesturePoint = gesturePosition; //设置gesturePoint无效布局
}
else if(sender.state == UIGestureRecognizerStateChanged)
{
layout.gesturePoint = gesturePosition; //设置gesturePoint无效布局
[self swapCellAtPoint:gesturePosition];
[self manageScrollWithReferencePoint:gesturePosition];
}
else
{
[self.collectionView performBatchUpdates:^
{
layout.selectedItem = nil;
layout.gesturePoint = CGPointZero; //设置gesturePoint无效布局
}完成:^(BOOL完成){[self.collectionView reloadData];}];
}
}

为了使CV滚动,我正在使用该方法:

   - (void)manageScrollWithReferencePoint:(CGPoint)gesturePoint 
{
ReorganizableCVCLayout * layout =(ReorganizableCVCLayout *)self.collectionView.collectionViewLayout;
CGFloat topScrollLimit = self.collectionView.contentOffset.y + layout.itemSize.height / 2 + SCROLL_BORDER;
CGFloat bottomScrollLimit = self.collectionView.contentOffset.y + self.collectionView.frame.size.height-layout.itemSize.height / 2-SCROLL_BORDER;
CGPoint contentOffset = self.collectionView.contentOffset;

if(gesturePoint.y< topScrollLimit&& HandsPoint.y - layout.itemSize.height / 2 - SCROLL_BORDER> 0)
contentOffset.y - = SCROLL_STEP;
else if(gesturePoint.y> bottomScrollLimit&&
gesturePoint.y + layout.itemSize.height / 2 + SCROLL_BORDER< self.collectionView.contentSize.height)
contentOffset。 y + = SCROLL_STEP;

[self.collectionView setContentOffset:contentOffset];
}


解决方案

这可能有助于



https://github.com/lxcid/LXReorderableCollectionViewFlowLayout



这是将 UICollectionView 扩展为允许每个 UICollectionViewCells 由用户手动重新布置,长时间触摸(又称触摸按钮)。用户可以将单元格拖动到集合中的任何其他位置,其他单元格将自动重新排序。感谢 lxcid 为此。


I am currently trying to implement the UITableView reordering behavior using UICollectionView.

Let's call a UItableView TV and a UICollectionView CV (to clarify the following explanation)

I am basically trying to reproduce the drag&drop of the TV, but I am not using the edit mode, the cell is ready to be moved as soon as the long press gesture is triggered. It works prefectly, I am using the move method of the CV, everything is fine.

I update the contentOffset property of the CV to handle the scroll when the user is dragging a cell. When a user goes to a particular rect at the top and the bottom, I update the contentOffset and the CV scroll. The problem is when the user stop moving it's finger, the gesture doesn't send any update which makes the scroll stop and start again as soon as the user moves his finger.

This behavior is definitely not natural, I would prefer continu to scroll until the user release the CV as it is the case in the TV. The TV drag&drop experience is awesome and I really want to reproduce the same feeling. Does anyone know how they manage the scroll in TV during reordering ?

  • I tried using a timer to trigger a scroll action repeatedly as long as the gesture position is in the right spot, the scroll was awful and not very productive (very slow and jumpy).
  • I also tried using GCD to listen the gesture position in another thread but the result is even worst.

I ran out of idea about that, so if someone has the answer I would marry him!

Here is the implementation of the longPress method:

- (void)handleLongPress:(UILongPressGestureRecognizer *)sender
{
    ReorganizableCVCLayout *layout = (ReorganizableCVCLayout *)self.collectionView.collectionViewLayout;
    CGPoint gesturePosition = [sender locationInView:self.collectionView];
    NSIndexPath *selectedIndexPath = [self.collectionView indexPathForItemAtPoint:gesturePosition];

    if (sender.state == UIGestureRecognizerStateBegan)
    {
        layout.selectedItem = selectedIndexPath;
        layout.gesturePoint = gesturePosition; // Setting gesturePoint invalidate layout
    }
    else if (sender.state == UIGestureRecognizerStateChanged)
    {
        layout.gesturePoint = gesturePosition; // Setting gesturePoint invalidate layout
        [self swapCellAtPoint:gesturePosition];
        [self manageScrollWithReferencePoint:gesturePosition];
    }
    else
    {
        [self.collectionView performBatchUpdates:^
        {
            layout.selectedItem = nil;
            layout.gesturePoint = CGPointZero; // Setting gesturePoint invalidate layout
        } completion:^(BOOL completion){[self.collectionView reloadData];}];
    }
}

To make the CV scroll, I am using that method:

- (void)manageScrollWithReferencePoint:(CGPoint)gesturePoint
{
    ReorganizableCVCLayout *layout = (ReorganizableCVCLayout *)self.collectionView.collectionViewLayout;
    CGFloat topScrollLimit = self.collectionView.contentOffset.y+layout.itemSize.height/2+SCROLL_BORDER;
    CGFloat bottomScrollLimit = self.collectionView.contentOffset.y+self.collectionView.frame.size.height-layout.itemSize.height/2-SCROLL_BORDER;
    CGPoint contentOffset = self.collectionView.contentOffset;

    if (gesturePoint.y < topScrollLimit && gesturePoint.y - layout.itemSize.height/2 - SCROLL_BORDER > 0)
        contentOffset.y -= SCROLL_STEP;
    else if (gesturePoint.y > bottomScrollLimit &&
             gesturePoint.y + layout.itemSize.height/2 + SCROLL_BORDER < self.collectionView.contentSize.height)
        contentOffset.y += SCROLL_STEP;

    [self.collectionView setContentOffset:contentOffset];
}

解决方案

This might help

https://github.com/lxcid/LXReorderableCollectionViewFlowLayout

This is extends the UICollectionView to allow each of the UICollectionViewCells to be rearranged manually by the user with a long touch (aka touch-and-hold). The user can drag the Cell to any other position in the collection and the other cells will reorder automatically. Thanks go to lxcid for this.

这篇关于UICollectionView有效拖放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆