[英]View is added to UIViewControllerWrapperView, but it doesn't appear correctly
我試圖在UITableViewController
頂部顯示加載指示器。 因此,我將子視圖添加到myTableViewontroller.View.Superview
,即UIViewControllerWrapperView
。 到目前為止,此方法仍然有效,但並非在所有情況下都有效。 如果將UITableViewController
第一次添加到導航堆棧中,則可以根據需要頻繁顯示加載指示器。 如果我彈出UITableViewController
並將其新實例再次推入導航堆棧,則不會顯示加載指示器。 連續的通話使加載指示再次出現!
我試圖在UpdateConstraints
, LayoutSubviews
設置約束,但並沒有幫助。 不知何故,框架的高度似乎為零。 檢查框架顯示以下內容:
正常情況:
parent:{X=0,Y=0,Width=320,Height=480}
hud:{X=0,Y=0,Width=0,Height=0}
parent - before setting up constraints{X=0,Y=0,Width=320,Height=480}
hud - after hud showing: {X=0,Y=0,Width=279,5,Height=0}
parent:{X=0,Y=0,Width=320,Height=480}
hud:{X=0,Y=0,Width=320,Height=480}
失敗案例
parent:{X=0,Y=0,Width=320,Height=480}
hud:{X=0,Y=0,Width=0,Height=0}
parent - before setting up constraints{X=0,Y=0,Width=320,Height=480}
hud - after hud showing: {X=-20,Y=59,Width=279,5,Height=0}
因此,在正常情況下, LayoutSubviews
似乎被調用了兩次,因為在那里會輸出parent:和hud:行。 -20來自我使用的一個約束,我通過使用不同的約束(限制寬度/高度)在接下來的步驟之一中擺脫了這個約束。
如果我增加了最小高度,則可以在表格視圖左上方的導航欄下方看到平移,但它會通過導航欄切斷並且不會居中。 如果我嘗試將寬度/高度限制在零到我定義的最大大小之間,則會發生相同的行為:
NSLayoutConstraint widthConstraint1 = NSLayoutConstraint.Create(this.hudContainer, NSLayoutAttribute.Width, NSLayoutRelation.LessThanOrEqual, this, NSLayoutAttribute.Width, 1, -40);
widthConstraint1.Priority = 750;
NSLayoutConstraint widthConstraint2 = NSLayoutConstraint.Create(this.hudContainer, NSLayoutAttribute.Width, NSLayoutRelation.GreaterThanOrEqual, null, NSLayoutAttribute.NoAttribute, 1, 0);
widthConstraint2.Priority = 1000;
NSLayoutConstraint heightConstraint1 = NSLayoutConstraint.Create(this.hudContainer, NSLayoutAttribute.Height, NSLayoutRelation.LessThanOrEqual, this, NSLayoutAttribute.Height, 1, -100);
heightConstraint1.Priority = 750;
NSLayoutConstraint heightConstraint2 = NSLayoutConstraint.Create(this.hudContainer, NSLayoutAttribute.Height, NSLayoutRelation.GreaterThanOrEqual, null, NSLayoutAttribute.NoAttribute, 1, 0);
heightConstraint2.Priority = 1000;
AddConstraints(new NSLayoutConstraint[] { widthConstraint1, widthConstraint2, heightConstraint1, heightConstraint2});
在此不考慮最大寬度。
我使用此代碼將hud添加為子視圖並設置主要約束:
this.TranslatesAutoresizingMaskIntoConstraints = false;
this.parentView.AddSubview(this);
NSMutableDictionary viewsDictionary = new NSMutableDictionary();
viewsDictionary["hud"] = this;
this.parentView.LayoutIfNeeded();
Console.WriteLine("parent - before setting up constraints" + this.parentView.Frame);
this.parentView.AddConstraint(NSLayoutConstraint.Create(this, NSLayoutAttribute.Width, NSLayoutRelation.Equal, this.parentView, NSLayoutAttribute.Width, 1, 0));
this.parentView.AddConstraint(NSLayoutConstraint.Create(this, NSLayoutAttribute.Height, NSLayoutRelation.Equal, this.parentView, NSLayoutAttribute.Height, 1, 0));
this.parentView.AddConstraint(NSLayoutConstraint.Create(this, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this.parentView, NSLayoutAttribute.Top, 1, 0));
this.parentView.AddConstraint(NSLayoutConstraint.Create(this, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this.parentView, NSLayoutAttribute.Right, 1, 0));
this.parentView.AddConstraint(NSLayoutConstraint.Create(this, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, this.parentView, NSLayoutAttribute.Bottom, 1, 0));
this.parentView.AddConstraint(NSLayoutConstraint.Create(this, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this.parentView, NSLayoutAttribute.Left, 1, 0));
this.parentView.AddConstraint(NSLayoutConstraint.Create(this, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, this.parentView, NSLayoutAttribute.CenterX, 1, 0));
this.parentView.AddConstraint(NSLayoutConstraint.Create(this, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, this.parentView, NSLayoutAttribute.CenterY, 1, 0));
這是用於刪除和隱藏hud的代碼:
this.Alpha = 0.0f;
RemoveFromSuperview();
我的想法不多了。 我怎么解決這個問題? 也許有人可以給我一個提示,我該如何更好地調試它。 此處提供的代碼在C#中,但是您可以在Objective-C / Swift中提供代碼示例!
您不應該將視圖手動添加到UIViewControllerWrapperView
因為它是內部API。 這樣做可能導致不可預測的結果。
而是將您的加載指示器作為子視圖添加到UITableViewController
的view
屬性中。 也許這已經解決了您的問題。
還有一件事:如果HUD是UIActivityIndicatorView
,則無需刪除它即可將其隱藏。 只需將hidesWhenStopped
屬性設置為true
; 那么該指標將在stopAnimating
時自動隱藏,並在startAnimating
時重新出現。
編輯:
正如您所指出的,將HUD直接添加到視圖可能會導致定位問題。 解決此問題的一種方法是手動設置一個包含表視圖和HUD的容器視圖(普通的UIView
):
override func viewDidLoad() {
super.viewDidLoad()
let tableView = self.tableView
let containerView = UIView(frame: self.view.bounds)
containerView.addSubview(tableView)
containerView.addSubview(spinner)
view = containerView
spinner.translatesAutoresizingMaskIntoConstraints = false
view.addConstraint(NSLayoutConstraint(item: spinner, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: 0))
view.addConstraint(NSLayoutConstraint(item: spinner, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: 0))
spinner.startAnimating()
}
請注意,此示例使用了一個簡單的活動指示器,該指示器具有內在的大小,因此要使其居中,只需要兩個約束即可; 對於HUD,您可能必須添加更復雜的約束。
我采用了dr_barto建議的方法。 我定義了新的基類HUDTableViewController
,這是我的新UITableViewController
。 所以我從HUDTableViewController
而不是UITableViewController
HUDTableViewController
子類。
我的HUD獲得以下視圖:
TableView.Superview
(在我的子類HUDTableViewController
內部)
人們將不得不添加其他方法,並為UICollectionViewController
實現此類基類。 在這里,我為UITableViewController
提供了一個示例:
public class HUDTableViewController : UIViewController, IUITableViewDataSource, IUITableViewDelegate, IDisposable
{
private UITableView tableView;
public UITableView TableView
{
get
{
return this.tableView;
}
set
{
this.tableView = value;
}
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
this.tableView = new UITableView();
this.tableView.TranslatesAutoresizingMaskIntoConstraints = false;
this.tableView.WeakDelegate = this;
this.tableView.WeakDataSource = this;
UIView parentView = new UIView();
parentView.AddSubview(this.tableView);
View = parentView;
NSMutableDictionary viewsDictionary = new NSMutableDictionary();
viewsDictionary["parent"] = parentView;
viewsDictionary["tableView"] = this.tableView;
parentView.AddConstraints(NSLayoutConstraint.FromVisualFormat("H:|[tableView]|", (NSLayoutFormatOptions)0, null, viewsDictionary));
parentView.AddConstraints(NSLayoutConstraint.FromVisualFormat("V:|[tableView]|", (NSLayoutFormatOptions)0, null, viewsDictionary));
}
[Foundation.Export("numberOfSectionsInTableView:")]
public virtual System.nint NumberOfSections(UIKit.UITableView tableView)
{
throw new NotImplementedException();
}
public virtual System.nint RowsInSection(UIKit.UITableView tableview, System.nint section)
{
throw new NotImplementedException();
}
public virtual UIKit.UITableViewCell GetCell(UIKit.UITableView tableView, Foundation.NSIndexPath indexPath)
{
throw new NotImplementedException();
}
[Foundation.Export("tableView:didSelectRowAtIndexPath:")]
public virtual void RowSelected(UIKit.UITableView tableView, Foundation.NSIndexPath indexPath)
{
throw new NotImplementedException();
}
[Foundation.Export("tableView:heightForHeaderInSection:")]
public virtual System.nfloat GetHeightForHeader(UIKit.UITableView tableView, System.nint section)
{
throw new NotImplementedException();
}
[Foundation.Export("tableView:viewForHeaderInSection:")]
public virtual UIKit.UIView GetViewForHeader(UIKit.UITableView tableView, System.nint section)
{
throw new NotImplementedException();
}
[Foundation.Export("tableView:willDisplayCell:forRowAtIndexPath:")]
public virtual void WillDisplay(UIKit.UITableView tableView, UIKit.UITableViewCell cell, Foundation.NSIndexPath indexPath)
{
throw new NotImplementedException();
}
}
可以看到,我在UITableView
后面添加了一個附加視圖。 現在,我可以將表視圖的超級視圖用於HUD。 到目前為止似乎工作正常。
惰性替代方案(具有不同的行為):
使用Window
屬性:
UIApplication.SharedApplication.Delegate.GetWindow().View
使用NavigationController
:
NavigationController.View
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.