视图添加到UIViewControllerWrapperView,但它没有正确显示

时间:2015-12-10 16:05:08

标签: c# ios uiview uiviewcontroller xamarin.ios

我正在尝试在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 来自我使用的一个约束,我通过使用不同的约束(限制widht / height)在后续步骤之一中消除了这些约束。

如果我添加一个最小高度,我可以在表格视图左上角的导航栏下看到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中提供代码示例!

2 个答案:

答案 0 :(得分:2)

您不应手动向UIViewControllerWrapperView添加视图,因为它是内部API。这样做会导致不可预测的结果。

相反,请将加载指标作为子视图添加到view的{​​{1}}属性中。也许这已经解决了你的问题。

还有一件事:如果你的HUD是UITableViewController,你不需要删除它来隐藏它。只需将UIActivityIndicatorView属性设置为hidesWhenStopped;然后,在调用true时,指标会自动隐藏,并在调用stopAnimating时重新显示。

修改

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

UIView

请注意,此示例使用具有固有大小的简单活动指示符,因此要使其居中,只需要两个约束;对于您的HUD,您可能需要添加更复杂的约束。

答案 1 :(得分:0)

我采用了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后面添加了一个额外的视图。现在我可以使用表视图的superview来查看我的HUD。似乎到目前为止工作。

懒惰的替代品(具有不同的行为):

  • 使用Window属性:

    UIApplication.SharedApplication.Delegate.GetWindow().View

  • 使用NavigationController

    NavigationController.View