2017-05-06 12 views
1

UIScrollViewには、多くの場合、正方形のサイズが異なる多くのドラッグ可能なUIViewsが含まれています。これらのUIViewsは、画面上の6列グリッドにスナップします。上の別のUIViewを動かすことで影響を受けるすべてのUIViewを取得

完全または最初の半分の高さのいずれかによって、UIView(のは、その大きさが132x132であるとしましょう)が所定の位置に固定し、別のUIView'sフレームは、第が最初に下に移動するようになっている、第一UIViewフレームと交差する場合UIViewUIViewsのどこが交差しているかによって異なります)。私は、CGRectIntersectsRectと、CGRectGetMaXYCGRectGetMinYを使って、必要な移動距離を計算することで、この作業を行っています。

しかし、移動しなければならない可能性のある既に影響を受けたUIViewの下には、さらに3番目またはそれ以上の可能性があります。UIViewsここでの私の問題は、に基づいてUIViewsを移動する彼らのY原点で注文正しい順序()
b)の中(UIViewスナップません)私は

にはできませんよということa)すべての移動UIView以下UIViewsに影響を与えますですUIViewは、UIViewの影響を受けずに(移動距離は同じかもしれませんが)、所定の位置にスナップします。

私の現在の試みは、スナップアレイに辞書としてUIView、必要な移動距離を添加し、次に再帰を使用して、その下に他のUIViewsを添加した後、移動UIViewと交差1 UIViewを得ることです。ただし、UIViewsがビュー階層内での順序のために正しく移動されない場合や、まったく移動されない場合もあります。フレームと

  • のUIView A =フレームと0 0; 269 132
  • のUIView B =ボーダー間隔が5である
  • 0 0; 132 132に収まるフレームと0 205.5; 63.5 63.5
  • のUIView C = 137 137; 132 132:ここ

    は一例で画素

UIView Cが適切な位置にスナップすると、UIView Aは0 137; 269 132に移動することになっています。これは、必要な移動距離がUIView C +のボーダー間隔の最大高さであるためです。しかし、UIView Aをその新しい位置に移動すると、UIView Bにも影響があり、それはUIViewAの半分の高さと境界の間隔になり、UIView AとBの間のスペースが削除されます。ここ

は別の例である:0 68.5; 269 269

に収まるフレームとフレーム= 0 205.5; 63.5 63.5

  • のUIView C = 0 274; 269 269のフレーム=
  • 0 0; 269 132
  • のUIView Bと

    • のUIView A UIView Cが移動し、UIView Aが0 274; 269 132に移動し、次にに影響しますBを入力し、0 411; 63.5 63.5に移動して、前にUIView AとBの間のスペースを削除します。

  • +0

    最初の例では、UIView Aのフレームサイズが269,132から132,132に変更されていますか?あれは正しいですか?私はそれらがフレームの幅/高さであると仮定しています。 –

    +0

    2番目の例では、UIView Cが動いてUIView Aが動いた後、CとAが重なっていますか? –

    +0

    UIViewのサイズは変更されていません。それは間違いで、私はそれを修正しました。 2番目の例では、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)]; 
          } 
         } 
        } 
    }