IOS 7アプリで透明なナビゲーションバーを使用しようとしています。私のアプリケーションにはフルスクリーン画像があります。また、その画像の上にUITableViewがあります。以下のコードを使用すると、イメージは画面に収まりますが、UITableViewはナビゲーションバーの下に表示されます。
viewDidLoad
に
私が使う
self.navigationController.navigationBar.shadowImage = [UIImage new];
self.navigationController.navigationBar.translucent = YES;
self.navigationController.view.backgroundColor = [UIColor clearColor];
self.navigationController.navigationBar.translucent = NO;
に変更しても問題ありませんが、ナビゲーションバーの透明性が失われます。
TableViewのcontentInsetsは、最初はナビゲーションバーの下にあるように設定できますが、その後ろにスクロールします(コンテンツは重複します)
self.tableView.contentInset = UIEdgeInsetsMake(44,0,0,0);
または、TableViewのフレームをオフセットできます。スクロールコンテンツはナビゲーションバーの下で途切れます(見た目も良くありません)
私は私のケースがこれを助けました(ビルチャンのコードの修正版):
目的のCバージョン:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
CGRect rect = self.navigationController.navigationBar.frame;
float y = rect.size.height + rect.Origin.y;
self.tableView.contentInset = UIEdgeInsetsMake(y, 0, 0, 0);
}
ポイントは、navigationBarの高さ(rect.size.height
)とステータスバーの高さ(rect.Origin.y
)のためにテーブルを押し下げる必要があることです。
Swiftバージョン(Swift 2と互換性があります):
override func viewDidLayoutSubviews() {
if let rect = self.navigationController?.navigationBar.frame {
let y = rect.size.height + rect.Origin.y
self.tableView.contentInset = UIEdgeInsetsMake( y, 0, 0, 0)
}
}
Tableviewのy位置をナビゲーションバーの高さとステータスバーの高さに設定します(height
にします)
すなわち、
height = 64; // height of navigation bar = 44(In portait), height of status bar = 20
tableView.frame = CGRectMake(tableView.frame.Origin.x, height , tableView.frame.size.width, tableView.frame.size.height);
自動レイアウトを使用している場合は、フレームを変更するのではなく、tableView top制約の更新を変更するだけです。
また、viewControllerを自動的に変更しますAdjustsScrollViewInsetsをNOに変更します
self.automaticallyAdjustsScrollViewInsets = NO;
異なる方向をサポートしている場合は、フレームとcontentInsetを(52)に更新します。これは、横向きモードのナビゲーションバーの高さが32であるためです。
これを確認してください サンプル
これはiOS8の横向きモードと縦向きモードの両方で動作しています:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
CGRect rect = self.navigationController.navigationBar.frame;
float y = -rect.Origin.y;
self.tableView.contentInset = UIEdgeInsetsMake(y ,0,0,0);
}
デバイスの向きに基づいている可能性があるため、インセット値をハードコードしない方が良いです。
コード:
func setTableViewContentInset() {
let contentInsetHeight = topLayoutGuide.length
let contentInset = UIEdgeInsetsMake(contentInsetHeight, 0, 0, 0)
tableView.contentInset = contentInset
tableView.scrollIndicatorInsets = contentInset
}
func scrollToTop() {
if tableView.indexPathsForVisibleRows?.count > 0 {
let topIndexPath = NSIndexPath(forRow: 0, inSection: 0)
tableView.scrollToRowAtIndexPath(topIndexPath, atScrollPosition: .Top, animated: false)
}
}
func scrollToTopOfVisibleCells() {
if let visibleIndexPaths = tableView.indexPathsForVisibleRows where tableView.indexPathsForVisibleRows?.count > 0 {
let topMostVisibleIndexPath = visibleIndexPaths[0]
tableView.scrollToRowAtIndexPath(topMostVisibleIndexPath, atScrollPosition: .Top, animated: false)
}
}
//MARK: Load Views
override func viewDidLoad() {
super.viewDidLoad()
setTableViewContentInset()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
scrollToTop()
}
//MARK: Trait collection change
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
setTableViewContentInset()
scrollToTopOfVisibleCells()
}
ほとんどの場合、マジック定数を導入するソリューションはスケールしません。たとえば、次のiPhoneが異なるナビゲーションバーの高さを導入する場合、コードを更新する必要があります。
幸いなことに、Appleは、この問題をよりきれいに解決する方法を提供してくれました。たとえば、 topLayoutGuide :
TopLayoutGuideプロパティは、View Controllerが画面の最前面にあるときに機能します。半透明または透明のUIKitバー(ステータスバーやナビゲーションバーなど)の背後に表示したくないコンテンツの最大垂直範囲を示します
プログラムにより、次のコードスニペットを使用して達成できます(同じことはIBでも達成できます)。
override func viewDidLoad() {
super.viewDidLoad()
automaticallyAdjustsScrollViewInsets = false
tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
tableView.topAnchor.constraint(equalTo:
topLayoutGuide.bottomAnchor),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
注:topLayoutGuideはiOS 11で非推奨になりました。代わりにUIViewの safeAreaLayoutGuide プロパティを使用する必要があります。
私はiOS開発とStack Overflowの両方に慣れていないので、投稿が完璧でない場合はご容赦ください。
この問題もありました。UITableViewのコンテンツインセットを使用した場合、最初に読み込んだとき、または他のタブからアクセスしたときに完全に機能しました。ただし、ビューに戻ると、余分な「パディング」があります。 UITableViewが毎回正しく配置されるように、回避策を考えました。
UITableViewまたはタブを最初にロードするとき、ナビゲーションバーの下のテーブルを正しく開始するためにインセットが必要ですが、後ろに移動するときにインセットは必要ありません。何らかの理由で、 UITableView。これが余分なパディングを取得できる理由です。
ソリューションでは、ブールを使用して、離れて移動したかどうかを判断します。これにより、コンテンツのインセットが必要かどうかを正しく判断できます。
_-(void)viewDidLoad
でhasNavigatedFurther = NO
を設定します。次に:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (!hasNavigatedFurther) {
self.tableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
} else {
self.tableView.contentInset = UIEdgeInsetsZero;
//In order to allow visiting between tabs and retaining desired look
hasNavigatedFurther = NO;
}
}
これを機能させるには、別のビューをナビゲーションスタックにプッシュするコードの直前にhasNavigatedFurther = YES
を設定する必要があります。
-(void)btnTouched:(id)sender {
hasNavigatedFurther = YES;
NextViewController* nvc = [NextViewController new];
[self.navigationController pushViewController:nvc animated:YES];
}
このコードのみが問題を解決します。
@IBOutlet weak var tableView: UITableView!
func viewDidLoad() {
super.viewDidLoad()
self.tableView.contentInset = UIEdgeInsetsZero
}
次のソリューションを思い付きました。これは、View Controllerに初めてナビゲートするときに、最上位セルにある可能性のあるパディングを考慮して、Table ViewのcontentInset
をナビゲーションバーの高さに合わせて調整します。別のView ControllerをスタックにプッシュしてこのView Controllerに戻ると、contentInset
をUIEdgeInsetsZero
に再調整します。
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self adjustEdgeInsetsForTableView];
}
- (void)adjustEdgeInsetsForTableView {
if(self.isMovingToParentViewController) {
self.tableViewForm.contentInset = UIEdgeInsetsMake(self.navigationController.navigationBar.frame.size.height + padding, 0, 0, 0);
} else {
self.tableViewForm.contentInset = UIEdgeInsetsZero;
}
}
@Adam Farrellと@Tash Pemhiwaのソリューションを組み合わせたところ、最終的に以下のコードが機能しました。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self adjustEdgeInsetsForTableView];
}
- (void)adjustEdgeInsetsForTableView
{
if(self.isMovingToParentViewController) {
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
} else {
self.tableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
}
}
これが、この奇妙なUIの動作に数時間を費やす人々に役立つことを願っています。