视图被添加到UIViewControllerWrapperView中,但它没有';t显示正确

本文关键字:显示 添加 UIViewControllerWrapperView 视图 | 更新日期: 2023-09-27 18:26:18

我试图在UITableViewController的顶部显示一个加载指示器。因此,我将我的子视图添加到myTableViewontroller.View.Superview,即UIViewControllerWrapperView。到目前为止,这是有效的,但并非在所有情况下都有效。如果第一次在导航堆栈上添加UITableViewController,我可以随心所欲地显示加载指示符。如果我弹出UITableViewController并再次在导航堆栈上推送它的新实例,则加载指示器不会出现。连续调用使加载指示器再次出现!

我尝试在UpdateConstraintsLayoutSubviews中设置约束,但没有帮助。不知怎么的,框架的高度似乎为零。检查框架显示以下内容:

正常情况:

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来自我使用的一个约束,我在接下来的一个步骤中通过使用不同的约束(限制宽度/高度)来消除这个约束。

如果我添加一个最小高度,我可以在表格视图左上角的导航栏下看到hud,但它通过导航栏被切掉了,并且没有居中。如果我试图将宽度/高度限制在零和我定义的最大尺寸之间,也会发生同样的行为:

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中,但它没有';t显示正确

由于UIViewControllerWrapperView是内部API,因此不应手动向其添加视图。这样做可能会导致不可预测的结果。

相反,将加载指示器作为子视图添加到UITableViewControllerview属性中。也许这已经解决了你的问题。

还有一件事:如果你的HUD是UIActivityIndicatorView,你不需要为了隐藏它而删除它。只需将hidesWhenStopped属性设置为true;则当调用stopAnimating时指示符将自动隐藏并且当调用startAnimating时指示符将重新出现。

编辑:

正如您所指出的,将HUD直接添加到视图中可能会导致定位问题。一种解决方法是手动设置一个容器视图(一个普通的UIView),该视图承载表视图和HUD:

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进行子类化。

我的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