문제

현재 UICollectionView를 사용하여 UITableView 재정렬 동작을 구현하려고 합니다.

전화하자 UItableView TV 그리고 UICollection이력서 보기 (다음 설명을 명확히 하기 위해)

기본적으로 TV의 드래그 앤 드롭을 재현하려고 하는데 편집 모드를 사용하지 않고 길게 누르기 동작이 트리거되는 즉시 셀을 이동할 준비가 되어 있습니다.완벽하게 작동하고 CV의 이동 방법을 사용하고 있으며 모든 것이 정상입니다.

사용자가 셀을 드래그할 때 스크롤을 처리하도록 CV의 contentOffset 속성을 업데이트합니다.사용자가 상단과 하단의 특정 사각형으로 이동하면 contentOffset과 CV 스크롤을 업데이트합니다.문제는 사용자가 손가락 움직임을 멈추면 제스처가 업데이트를 보내지 않아 사용자가 손가락을 움직이자마자 스크롤이 멈추고 다시 시작된다는 것입니다.

이 동작은 확실히 자연스럽지 않습니다. TV의 경우처럼 사용자가 CV를 공개할 때까지 계속 스크롤하는 것이 좋습니다.TV 드래그 앤 드롭 경험은 정말 훌륭하고 같은 느낌을 꼭 재현하고 싶습니다.재정렬하는 동안 TV에서 스크롤을 어떻게 관리하는지 아는 사람이 있나요?

  • 제스처 위치가 올바른 위치에 있는 한 타이머를 사용하여 스크롤 작업을 반복적으로 실행해 보았지만 스크롤이 끔찍했고 그다지 생산적이지 않았습니다(매우 느리고 불안했습니다).
  • 또한 다른 스레드에서 제스처 위치를 듣기 위해 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; // 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];}];
    }
}

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 && 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];
}
도움이 되었습니까?

해결책

도움이 될 수 있습니다.

https://github.com/lxcid/LXReorderableCollectionViewFlowLayout

이는 다음을 확장합니다. UICollectionView 각각을 허용하기 위해 UICollectionViewCells 사용자가 길게 터치(일명 길게 누르기)하여 수동으로 재정렬할 수 있습니다.사용자는 셀을 컬렉션의 다른 위치로 끌 수 있으며 다른 셀은 자동으로 재정렬됩니다.감사합니다 lxcid 이를 위해.

다른 팁

여기 대안은 다음과 같습니다.

DraggableCollectionView와 DraggableCollectionView의 차이점 LXReorderableCollectionViewFlowLayout 이다:

  • 데이터 소스는 한 번만 변경됩니다.이는 사용자가 항목을 드래그하는 동안 데이터 소스를 수정하지 않고 셀 위치가 변경됨을 의미합니다.
  • 사용자 정의 레이아웃과 함께 사용할 수 있도록 작성되었습니다.
  • 그것은 CADisplayLink 부드러운 스크롤과 애니메이션을 위해.
  • 드래그하는 동안 애니메이션이 취소되는 빈도가 줄어듭니다.좀 더 "자연스럽다"는 느낌이 듭니다.
  • 프로토콜이 확장됩니다. UICollectionViewDataSource 와 비슷한 방법으로 UITableViewDataSource.

진행중인 작업입니다.이제 여러 섹션이 지원됩니다.

사용자 정의 레이아웃과 함께 사용하려면 다음을 참조하세요. DraggableCollectionViewFlowLayout.대부분의 논리는 다음과 같습니다. LSCollectionViewLayoutHelper.CircleLayoutDemo에는 WWDC 2012의 Apple CircleLayout 예제를 작동시키는 방법을 보여주는 예제도 있습니다.

iOS 9의 현재 UICollectionView는 이제 재정렬을 지원합니다.

UICollectionViewControllers의 경우 collectionView(collectionView: UICollectionView, moveItemAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath)

만 대체하십시오.

UICollectionViews의 경우 위의 UICollectionViewDataSource 메소드를 구현하는 것 외에도 직접 제스처를 처리해야합니다.

여기서는 소스의 코드입니다.

private var longPressGesture: UILongPressGestureRecognizer!

override func viewDidLoad() {
    super.viewDidLoad()

    longPressGesture = UILongPressGestureRecognizer(target: self, action: "handleLongGesture:")
    self.collectionView.addGestureRecognizer(longPressGesture)
}

func handleLongGesture(gesture: UILongPressGestureRecognizer) {

    switch(gesture.state) {

    case UIGestureRecognizerState.Began:
        guard let selectedIndexPath = self.collectionView.indexPathForItemAtPoint(gesture.locationInView(self.collectionView)) else {
            break
        }
        collectionView.beginInteractiveMovementForItemAtIndexPath(selectedIndexPath)
    case UIGestureRecognizerState.Changed:
        collectionView.updateInteractiveMovementTargetPosition(gesture.locationInView(gesture.view!))
    case UIGestureRecognizerState.Ended:
        collectionView.endInteractiveMovement()
    default:
        collectionView.cancelInteractiveMovement()
    }
}
.

소스 : https ://developer.apple.com/library/ios/documentation/uikit/reference/uicollectionview_class/#/apple_ref/doc/uid/tp40012177-ch1-sw67

http://nshint.io/blog./ 2015 / 07 / 16 / UICollectionViews - 지금 - 쉬운 재정렬 /

실험을 원한다면, 당신이 볼 수있는 신속한 기반 자습서를 썼습니다.나는 "nofollow">이 .

여기 는 또 다른 접근법입니다 :

키 차이점은이 솔루션이 드래그 앤 드롭 기능을 제공하기 위해 "GHOST"또는 "더미"셀을 필요로하지 않는다는 것입니다.그것은 단순히 셀 자체를 사용합니다.애니메이션은 UITableView와 일치합니다.주위를 이동하면서 컬렉션보기 레이아웃의 개인 데이터 소스를 조정하여 작동합니다.일단 놓아두면 컨트롤러에 자신만의 데이터 소스에 변경 사항을 커밋 할 수 있습니다.

나는 그것이 대부분의 유스 케이스를 위해 일하는 것이 조금 더 간단하다고 생각한다.여전히 진행중인 일이지만,이를 수행하는 또 다른 방법.가장 맞춤형 UICollectionViewLayouts에이를 쉽게 통합하기 쉽게 찾을 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top