iPhone: ซ่อนแถบค้นหา UITableView ตามค่าเริ่มต้น


85

ฉันใช้ตัวสร้างส่วนต่อประสานเพื่อสร้างมุมมองตารางซึ่งฉันได้เพิ่มแถบค้นหาของไลบรารีและตัวควบคุมการแสดงผลการค้นหาเพื่อเพิ่มฟังก์ชันการค้นหา อย่างไรก็ตาม IB ตั้งค่าเพื่อให้มองเห็นแถบที่ด้านบนของหน้าจอเมื่อมุมมองปรากฏขึ้นครั้งแรก

ฉันต้องการทราบวิธีซ่อนแถบค้นหาตามค่าเริ่มต้น แต่ยังคงเลื่อนได้ด้วยมุมมองตาราง (ดูตัวอย่างแอปพลิเคชัน Mail ของ Apple) ฉันพยายามโทรscrollRectToVisible:animated:เข้าviewDidLoadเพื่อเลื่อนมุมมองตารางลง แต่ก็ไม่เป็นประโยชน์ วิธีใดที่ดีที่สุดในการซ่อนแถบค้นหาตามค่าเริ่มต้น

คำตอบ:


116

ขั้นแรกตรวจสอบให้แน่ใจว่าได้เพิ่ม UISearchBar ลงใน tableHeaderView ของ UITableView เพื่อให้เลื่อนไปพร้อมกับเนื้อหาของตารางและไม่ได้ถูกกำหนดไว้ที่ด้านบนสุดของมุมมอง

แถบค้นหาไม่นับเป็นแถวในมุมมองตารางดังนั้นหากคุณเลื่อนด้านบนสุดของมุมมองตารางไปที่แถวแรกแถบค้นหาจะ 'ซ่อน' แถบค้นหา:

[yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];

หรือใน Swift:

yourTableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: false)

ตรวจสอบให้แน่ใจว่าไม่ได้เลื่อน tableview ก่อนที่จะมีข้อมูล ( scrollToRowAtIndexPathจะเพิ่มข้อยกเว้นหาก indexPath ที่กำหนดไม่ชี้ไปยังแถวที่ถูกต้อง (เช่นถ้า tableview ว่างเปล่า))


12
อันที่จริงฉันได้รับปัญหาที่มุมมองตารางจะไม่เลื่อนหากมีแถวไม่เพียงพอที่จะเต็มหน้าจอ - ในตารางที่มีแถวหนึ่งหรือสองแถวรหัสนี้จะไม่ทำอะไรเลย เป็นพฤติกรรมที่คาดหวังหรือไม่? ฉันสามารถหลีกเลี่ยงมันได้หรือไม่?
ทิม

18
ฉันพบวิธี: แทนที่จะเลื่อนไปยังเส้นทางดัชนีเปลี่ยนการชดเชยเนื้อหาของมุมมองการเลื่อนของตารางเป็น CGRect ที่ 0.0, 44.0
ทิม

107
ทิมนั่นคือวิธีที่จะไป! ฉันใช้ self.tableView.contentOffset = CGPointMake (0, self.searchDisplayController.searchBar.frame.size.height);
Joe D'Andrea

1
Btw - เมื่อฉันใส่รหัสนี้หลังจากเรียกไปที่ [tableView reloadData] ซึ่งทำให้ตารางของฉันเปลี่ยนจาก 2 แถวไปจนถึงแถวที่เพียงพอที่จะให้เลื่อนได้ตามปกติฉันพบว่าการใช้เมธอด contentOffset ทำให้การแสดงกระตุกและการซ่อนการค้นหา ในขณะที่ใช้เมธอด scrollToRowAtIndexPath ไม่มีอาการกระตุกเหมือนกัน
Chris R

1
นี่เป็นวิธีเดียวที่ดีที่สุดที่ใช้ได้ในทุกสถานการณ์ การตั้งค่าcontentOffsetด้วยค่าใดก็ตามจะเสียหายหากคุณใช้เค้าโครงตัวควบคุมมุมมองที่ซับซ้อน ฉันไม่แนะนำมัน
eonil

45

อย่าเพิ่ม UISearchBar เป็นมุมมองย่อยของ UITableView ซึ่งไม่จำเป็น

UITableView มีคุณสมบัติ tableHeaderView ที่เหมาะสำหรับสิ่งนี้:

- (void) viewDidLoad {
    [super viewDidLoad]; 
    self.searchBar = [[[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)] autorelease];
    self.searchBar.showsCancelButton = YES;    
    self.searchBar.delegate = self;
    self.tableView.tableHeaderView = self.searchBar;     
}

หากคุณไม่ต้องการเห็นโดยค่าเริ่มต้น:

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.tableView setContentOffset:CGPointMake(0, 44)];
}

ฉันยังได้รับปุ่มยกเลิกเพื่อซ่อนอีกครั้ง .... (และนำแป้นพิมพ์ออก)

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    [self.tableView setContentOffset:CGPointMake(0, 44) animated:YES];
    [self.searchBar resignFirstResponder];
}

สำหรับฉันนี่เป็นทางออกเดียวที่สร้างการใช้งาน UISearchBar ที่ซ่อนอยู่ซึ่งให้ความรู้สึกว่าสอดคล้องกับ HIG วิธีแก้ปัญหาอื่น ๆ ที่ "ติดอยู่" ที่ด้านบนของมุมมองตารางรู้สึกไม่เป็นธรรมชาติ
kurtzmarc

1
วิธีนี้ได้ผลดีที่สุด นี่น่าจะเป็นคำตอบในความคิดของฉัน
darwindeeds

วิธีนี้ดี (+1) อย่างไรก็ตาม tableView ไม่ได้ซ่อนแถบค้นหาอย่างถูกต้องในบางกรณี (ในกรณีของฉัน: เมื่อตัวควบคุม tableview ถูกผลักกลับจากตัวควบคุมมุมมองอื่น) มีคำถามเกี่ยวกับปัญหานี้: stackoverflow.com/questions/15222186/…ฉันคิดว่าคำตอบที่ให้ไว้ของคำถามนี้ไม่ค่อยดีนัก @bandejapaisa คุณมีความคิดอย่างไร?
Brian

3
สิ่งนี้ใช้งานได้ดีสำหรับฉันแม้ว่าจะใช้ฮาร์ดโค้ด 44 ตลอดฉันขอแนะนำให้ใช้ self.tableView.tableHeaderView.frame.size.height ใน viewWillAppear เพื่ออนุญาตให้มีการเปลี่ยนแปลงที่ Apple อาจทำในอนาคตกับความสูงของแถบค้นหา
John Stephen

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

25

contentOffset ถูกบันทึกไว้ในความคิดเห็นของ Tim และ Joe D'Andrea แต่จะขยายได้เล็กน้อยโดยการเพิ่มภาพเคลื่อนไหวเพื่อซ่อนแถบค้นหา ฉันสังเกตว่ามันเป็นเรื่องที่คาดไม่ถึงเล็กน้อยที่แถบค้นหาจะหายไป

การอัปเดตเล็กน้อยสำหรับผู้ที่ต้องการกำหนดเป้าหมายเป็น iOS 4.0 ขึ้นไปลองสิ่งนี้:

[UIView animateWithDuration:0.4 animations:^{
    self.tableView.contentOffset = CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height);
 } completion:nil];

คำตอบก่อนหน้า:

[UIView beginAnimations:@"hidesearchbar" context:nil];
[UIView setAnimationDuration:0.4];
[UIView setAnimationBeginsFromCurrentState:YES];

self.tableView.contentOffset = CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height);

[UIView commitAnimations];


9
ฉันพบว่าภาพเคลื่อนไหวเป็นกุญแจสำคัญในการแก้ปัญหานี้ การพยายามตั้งค่าชดเชยเนื้อหาโดยไม่มีภาพเคลื่อนไหวจะดูเหมือนว่าไม่ต้องทำอะไรเลย อย่างไรก็ตามแทนที่จะใช้วิธีการสร้างภาพเคลื่อนไหว (หรือบล็อก) ในตัวอย่างนี้ฉันพบว่าการเรียก [self.tableView setContentOffset: CGPointMake (0,44) animated: TRUE] ทำงานได้ดีเพียงพอ
quickthyme

ดูเหมือนว่าจะไม่ทำงานเลยหากไม่มีภาพเคลื่อนไหว @quickthyme ได้ทำการสังเกตเช่นเดียวกัน
Thilo

5
ผมเคยประสบความสำเร็จกับเรื่องนี้โดยไม่จำเป็นต้องเคลื่อนไหวถ้าคุณใช้มันในแทนviewDidAppear: viewDidLoad
wbyoung

8

มีคำตอบมากมายสำหรับวิธีแก้ปัญหานี้ แต่ไม่มีคำตอบใดที่ได้ผลสำหรับฉัน

นี้ทำงานได้อย่างสมบูรณ์ ไม่มีภาพเคลื่อนไหวและเสร็จสิ้น-viewDidLoad

 - (void)viewDidLoad {
     [super viewDidLoad];
     self.tableView.contentOffset = CGPointMake(0,  self.searchBar.frame.size.height - self.tableView.contentOffset.y);
 }

บันทึก:

โค้ดจะถือว่าคุณมีสิ่งsearchBar @propertyที่เชื่อมโยงกับแถบค้นหา หากไม่เป็นเช่นนั้นคุณสามารถใช้self.searchDisplayController.searchBarแทนได้


นี่เป็นคนเดียวที่เหมาะกับฉัน! แต่มันจะยกเลิก viewdidload เท่านั้น ... ดังนั้นครั้งแรกที่มันซ่อน แต่จากนั้นจะไม่ซ่อนอีกต่อไปในขณะที่แอปกำลังทำงาน และฉันลองใส่ในมุมมองจะปรากฏและดูปรากฏขึ้น แต่ทำงานผิดพลาด ขอบคุณ!
fguespe

@fguespe ที่แปลก .. viewDidLoad ควรถูกเรียกทุกครั้งที่มีการสร้างอินสแตนซ์มุมมอง ไม่เคยเกิดขึ้นกับฉันเลยที่ UISearchBar สามารถมองเห็นได้หลังจากกลับมาจากมุมมองอื่น
Matej

ฉันใช้แอปพลิเคชันแบบแท็บ อาจจะเป็นอย่างนั้น?
fguespe

@fguespe ฉันเห็นว่านั่นอาจเป็นปัญหาอืม น่าเสียดายที่ฉันไม่แน่ใจว่าคุณจะแก้ปัญหานั้นอย่างไรหาก-viewWillAppearไม่ได้ผล .. มันถูกเรียกเมื่อตัวควบคุมแท็บเปลี่ยนเป็นมุมมองหรือไม่?
Matej

viewwillappear และ viewdidappear ถูกเรียก แต่ฉันลองใช้ทั้งสองอย่างแล้วมุมมองก็เหมือนหักล้างผิด ไม่ส่งคืนผลลัพธ์ที่คาดหวัง ฉันหมายความว่ามีบางอย่างทำ แต่มันไม่ดี
fguespe

7

สำหรับ Swift 3+

ฉันทำอย่างนี้:

ประกาศสิ่งนี้var:

    var searchController = UISearchController()

และในviewDidLoad()วิธีการ

    searchController = UISearchController(searchResultsController: nil)
    searchController.searchResultsUpdater = self
    searchController.hidesNavigationBarDuringPresentation = false
    searchController.dimsBackgroundDuringPresentation = true
    searchController.searchBar.placeholder = NSLocalizedString("Search", comment: "")
    definesPresentationContext = true
    tableView.tableHeaderView = searchController.searchBar

    tableView.contentOffset = CGPoint(x: 0, y: searchController.searchBar.frame.size.height)

5

เป้าหมายของฉันคือซ่อนแถบค้นหาที่เพิ่มลงใน tableHeaderView ของสไตล์ TableView ธรรมดาในสตอรีบอร์ดเมื่อโหลดตัวควบคุมมุมมองและแสดงแถบเมื่อผู้ใช้เลื่อนลงที่ด้านบนของ UITableView ดังนั้นฉันใช้Swiftและได้เพิ่มส่วนขยาย:

extension UITableView {
    func hideSearchBar() {
        if let bar = self.tableHeaderView as? UISearchBar {
            let height = CGRectGetHeight(bar.frame)
            let offset = self.contentOffset.y
            if offset < height {
                self.contentOffset = CGPointMake(0, height)
            }
        }
    }
}

ในviewDidLoad ()เพียงแค่โทร:

self.tableView.hideSearchBar()

5

โซลูชันที่มีอยู่ทั้งหมดไม่ได้ผลสำหรับฉันใน iOS 8 เมื่อมีแถวไม่เพียงพอที่จะเติม tableView เนื่องจาก iOS จะปรับสิ่งที่ใส่เข้าไปโดยอัตโนมัติในสถานการณ์นี้ (คำตอบที่มีอยู่จะดีเมื่อมีแถวเพียงพอ)

หลังจากเสียเวลาไป 6 ชั่วโมงกับปัญหานี้ในที่สุดฉันก็ได้วิธีแก้ปัญหานี้

ในระยะสั้นคุณต้องแทรกเซลล์ว่างลงใน tableView หากมีเซลล์ไม่เพียงพอดังนั้นขนาดเนื้อหาของ tableView จึงใหญ่พอที่ iOS จะไม่ปรับสิ่งที่ใส่เข้าไปให้คุณ

นี่คือวิธีที่ฉันทำใน Swift:

1. ) ประกาศตัวแปรminimumCellNumเป็นคุณสมบัติคลาส

var minimumCellNum: Int?

2. ) คำนวณminimumCellNumและตั้งค่าtableView.contentOffsetในviewWillAppear

let screenHeight = Int(UIScreen.mainScreen().bounds.height)

// 101 = Height of Status Bar(20) + Height of Navigation Bar(44) + Height of Tab Bar(49)
// you may need to subtract the height of other custom views from the screenHeight. For example, the height of your section headers.
self.minimumCellNum = (screenHeight - 103 - heightOfOtherCustomView) / heightOfYourCell
self.tableView.contentOffset = CGPointMake(0, 44)

3. ) ใน tableView(tableView: UITableView, numberOfRowsInSection section: Int))

let numOfYourRows = YOUR LOGIC
if numOfYourRows > minimumCellNum {
    return numOfYourRows
} else {
    return minimumCellNum!
}

4. ) ลงทะเบียนเซลล์ว่างซึ่งมีselectionแอตทริบิวต์อยู่Noneบนกระดานเรื่องราวและในtableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)

if indexPath.row < numOfYourRows {
    return YOUR CUSTOM CELL
} else {
    let cell = tableView.dequeueReusableCellWithIdentifier("EmptyCell", forIndexPath: indexPath) as! UITableViewCell
    return cell
}

5. ) ใน tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)

if tableView == self.tableView {
    if numOfYourRows < (indexPath.row + 1) {
        return
    }
    YOUR LOGIC OF SELECTING A CELL
}

นี่ไม่ใช่วิธีแก้ปัญหาที่สมบูรณ์แบบ แต่เป็นวิธีแก้ปัญหาเดียวที่ใช้ได้กับฉันบน iOS 8 ฉันอยากทราบว่ามีวิธีแก้ปัญหาที่ดีกว่านี้หรือไม่


ฉันต้องทำสิ่งนี้สำหรับ iOS 11 การตั้งค่า contentOffset เพียงอย่างเดียวใช้ได้กับ iOS 9/10 สำหรับเซลล์ 0 เซลล์ขึ้นไปและมันยังทำงานบน iOS 11 สำหรับเซลล์ 8+ สิ่งที่น้อยกว่าต้องการโซลูชันนี้ มีเหตุผลว่าทำไม?
Tony

ฉันคิดว่าย่อหน้าแรกของโพสต์นี้อธิบายว่าทำไม
Brian

ฉันเข้าใจย่อหน้าแรก แต่ก็ยังแปลกที่มีเพียง "เสีย" บน iOS 11 สำหรับฉัน ฉันคาดว่าจะมีพฤติกรรมคล้ายกันสำหรับ iOS 9, 10 และ 11 เมื่อจำนวนเซลล์เท่ากัน (น้อยกว่าเพียงพอ) ขอบคุณอีกครั้งและขออภัยที่นำโพสต์เก่ามาโพสต์!
Tony

4

ข้างต้นไม่ได้ผลสำหรับฉันดังนั้นในกรณีที่มีคนจะมีปัญหาเดียวกัน

ฉันได้searchBarตั้งค่าเป็นtableHeaderViewตารางที่จัดกลุ่มบน iOS7 ในviewDidLoadฉันมีtableView.contentOffset = CGPointMake(0, 44);ที่จะให้searchBarในตอนแรก "ซ่อน" เมื่อผู้ใช้เลื่อนลงsearchBarจะถูกเลื่อนลง

เป้าหมาย:ซ่อนแถบค้นหาเมื่อกดปุ่มยกเลิก

ใน searchBarCancelButtonClicked(searchBar: UISearchBar!)

ไม่ได้ผล: [yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; tableView เลื่อนขึ้นมากเกินไปส่งผลให้แถว 0 อยู่ด้านหลัง toolBar

สิ่งนี้ไม่ได้ผล: tableView.ContentOffset = CGPointMake(0, 44) - ไม่มีอะไรเกิดขึ้น

สิ่งนี้ไม่ได้ผล: tableView.ContentOffset = CGPointMake(0, searchBar.frame.size.height) - ไม่มีอะไรเกิดขึ้น

ไม่ได้ผล: tableView.setContentOffset(CGPointMake(0, 44), animated: true); อีกครั้ง tableView เลื่อนขึ้นมากเกินไปส่งผลให้แถว 0 อยู่ด้านหลัง toolBar

สิ่งนี้ใช้ได้ผลบางส่วน: tableView.setContentOffset(CGPointMake(0, 0)แต่titleForHeaderInSectionกำลังอยู่เบื้องหลัง toolBar

ทำงานนี้: tableView.setContentOffset(CGPointMake(0, -20)

ดูเหมือนจะไม่เป็นตรรกะ แต่มีเพียง -20 เท่านั้นที่ขยับขึ้นเพื่อแก้ไขตำแหน่ง


คุณไม่ควรฮาร์ดโค้ดคะแนนของคุณจริงๆทำไมคุณไม่ใช้CGRectGetHeight(searchBar.bounds)?
Zorayr

ฉันเดาว่าคุณต้องทำใน viewDidLoad () / init () ซึ่งไม่มีการตั้งค่าเฟรมเพื่อให้คุณได้รับความสูงของแถบค้นหา คุณควรลองด้วย viewDidLayoutSubviews ()
Kaushil Ruparelia

หากการโหลด tableView ยังไม่เสร็จสิ้นจะไม่มีContentOffsetวิธีแก้ปัญหาใด ๆ
Maor

4

การชดเชยเนื้อหาเป็นวิธีที่จะไป แต่มันไม่ได้ผล 100% ของเวลา

จะไม่ทำงานหากตั้งค่าestimatedRowHeightเป็นตัวเลขคงที่ ไม่รู้งานรอบยัง ฉันได้สร้างโครงการที่แสดงปัญหาและได้สร้างเรดาร์กับ Apple แล้ว

ตรวจสอบโครงการหากคุณต้องการตัวอย่างวิธีการตั้งค่าทั้งหมดอย่างรวดเร็ว


1
ขอขอบคุณ! นี่คือสิ่งที่ฉันกำลังมองหา คุณต้องไปทางขึ้น
user2387149

3

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

[yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; // crashes if no rows/data

ดังนั้นให้เพิ่มโค้ดบรรทัดนี้แทน:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    [yourTableView setContentOffset:CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height)];
}

2

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

สิ่งเดียวที่ใช้ได้:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.tableView.contentOffset = (CGPoint){.y =  self.tableView.contentOffset.y + self.searchController.searchBar.frame.size.height};
}

ทางออกที่ดีสำหรับปัญหาออฟเซ็ต ใช้ได้ผลกับฉันเมื่อใช้ UINavigationController
Andreas Kraft

1
วิธีแก้ปัญหาไม่ได้ผลเมื่อจำนวนแถวไม่ครอบคลุมทั้งหน้าจอคุณจะรู้วิธีแก้ปัญหานี้หรือไม่?
Zorayr

ไม่แน่ใจว่าฉันเข้าใจเรื่องนี้อย่างสมบูรณ์ วิธีนี้ใช้ได้ผลกับฉันเมื่อมีแถวในตารางเพียงไม่กี่แถว อย่างไรก็ตามฉันใช้สิ่งต่อไปนี้: self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];.
p0lAris

2

scrollToRowAtIndexPathวิธีการที่ทำให้เกิดความผิดพลาดถ้ามีศูนย์แถวในตาราง

UITableView เป็นเพียงมุมมองแบบเลื่อนดังนั้นคุณสามารถเปลี่ยนออฟเซ็ตเนื้อหาได้

สิ่งนี้จะตรวจสอบว่าคุณมีอะไรเป็น tableHeaderView ของคุณและสมมติว่าคุณเลื่อนเพื่อซ่อน

    if let searchHeight = tableView.tableHeaderView?.frame.height {
        tableView.setContentOffset(CGPoint.init(x: 0, y:searchHeight ), animated: false)
    }

1

ฉันพบว่าแอป "Notes" ไม่สามารถค้นหารายการเมื่อ tableView ว่างเปล่า ดังนั้นฉันคิดว่ามันใช้แค่-(void)addSubview:(UIView *)viewเพิ่มตารางเปล่าในตอนแรก เมื่อคุณเพิ่มรายการในอาร์เรย์แหล่งข้อมูลมันจะเรียกใช้โค้ดอีกชิ้นเพื่อโหลด tableView

ดังนั้นทางออกของฉันคือ:

if([self.arrayList count] > 0)
{
     [self.tableView reloadData];     //use jdandrea's code to scroll view when cell==nil in cellForRowAtIndexPath
     self.tableView.scrollEnabled = YES;
}
else
{
     tableBlank = [[UITableView alloc]initWithFrame:CGRectMake(0,0,320,416) style:UITableViewStylePlain] autorelease];
     tableBlank.delegate = self;
     tableBlank.dataSource = self;
     [self.view addSubview:tableBlank];
}

หวังว่านี่จะช่วยได้ :-)


1

เปลี่ยนขอบเขตของ tableView ซึ่งสามารถทำได้ภายในviewDidLoadและคุณไม่ต้องกังวลว่าตารางจะว่างหรือไม่ (เพื่อหลีกเลี่ยงข้อยกเว้น)

CGRect newBounds = self.tableView.bounds;
newBounds.origin.y = newBounds.origin.y + self.searchBar.bounds.size.height;
self.tableView.bounds = newBounds;

เมื่อผู้ใช้เลื่อนลงในตารางแล้วแถบค้นหาจะปรากฏขึ้นและทำงานได้ตามปกติ


1

คำตอบอื่น ๆ สำหรับคำถามนี้ไม่ได้ผลเลยสำหรับฉันมีพฤติกรรมแปลก ๆ เมื่อ tableView มี 0 แถวหรือทำให้ตำแหน่งการเลื่อนยุ่งเหยิงเมื่อไปมาระหว่างรายการโฆษณาระดับบนสุดและที่ซ้อนกัน สิ่งนี้ใช้ได้ผลสำหรับฉัน (เป้าหมายคือการซ่อน UISearchBar เมื่อโหลด):

public override func viewWillAppear(animated: Bool) {        
    if self.tableView.contentOffset.y == 0 {
        self.tableView.contentOffset = CGPoint(x: 0.0, y: self.searchBar.frame.size.height) 
    }
}

คำอธิบาย
เมื่อใดก็ตามที่tableViewจะปรากฏขึ้นรหัสนี้จะตรวจสอบว่า UISearchBar มองเห็นได้หรือไม่ (หมายถึงyตำแหน่งของcontentOffsetตำแหน่งเลื่อนหรือที่เรียกว่าคือ0) หากเป็นเช่นนั้นก็เพียงแค่เลื่อนความสูงของแถบค้นหาลงมา หากมองไม่เห็นแถบค้นหา (คิดว่าเป็นรายการที่มีขนาดใหญ่กว่าtableView) ระบบจะไม่พยายามและเลื่อนtableViewเนื่องจากจะทำให้การวางตำแหน่งยุ่งเหยิงเมื่อคุณกลับจากรายการโฆษณาที่ซ้อน

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


1

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

let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)

self.tableView.selectRowAtIndexPath (firstIndexPath, ภาพเคลื่อนไหว: เท็จ, scrollPosition: .Top)

หากคุณใส่รหัสด้านบนในviewDidLoadมันจะทำให้เกิดข้อผิดพลาดเนื่องจาก tableView ยังไม่ได้โหลดดังนั้นคุณต้องวางไว้ในviewDidAppearเพราะ ณ จุดนี้ tableView ได้โหลดแล้ว

ถ้าคุณวางไว้ในviewDidAppearทุกครั้งที่คุณเปิด tableView มันจะเลื่อนขึ้นไปด้านบน

บางทีคุณอาจไม่ต้องการพฤติกรรมนี้หาก tableView ยังคงเปิดอยู่เช่นเมื่อเป็น UITabBar View Controller หรือเมื่อคุณทำต่อแล้วกลับมา หากคุณเพียงต้องการให้มันเลื่อนขึ้นไปด้านบนในการโหลดครั้งแรกคุณสามารถสร้างตัวแปรเพื่อตรวจสอบว่าเป็นการโหลดครั้งแรกหรือไม่เพื่อให้เลื่อนขึ้นไปด้านบนเพียงครั้งเดียว

กำหนดตัวแปรแรกที่เรียกว่า isInitialLoad ในคลาสตัวควบคุมมุมมองและตั้งค่าให้เท่ากับ "จริง":

var isInitialLoad = true

จากนั้นตรวจสอบว่า isInitialLoad เป็นจริงบนviewDidAppear หรือไม่และถ้าเป็นจริงให้เลื่อนไปด้านบนและตั้งค่าตัวแปร isInitialLoad เป็น false:

if isInitialLoad {
            let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)
            self.tableView.selectRowAtIndexPath(firstIndexPath, animated: false, scrollPosition: .Top)

            isInitialLoad = false
        }


1

ฉันลองตั้งค่าออฟเซ็ตเนื้อหาและ scrollToIndexpath แต่ไม่มีอะไรทำงานได้อย่างน่าพอใจ ฉันลบการตั้งค่า tableHeaderView เป็น searchBar ออกจาก viewDidLoad และตั้งค่าใน scrollview delegate ดังต่อไปนี้

override func scrollViewWillBeginDragging(scrollView: UIScrollView) {
    if scrollView.contentOffset.y < 0 && tableView.tableHeaderView == nil {
        tableView.tableHeaderView = searchController.searchBar
        tableView.setContentOffset(CGPointMake(0, scrollView.contentOffset.y + searchController.searchBar.frame.size.height), animated: false)
    }
}

สิ่งนี้ทำงานได้อย่างมีเสน่ห์การตั้งค่าการชดเชยเนื้อหามีไว้เพื่อการเลื่อนที่ราบรื่น


0

อย่าลืมคำนึงถึงแถบสถานะและแถบนำทางด้วย ตัวควบคุมมุมมองตารางของฉันฝังอยู่ในตัวควบคุมการนำทางในviewDidAppear:

tableView.contentOffset = CGPointMake(0, -20) // -20 = 44 (search bar height) - 20 (status bar height) - 44 (navigation bar height)

ทำงานให้ฉัน


0

สำหรับ Swift:

เพียงแค่ทำการชดเชยเนื้อหา tableview ซึ่งควรเป็นค่าความสูงของแถบค้นหา

self.tableView.contentOffset = CGPointMake(0, self.searchController.searchBar.frame.size.height)

0

สวิฟต์ 3

ใช้งานได้กับโต๊ะว่างด้วย!

ในสภาพแวดล้อมของฉันฉันโหลดเซลล์ที่กำหนดเองด้วยไฟล์ xib และ rowHeight ถูกตั้งค่าโดยอัตโนมัติ

    override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        self.tableView.contentOffset = CGPoint(x: 0, y: self.tableView.contentOffset.y + self.searchController.searchBar.bounds.height)
}

0

ฉันมีปัญหาที่คล้ายกัน และวิธีเดียวที่ฉันพบในการแก้ไขปัญหานี้คือใช้ผู้สังเกตการณ์ค่าคีย์บนคุณสมบัติ UITableView contentOffset

หลังจากการดีบักบางอย่างฉันพบว่าปัญหาปรากฏขึ้นหากขนาดเนื้อหาของมุมมองตารางเล็กกว่า tableview ฉันเริ่ม KVO เมื่ออยู่ที่ viewWillAppear และส่งหยุด KVO 0.3 วินาทีหลังจากที่มุมมองปรากฏขึ้น ทุกครั้งที่ contentOffset กลายเป็น 0.0 KVO จะตอบสนองและตั้งค่า contentOffset ตามความสูงของแถบค้นหา ฉันหยุด KVO แบบอะซิงโครนัสหลังจาก 0.3 วินาทีเนื่องจากเค้าโครงมุมมองจะรีเซ็ต contentOffset แม้จะดูแล้วก็ตาม

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  [self.tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
}

-(void)viewDidAppear:(BOOL)animated{
   __weak typeof (self) weakSelf = self;
   dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [weakSelf.tableView removeObserver:self forKeyPath:@"contentOffset"];});
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if ([keyPath isEqualToString:@"contentOffset"] && self.tableView.contentOffset.y == 0.0) {
       self.tableView.contentOffset = CGPointMake(0, CGRectGetHeight(self.tableView.tableHeaderView.frame));
    }
}

-(void)dealloc {
    [self.tableView removeObserver:self forKeyPath:@"contentOffset"];
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.