UITableViewControllerのviewDidLoadメソッド内からサブビュー(UIView)を追加するのが難しい
これは動作します:
[self.view addSubview:self.progView];
ただし、UIView progViewを介して表のセル行がにじむのを確認できます。
私はこのアプローチを試しました:
[self.view.superview insertSubview:self.progView aboveSubview:self.view];
これは、現在のビューの上に、progView、UIViewをスーパービューに追加する試みです。これを試しても、UIViewは表示されません。
-更新-
以下は最新の試みです。
UIView *myProgView = (UIView *)self.progView; //progView is a method that returns a UIView
[self.tableView insertSubview:myProgView aboveSubview:self.tableView];
[self.tableView bringSubviewToFront:myProgView];
結果は[self.view addSubview:self.progView]と同じです。 UIViewは表示されますが、テーブルの背後に表示されます。
上記の方法を試しましたが、うまくいきませんでした。また、テーブルビューをゼロからセットアップする必要があるため(ストーリーボード内から簡単に実行できること)、構成とコードが多すぎることがわかりました。
代わりに、UITableViewの上に追加したいビューをUITableViewControllerのUINavigationControllerのビューに追加しました。
[self.navigationController.view addSubview:<view to add above the table view>];
この方法では、UITableViewControllerをUINavigationControllerに埋め込む必要がありますが、Navigation Controllerが必要ない場合でも、この方法を使用して、Navigation Barを非表示にすることができます。
これは実際には非常に可能で簡単です-ほんの少しの再配線が必要です。同様の状況に遭遇し、これをコーディングして、テーブルビューの上部にロード画面を追加できるようにしました。このアプローチでは、静的なテーブルセルを独自のコンテンツで使用することもできます。
コントローラーがStoryboardまたはXIBのUITableViewControllerであり、既存のテーブルビューを保持しながらself.viewを標準UIViewに再割り当てする場合:
これらのインスタンス変数をヘッダーファイルに追加します。
IBOutlet UITableView *tableViewReference; // to keep a reference to the tableview
UIView *viewReference; // a reference to the new background view
ストーリーボードまたはXIBファイル:tableView
のUITableViewController
をtableViewReference
変数に接続します。
次に、実装ファイル:
// Override the default accessors of the tableview and view
- (UITableView*)tableView { return tableViewReference; }
- (UIView*)view { return viewReference; }
- (void)viewDidLoad
{
[super viewDidLoad];
// instantiate the new self.view, similar to the tableview
viewReference = [[UIView alloc] initWithFrame:tableViewReference.frame];
[viewReference setBackgroundColor:tableViewReference.backgroundColor];
viewReference.autoresizingMask = tableViewReference.autoresizingMask;
// add it as a subview
[viewReference addSubview:tableViewReference];
/* remainder of viewDidLoad */
}
奇妙に思えるかもしれませんが、UITableViewControllerは、背後で参照を使用して、風変わりなことをたくさん行っています。スワップを行うには、viewDidLoadまで待つ必要があります。このポイントの後、アクセサーは正しいUIView
とUITableView
をポイントします。
使用法:次のようなもの
[self.view addSubview:myView];
テーブルビューのコンテンツをmyView
スクロールせずに、テーブルビューの前にUIView myView
を追加します。
注:この回答は、ソリューションに境界線の逆説的なコードが含まれていることが指摘された後に編集されました。 UITableViewControllerは、保持する参照に対して奇妙なことをします。いくつかのより慎重なテストがこの単純な答えを導き出しました:)
ビューのレイヤーのzPositionを増やすことができます。
これにより、他のビュー(デフォルトで0に等しいzPositionを持つビュー)の上に表示されます。
self.progView.layer.zPosition++;
[self.view addSubview:self.progView];
Uiviewcontrollerの包含を使用して、uitableviewcontrollerの上にサブビューを追加できました。
UITableViewControllerは、静的セルに関しては実際に非常に便利です。これはおそらく、「uitableviewを使用するだけ」という一般的な答えが実際には実行できない唯一の時間です。
だからこれは私がそれを行う方法です。
次のようなコードを追加します。
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
UITableViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"MyStaticTableView"];
[self addChildViewController:vc];
[self.view_container addSubview:vc.view];
}
あなたが持っているかもしれない問題:
コードを追加:
- (void)viewWillAppear:(BOOL)animated
{
[[self.view_container.subviews lastObject] setFrame:self.view.frame];
}
この時点で、UITableViewControllerからコンテナビューに直接アクセスできます。
self.view.superview.superview
追加したものはすべて、Table View Controllerの上に表示されます
これがストーリーボードの使用方法です。
2)UITableViewControllerクラスにリンクします:
@IBOutlet weak var copyrightLabel: UILabel!
3)コードに追加する
self.navigationController?.view.addSubview(copyrightView)
copyrightView.frame = CGRect(x: 0,
y: self.view.bounds.size.height - copyrightView.bounds.size.height,
width: self.view.bounds.size.width,
height: copyrightView.bounds.size.height)
ビューはテーブルビューでスクロールしません。ストーリーボードから簡単に設計できます。
注:このソリューションは、ナビゲーションコントローラーにサブビューを追加します。ここからナビゲーションのさらに別の画面に移動する場合、このサブビューが持続することがわかります。 、セグエの実行中にviewDidDisappearでcopyrightView.removeFromSuperViewを使用して削除します。
UITableViewControllerはUIViewControllerのサブクラスであるため、目的のビューをそのスーパービューに追加する必要があります。
Swift:
self.view.superview?.addSubview(viewTobeAdded)
Objective C:
[self.view.superview addSubview: viewTobeAdded];
問題は、view
のUITableViewController
プロパティがtableView
プロパティと同一であることです。つまり、ルートビューはalwaysTable View Controllerであり、サブビューとして追加されるものはすべてTable View機能の対象となります。これには他の望ましくない副作用があります。たとえば、サブビューをスクロールしたくない場合にスクロールします。
ここにはいくつかのオプションがあります。 loadView
をオーバーライドして、独自のビューとテーブルビューをインストールできます。
// note: untested
- (void)loadView {
self.view = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
self.view.backgroundColor = [UIColor whiteColor];
UITableView *tblView = [[UITableView alloc]
initWithFrame:CGRectZero
style:UITableViewStylePlain
];
tblView.autoresizingMask =
UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight
;
self.tableView = tblView;
[self.view addSubview:tblView];
[tblView release];
}
そして、サブビューを追加する必要がある場合は、必要に応じてself.tableView
の下または上に追加します。
別のオプションは、必要なことを行うUIViewController
サブクラスを作成することです。 UITableViewController
はそれほど多くは追加しません。また、実装する小さな機能は簡単に複製できます。 コードの再利用を増やすためにUITableViewControllerを再作成する のような記事があり、これを簡単に行う方法を説明しています。
私は同様の問題を抱えていて、以下のコードを使用して解決しました:
[self.navigationController.view insertSubview:<subview>
belowSubview:self.navigationController.navigationBar];
これにより、スタックに存在するコントローラーを使用してビューが正しい場所に挿入されます。
Appleの例 "iPhoneCoreDataRecipes"は、NIBを使用してヘッダーをUITableViewにロードしています。 here を参照してください:
テーブルの上に画像を追加しました。私はこのコードを使用しました:
self.tableView.tableHeaderView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"header.png"]];
iOS 11のアップデート:
AutoLayout制約を安全な領域に使用するときに、サブビューをUITableView
に追加できるようになりました。これらのビューは、TableViewに沿ってスクロールしません。
この例では、UITableView
のUITableViewController
の上にあるNavigationBarの下にビューを配置します
[self.tableView addSubview:self.topBarView];
[NSLayoutConstraint activateConstraints:@[
[self.topBarView.topAnchor constraintEqualToAnchor:self.tableView.safeAreaLayoutGuide.topAnchor],
[self.topBarView.leadingAnchor constraintEqualToAnchor:self.tableView.safeAreaLayoutGuide.leadingAnchor],
[self.topBarView.trailingAnchor constraintEqualToAnchor:self.tableView.safeAreaLayoutGuide.trailingAnchor],
[self.topBarView.heightAnchor constraintEqualToConstant:40.0]
]];
Swift(Daniel Saidiと同等):
コントローラーがStoryboardまたはXIBのUITableViewControllerであり、既存のテーブルビューを保持しながらself.viewを標準UIViewに再割り当てする場合:
@IBOutlet var tableViewReference: UITableView!
var viewReference: UIView!
次に、実装ファイルで:
これらのインスタンス変数をTable View Controllerファイルに追加します。
override var tableView: UITableView! {
get { return tableViewReference }
set { super.tableView = newValue }
}
override var view: UIView! {
get { return viewReference }
set { super.view = newValue }
}
override func viewDidLoad() {
super.viewDidLoad()
self.edgesForExtendedLayout = UIRectEdge.None
self.extendedLayoutIncludesOpaqueBars = false
self.automaticallyAdjustsScrollViewInsets = false
//rewiring views due to add tableView as subview to superview
viewReference = UIView.init(frame: tableViewReference.frame)
viewReference.backgroundColor = tableViewReference.backgroundColor
viewReference.autoresizingMask = tableViewReference.autoresizingMask
viewReference.addSubview(tableViewReference)
}
ストーリーボードまたはXIBファイルで:UITableViewControllerのtableViewをtableViewReference変数に接続します。
その後、次のように子ビューを追加できます。
self.view.addSubView(someView)
UITableViewControllerのテーブルビューの上にUIViewを保持するために、デリゲートメソッド(UITableViewDelegate)の1つ(または複数)を使用しています。
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.addSubview(headerView)
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
tableView.addSubview(overlayView) // adds view always on top
}
// if using footers in table view
tableView(_ tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int) { ... }
ビューには、継ぎ目が良い解決策であるスーパービューが1つしかありませんので、間違っていたら修正してください。まだ60fpsを取得しているので、私には問題ありません。
試してください:[self.view bringSubviewToFront:self.progView];
または、self.progView
をテーブルのビューに追加してみてください。
Swift 4
これは、ビュー階層を再構成する多数の回答の中で最も単純化されたバージョンです。このアプローチでは、ストーリーボード/ペン先用の追加のアウトレットは必要なく、プログラムで構築されたインスタンスでも機能します。
class MyTableViewController: UITableViewController {
var strongTableView: UITableView?
override var tableView: UITableView! {
get {
return strongTableView ?? super.tableView
}
set {
strongTableView = newValue
}
}
override func viewDidLoad() {
super.viewDidLoad()
// theoretically we could use self.tableView = self.tableView but compiler will not let us assign a property to itself
self.tableView = self.view as? UITableView
self.view = UIView(frame: self.tableView!.frame)
self.view.addSubview(tableView)
}
}
次のコードをviewDidAppearに配置するだけです。
[self.tableView.superview addSubview:<your header view>];
これをしない理由があるかもしれませんが、これは今のところうまくいきます。 APを使用する場合
viewDidLayoutSubviews
内でこれを実行できますが、必ず一度だけ実行するようにしてください
self.searchTableView = [[UITableView alloc] initWithFrame:self.tableView.frame style:UITableViewStylePlain];
self.searchTableView.backgroundColor = [UIColor purpleColor];
[self.view.superview addSubview:self.searchTableView];
UITableViewControllerの上にロードインジケータを追加したいという同様の問題がありました。これを解決するために、UIViewをウィンドウのサブビューとして追加しました。これで問題は解決しました。これは私がやった方法です。
-(void)viewDidLoad{
[super viewDidLoad];
//get the app delegate
XYAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
//define the position of the rect based on the screen bounds
CGRect loadingViewRect = CGRectMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2, 50, 50);
//create the custom view. The custom view is a property of the VIewController
self.loadingView = [[XYLoadingView alloc] initWithFrame:loadingViewRect];
//use the delegate's window object to add the custom view on top of the view controller
[delegate.window addSubview: loadingView];
}
次のようなものを試してください:
[self.tableView addSubview:overlayView];
overlayView.layer.zPosition = self.tableView.backgroundView.layer.zPosition + 1;