วิธี จำกัด การจัดลำดับแถว UITableView ใหม่เป็นส่วน


121

ฉันโดนหัวของฉันเหนือสิ่งนี้และ Google ก็ไม่ได้ทำอะไรเลย ในที่สุดฉันก็ทำมันออกมาและคิดว่าฉันจะเขียนมันไว้ที่นี่เพื่อประโยชน์ของคนต่อไป

คุณมีUITableViewหลายส่วน แต่ละส่วนเป็นเนื้อเดียวกัน แต่ตารางโดยรวมมีความแตกต่างกัน ดังนั้นคุณอาจต้องการอนุญาตให้จัดลำดับแถวใหม่ภายในส่วน แต่ไม่สามารถเรียงลำดับข้ามส่วนได้ บางทีคุณแค่ต้องการให้ส่วนหนึ่งสามารถจัดเรียงใหม่ได้เลย (นั่นคือกรณีของฉัน) หากคุณกำลังมองหาเหมือนที่ฉันเป็นUITableViewDataSourceDelegateคุณจะไม่พบการแจ้งเตือนเมื่อกำลังจะให้คุณย้ายแถวระหว่างส่วนต่างๆ คุณจะได้รับหนึ่งเมื่อมันเริ่มย้ายแถว (ซึ่งก็ใช้ได้) และเมื่อมันย้ายไปแล้วและคุณจะมีโอกาสซิงค์กับสิ่งของภายในของคุณ ไม่เป็นประโยชน์

แล้วคุณจะป้องกันการสั่งซื้อซ้ำระหว่างส่วนต่างๆได้อย่างไร?

ฉันจะโพสต์สิ่งที่ฉันทำเป็นคำตอบแยกต่างหากปล่อยให้คนอื่นโพสต์คำตอบที่ดีกว่านี้!


1
คุณหมายถึงการแจ้งเตือนใดเมื่อคุณพูดว่า "คุณได้รับเมื่อเริ่มย้ายแถว" ฉันไม่เห็นมัน แต่ฉันหวังว่าจะแยกแยะได้เมื่อการเรียงลำดับเซลล์เริ่มต้นขึ้น
TomSwift

คำตอบ:


181

การใช้งานนี้จะป้องกันไม่ให้มีการสั่งซื้อซ้ำนอกส่วนเดิมเช่นคำตอบของ Phil แต่จะสแน็ปบันทึกไปยังแถวแรกหรือแถวสุดท้ายของส่วนด้วยขึ้นอยู่กับว่าการลากไปที่ใดแทนที่จะเป็นจุดเริ่มต้น

- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
  if (sourceIndexPath.section != proposedDestinationIndexPath.section) {
    NSInteger row = 0;
    if (sourceIndexPath.section < proposedDestinationIndexPath.section) {
      row = [tableView numberOfRowsInSection:sourceIndexPath.section] - 1;
    }
    return [NSIndexPath indexPathForRow:row inSection:sourceIndexPath.section];     
  }

  return proposedDestinationIndexPath;
}

มีวิธีป้องกันไม่ให้ตารางเลื่อนอัตโนมัติ (ขณะลากเซลล์) นอกส่วนที่อนุญาตหรือไม่
Palimondo

1
ใน Xamarin วิธีการห่อหุ้มUIKit.UITableViewController.CustomizeMoveTargetสำหรับใครก็ตามที่สงสัย
bunkerdive

74

ง่ายพอจริงๆ

UITableViewDelegate มีวิธีการ:


tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:

สิ่งนี้ถูกเรียกในขณะที่ผู้ใช้วางเมาส์เหนือจุดที่อาจเกิดขึ้น คุณมีโอกาสที่จะพูดว่า "ไม่! อย่าทำหล่นที่นั่น! วางตรงนี้แทน" คุณสามารถส่งคืนเส้นทางดัชนีอื่นไปยังเส้นทางที่เสนอ

ทั้งหมดที่ฉันทำคือตรวจสอบว่าดัชนีส่วนนั้นตรงกันหรือไม่ หากทำได้ดีให้ส่งคืนเส้นทางที่เสนอ ถ้าไม่ให้ส่งคืนเส้นทางต้นทาง นอกจากนี้ยังช่วยป้องกันไม่ให้แถวในส่วนอื่น ๆ แม้จะเคลื่อนออกไปในขณะที่คุณลาก - และแถวที่ลากจะกลับไปที่ตำแหน่งเดิมของคุณที่พยายามย้ายไปยังส่วนอื่น


- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
    if( sourceIndexPath.section != proposedDestinationIndexPath.section )
    {
        return sourceIndexPath;
    }
    else
    {
        return proposedDestinationIndexPath;
    }
}

การทำเช่นนี้ทำให้เกิดข้อบกพร่องในการแสดงผลที่แปลกประหลาดอย่างแท้จริงเกิดขึ้นในการตั้งค่าของฉันและมันแตกต่างจากโค้ดตัวอย่างของ apple ในการทำเช่นนี้ FWIW! ไม่ได้บอกว่าผิด แต่ฉันสงสัยว่ามันซับซ้อนกว่านี้จริงหรือ
Billy Gray

ฉันสามารถลากแถวในส่วนอื่น ๆ ได้แม้ว่าแถวนั้นจะไม่ได้รับการตั้งค่าก็ตาม แต่จะปรากฏให้คนอื่นเห็นได้เมื่อใด? ความคิดใด ๆ
แซนดี้

27

คำตอบของ Jason รุ่นที่รวดเร็วสำหรับคุณคนขี้เกียจ:

Swift 3, 4 และ 5

override func tableView(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath {
    if sourceIndexPath.section != proposedDestinationIndexPath.section {
        var row = 0
        if sourceIndexPath.section < proposedDestinationIndexPath.section {
            row = self.tableView(tableView, numberOfRowsInSection: sourceIndexPath.section) - 1
        }
        return IndexPath(row: row, section: sourceIndexPath.section)
    }
    return proposedDestinationIndexPath
}

Swift 1 & 2

override func tableView(tableView: UITableView, targetIndexPathForMoveFromRowAtIndexPath sourceIndexPath: NSIndexPath, toProposedIndexPath proposedDestinationIndexPath: NSIndexPath) -> NSIndexPath {
    if sourceIndexPath.section != proposedDestinationIndexPath.section {
        var row = 0
        if sourceIndexPath.section < proposedDestinationIndexPath.section {
            row = self.tableView(tableView, numberOfRowsInSection: sourceIndexPath.section) - 1
        }
        return NSIndexPath(forRow: row, inSection: sourceIndexPath.section)
    }
    return proposedDestinationIndexPath
}

7

คุณสามารถป้องกันการเคลื่อนที่ของแถวระหว่างส่วนโดยใช้วิธีการด้านล่าง อย่าให้มีการเคลื่อนไหวใด ๆ ระหว่างส่วน คุณยังสามารถควบคุมการเคลื่อนไหวของแถวเฉพาะภายในส่วนได้อีกด้วย เช่นแถวสุดท้ายในส่วน

นี่คือตัวอย่าง:

- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {

    // Do not allow any movement between section
    if ( sourceIndexPath.section != proposedDestinationIndexPath.section) {
        return sourceIndexPath;
    }
    // You can even control the movement of specific row within a section. e.g last row in a     Section

    // Check if we have selected the last row in section
    if (sourceIndexPath.row < sourceIndexPath.length) {
        return proposedDestinationIndexPath;
    } 
    else {
        return sourceIndexPath;
    }
}

7

Swift 3:

override func tableView(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath {
    if sourceIndexPath.section != proposedDestinationIndexPath.section {
        var row = 0
        if sourceIndexPath.section < proposedDestinationIndexPath.section {
            row = self.tableView(tableView, numberOfRowsInSection: sourceIndexPath.section) - 1
        }
        return IndexPath(row: row, section: sourceIndexPath.section)
    }
    return proposedDestinationIndexPath
}

3

กว่า @Jason Harwig รหัสด้านล่างทำงานได้อย่างถูกต้อง

- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
    {
      if (sourceIndexPath.section != proposedDestinationIndexPath.section) {
        NSInteger row = 0;
        if (sourceIndexPath.section < proposedDestinationIndexPath.section) {
          row = [tableView numberOfRowsInSection:sourceIndexPath.section] - 1;
        }
        return [NSIndexPath indexPathForRow:row inSection:sourceIndexPath.section];     
      }

      return proposedDestinationIndexPath;
    }

1

เพื่อไม่ให้เปลี่ยนตำแหน่งระหว่างส่วนSwift3

override func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
    if originalIndexPath.section != proposedIndexPath.section
    {
        return originalIndexPath
    }
    else
    {
        return proposedIndexPath
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.