2017-05-06 15 views
1

我有一個UIScrollView,它包含許多可拖動的UIViews,它們具有不同的大小,主要是方形的。這些UIViews捕捉到屏幕上的6列網格。通過移動另一個UIView來影響所有UIViews

UIView(假設其尺寸爲132x132)卡入位置與另一UIView's幀與所述第一UIView幀相交,第二應該移動低於第一,無論是通過全或第一高度的一半UIView(取決於UIViews相交的位置)。我通過使用CGRectIntersectsRect以及CGRectGetMaXYCGRectGetMinY來計算所需的移動距離。

但是,在已經受到影響的UIView下面還可能有第三個甚至更多的UIViews,這些UIView也可能需要移動。在這裏,我的問題是,我不能夠

一)獲得所有受影響UIViews以正確的順序移動的UIView(不搶購UIView)(由他們的Y原點訂購)
B)移動UIViews下面,基於UIView僅限於它們,不受UIView的影響(即使移動距離可能相同)。

我的當前的嘗試是得到一個UIView該貼緊,加入UIView和所需的移動距離爲字典到一個數組,然後使用遞歸加入其它UIViews下方之後與移動UIView相交。但有時候,UIViews由於它們在視圖層次結構中的順序而被錯誤移動,或者甚至根本不移動它們。

下面是一個例子:與框架

  • 的UIView A = 0 0; 269 132
  • 的UIView乙與幀= 0 205.5; 63.5 63.5
  • 的UIView下用幀= 137 137; 132 132卡入0 0; 132 132
  • 邊界間距爲5像素

UIView C卡入到位,UIView A應該移動到0 137; 269 132,因爲所需的移動距離是UIView C +邊框間距的整個高度。但移動UIView A到其新位置也影響UIView B,然後移動到0 274; 63.5 63.5,高度的一半UIView A +邊框間距,刪除UIView A和B之間的空間。

下面是另一個例子:與框架

  • 的UIView A = 0 0; 269 132
  • 的UIView乙與幀= 0 205.5; 63.5 63.5
  • 的UIView下用幀= 0 274; 269 269卡入0 68.5; 269 269

UIView C移動到位,UIView A移動到0 274; 269 132,然後影響UIView B並將其移動到0 411; 63.5 63.5,刪除之前在UIView A和B之間的空間。

+0

在你的第一個例子中,你的意思是說你的UIView A的幀大小從269,132變爲132,132?那是對的嗎?我假設那些是框架的寬度/高度。 –

+0

在第二個例子中,UIView C移動到位後,UIView A移動,那麼C和A重疊? –

+0

UIView大小不變。這是一個錯誤,我修復了它。在第二個示例中,當UIView C移動到位時,它與A和B重疊,因此需要向下移動。 –

回答

0

您可能需要設置先進先出堆棧。該算法將是這個樣子(無效的OBJ-C代碼!):

move viewC 
[stack addObject: viewC] 
while stack.isEmpty == false { 
    current = stack[0] 
    remove current from stack 
    for view in allViews { 
     if view != current and view needs to move because of current's position { 
      [stack addObject: view] 
      move view to correct position 
     } 
    } 
} 

以上將先移動viewC到新的位置,然後通過所有比viewC的意見,其他掃描,並把它們搬出如果有必要,從視圖C開始。移動的每個視圖都將被添加到堆棧中。

然後,它會去通過被感動,因爲viewC的新位置的所有意見,並檢查是否進行了尚未轉移的任何觀點都被感動,因爲那鑑於的新位置。等等...

- 編輯 -

經過反思,我不認爲你需要跟蹤已訪問過的意見。我更新了算法以刪除該步驟。

+0

以上是Dijkstra的路徑查找算法的變體,但是用於視圖移動。 –

+0

這個算法運行得很好。遠遠勝過我嘗試過的任何事情。非常感謝您的幫助! –

1

這是我使用的基於Daniel T.的答案和他的僞代碼的Objective-C實現。我接受了他的答案,因爲他提供了實際的解決方案這僅供參考。

- (void)moveAffectedViewsForView:(UIView*)movedView { 
    NSMutableArray* stack = [NSMutableArray new]; 
    [stack addObject:movedView]; 

    while ([stack count] > 0) { 
     UIView* current = [stack objectAtIndex:0]; 
     [stack removeObject:current]; 

     for (UIView* view in [self subviews]) { 
      if (view != current && CGRectIntersectsRect(current.frame, view.frame)) { 
       [stack addObject:view]; 

       CGFloat moveDistance = (CGRectGetMaxY(current.frame) - CGRectGetMinY(view.frame)) + 5; 
       [view setFrame:CGRectOffset(view.frame, 0, moveDistance)]; 
      } 
     } 
    } 
} 
相關問題