142

私は UITableView を持っていますが、場合によっては空でも合法です。したがって、アプリの背景画像を表示する代わりに、次のようなわかりやすいメッセージを画面に表示することをお勧めします。

このリストは空です

それを行う最も簡単な方法は何ですか?

4

22 に答える 22

193

UITableView の backgroundView プロパティはあなたの友達です。

テーブルが空かどうかを判断し、UILabel を含む UIView で UITableView の backgroundView プロパティを更新するか、単に nil に設定する必要がある場所またはviewDidLoad場所。reloadDataそれでおしまい。

もちろん、UITableView のデータ ソースに二重の義務を負わせ、特別な「リストが空です」セルを返すことは可能です。突然numberOfRowsInSection:(NSInteger)section、質問されていない他のセクションの行数を計算して、それらが空であることを確認する必要があります。また、空のメッセージを持つ特別なセルを作成する必要があります。また、空のメッセージに合わせてセルの高さを変更する必要があることも忘れないでください。これはすべて実行可能ですが、バンドエイドの上にバンドエイドがあるようです.

于 2013-07-02T22:20:36.167 に答える
18

次のライブラリをお勧めします: DZNEmptyDataSet

プロジェクトに追加する最も簡単な方法は、次のように Cocaopods で使用することです。pod 'DZNEmptyDataSet'

TableViewController に、次の import ステートメント (Swift) を追加します。

import DZNEmptyDataSet

次に、クラスが次のように準拠していることを確認しますDNZEmptyDataSetSourceDZNEmptyDataSetDelegate

class MyTableViewController: UITableViewController, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate

viewDidLoad次のコード行を追加します。

tableView.emptyDataSetSource = self
tableView.emptyDataSetDelegate = self
tableView.tableFooterView = UIView()

emptystate を表示するために必要なことは次のとおりです。

//Add title for empty dataset
func titleForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
    let str = "Welcome"
    let attrs = [NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)]
    return NSAttributedString(string: str, attributes: attrs)
}

//Add description/subtitle on empty dataset
func descriptionForEmptyDataSet(scrollView: UIScrollView!) -> NSAttributedString! {
    let str = "Tap the button below to add your first grokkleglob."
    let attrs = [NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleBody)]
    return NSAttributedString(string: str, attributes: attrs)
}

//Add your image
func imageForEmptyDataSet(scrollView: UIScrollView!) -> UIImage! {
    return UIImage(named: "MYIMAGE")
}

//Add your button 
func buttonTitleForEmptyDataSet(scrollView: UIScrollView!, forState state: UIControlState) -> NSAttributedString! {
    let str = "Add Grokkleglob"
    let attrs = [NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleCallout)]
    return NSAttributedString(string: str, attributes: attrs)
}

//Add action for button
func emptyDataSetDidTapButton(scrollView: UIScrollView!) {
    let ac = UIAlertController(title: "Button tapped!", message: nil, preferredStyle: .Alert)
    ac.addAction(UIAlertAction(title: "Hurray", style: .Default, handler: nil))
    presentViewController(ac, animated: true, completion: nil)
}

これらのメソッドは必須ではありません。ボタンなどを使用せずに空の状態を表示することもできます。

スイフト 4 の場合

// MARK: - Deal with the empty data set
// Add title for empty dataset
func title(forEmptyDataSet _: UIScrollView!) -> NSAttributedString! {
    let str = "Welcome"
    let attrs = [NSAttributedStringKey.font: UIFont.preferredFont(forTextStyle: UIFontTextStyle.headline)]
    return NSAttributedString(string: str, attributes: attrs)
}

// Add description/subtitle on empty dataset
func description(forEmptyDataSet _: UIScrollView!) -> NSAttributedString! {
    let str = "Tap the button below to add your first grokkleglob."
    let attrs = [NSAttributedStringKey.font: UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)]
    return NSAttributedString(string: str, attributes: attrs)
}

// Add your image
func image(forEmptyDataSet _: UIScrollView!) -> UIImage! {
    return UIImage(named: "MYIMAGE")
}

// Add your button
func buttonTitle(forEmptyDataSet _: UIScrollView!, for _: UIControlState) -> NSAttributedString! {
    let str = "Add Grokkleglob"
    let attrs = [NSAttributedStringKey.font: UIFont.preferredFont(forTextStyle: UIFontTextStyle.callout), NSAttributedStringKey.foregroundColor: UIColor.white]
    return NSAttributedString(string: str, attributes: attrs)
}

// Add action for button
func emptyDataSetDidTapButton(_: UIScrollView!) {
    let ac = UIAlertController(title: "Button tapped!", message: nil, preferredStyle: .alert)
    ac.addAction(UIAlertAction(title: "Hurray", style: .default, handler: nil))
    present(ac, animated: true, completion: nil)
}
于 2016-06-05T14:30:03.330 に答える
11

これには titleForFooterInSection メッセージを使用しています。これが最適かどうかはわかりませんが、うまくいきます。

-(NSString*)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section   {

    NSString *message = @"";
    NSInteger numberOfRowsInSection = [self tableView:self.tableView numberOfRowsInSection:section ];

    if (numberOfRowsInSection == 0) {
        message = @"This list is now empty";
    }

    return message;
}
于 2015-02-03T11:40:11.813 に答える
8

セルの後に UITextView を TableView 内にドラッグ アンド ドロップすることのみをお勧めします。ViewController への接続を作成し、必要に応じて非表示/表示します (たとえば、テーブルがリロードされるたび)。

ここに画像の説明を入力

于 2016-04-18T00:14:59.527 に答える
5

backgroundView の使用は問題ありませんが、Mail.app のようにうまくスクロールしません。

私はxtravarと同じようなことをしました。

のビュー階層の外側にビューを追加しましたtableViewController階層

次に、次のコードを使用しましたtableView:numberOfRowsInSection:

if someArray.count == 0 {
    // Show Empty State View
    self.tableView.addSubview(self.emptyStateView)
    self.emptyStateView.center = self.view.center
    self.emptyStateView.center.y -= 60 // rough calculation here
    self.tableView.separatorColor = UIColor.clear
} else if self.emptyStateView.superview != nil {
    // Empty State View is currently visible, but shouldn't
    self.emptyStateView.removeFromSuperview()
    self.tableView.separatorColor = nil
}

return someArray.count

基本的に、オブジェクトemptyStateViewのサブビューとしてを追加しました。tableViewセパレーターがビューに重なるので、色を に設定しclearColorます。デフォルトのセパレーターの色に戻すには、それを に設定するだけですnil

于 2016-09-06T19:49:03.933 に答える
3

まず、他の一般的なアプローチの問題。

背景ビュー

UILabel に設定する単純なケースを使用する場合、背景ビューはうまく中央に配置されません。

メッセージを表示するセル、ヘッダー、またはフッター

これにより、機能コードが妨げられ、奇妙なエッジ ケースが導入されます。メッセージを完全に中央に配置したい場合は、別のレベルの複雑さが追加されます。

独自のテーブル ビュー コントローラーのローリング

refreshControl などの組み込み機能を失い、車輪を再発明します。最良の保守可能な結果を​​得るには、UITableViewController に固執してください。

UITableViewController を子ビュー コントローラーとして追加する

iOS 7 以降では contentInset の問題が発生する気がしますが、なぜ複雑になるのでしょうか?

私の解決策

私が思いついた最善の解決策 (そして、これは理想的ではありません) は、スクロール ビューの上に座ってそれに応じて動作する特別なビューを作成することです。これは iOS 7 では contentInset の狂気で明らかに複雑になりますが、実行可能です。

あなたが気をつけなければならないこと:

  • reloadData 中のある時点で、テーブル セパレータが前面に表示されます。これを防ぐ必要があります。
  • contentInset/contentOffset - 特別なビューでこれらのキーを観察します
  • キーボード - キーボードが邪魔になりたくない場合は、別の計算です
  • 自動レイアウト - フレームの変更に依存してビューを配置することはできません

1 つの UIView サブクラスで一度これを理解したら、スピナーのロード、ビューの無効化、エラー メッセージの表示など、すべてに使用できます。

于 2014-03-16T23:53:32.070 に答える
3

これを Base クラスに追加できます。

var messageLabel = UILabel()

func showNoDataMessage(msg: String) {
    let rect = CGRect(origin: CGPoint(x: 0, y :self.view.center.y), size: CGSize(width: self.view.bounds.width - 16, height: 50.0))
    messageLabel = UILabel(frame: rect)
    messageLabel.center = self.view.center
    messageLabel.text = msg
    messageLabel.numberOfLines = 0
    messageLabel.textColor = Colors.grayText
    messageLabel.textAlignment = .center;
    messageLabel.font = UIFont(name: "Lato-Regular", size: 17)
    self.view.addSubview(messageLabel)
    self.view.bringSubviewToFront(messageLabel)
}

APIからデータを取得する際のクラスで、このように表示します。

func populateData(dataSource : [PRNJobDataSource]){
    self.dataSource = dataSource
    self.tblView.reloadData()
    if self.dataSource.count == 0 {self.showNoDataMessage(msg: "No data found.")}
}

このように隠します。

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if self.dataSource.count > 0 {self.hideNoDataMessage()}
    return dataSource.count
}

func hideNoDataMessage(){
    messageLabel.removeFromSuperview()
}
于 2020-03-09T12:14:30.957 に答える
0

Swift バージョンですが、よりシンプルで優れた形式です。**3.0

それがあなたの目的に役立つことを願っています......

あなたの UITableViewController で。

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if searchController.isActive && searchController.searchBar.text != "" {
        if filteredContacts.count > 0 {
            self.tableView.backgroundView = .none;
            return filteredContacts.count
        } else {
            Helper.EmptyMessage(message: ConstantMap.NO_CONTACT_FOUND, viewController: self)
            return 0
        }
    } else {
        if contacts.count > 0 {
            self.tableView.backgroundView = .none;
            return contacts.count
        } else {
            Helper.EmptyMessage(message: ConstantMap.NO_CONTACT_FOUND, viewController: self)
            return 0
        }
    }
}

関数を持つヘルパー クラス:

 /* Description: This function generate alert dialog for empty message by passing message and
           associated viewcontroller for that function
           - Parameters:
            - message: message that require for  empty alert message
            - viewController: selected viewcontroller at that time
         */
        static func EmptyMessage(message:String, viewController:UITableViewController) {
            let messageLabel = UILabel(frame: CGRect(x: 0, y: 0, width: viewController.view.bounds.size.width, height: viewController.view.bounds.size.height))
            messageLabel.text = message
            let bubbleColor = UIColor(red: CGFloat(57)/255, green: CGFloat(81)/255, blue: CGFloat(104)/255, alpha :1)

            messageLabel.textColor = bubbleColor
            messageLabel.numberOfLines = 0;
            messageLabel.textAlignment = .center;
            messageLabel.font = UIFont(name: "TrebuchetMS", size: 18)
            messageLabel.sizeToFit()

            viewController.tableView.backgroundView = messageLabel;
            viewController.tableView.separatorStyle = .none;
        }
于 2017-01-12T12:24:10.487 に答える