This is how my screen is supposed to look like. It has a UIToolBar at the bottom and its contains a UIBarButtonItem. It was working fine before before iOS 11.
But in iOS 11, the UIBarButtonItem is showing out its place. It is showing in the status bar. In the simulator it is working fine, and it shows inside the toolbar. But when I run it on an iPhone 6s running iOS 11. It's showing like in the screen below.
Here's the code..
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
UIBarButtonItem[] bArray = {
getSetAsHomeButton(apiCall, this, 0),
new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace)
};
SetToolbarItems(bArray, true);
}
public static UIBarButtonItem getSetAsHomeButton(ICommonApiCall commonApiCall, UIViewController controller, int status)
{
var view = new UIButton ();
view.Layer.CornerRadius = 8;
view.BackgroundColor = UIColor.White;
view.TranslatesAutoresizingMaskIntoConstraints = false;
view.WidthAnchor.ConstraintEqualTo(108).Active = true;
view.HeightAnchor.ConstraintEqualTo(32).Active = true;
var HomeIcon = new UILabel (new RectangleF (0, 0, 21, 21));
HomeIcon.Font = FontAwesome.Font (22);
HomeIcon.Text = FontAwesome.FAHome;
HomeIcon.TextColor = PlatformConstants.PrimaryColor;
var HomeLabel = new UILabel (new RectangleF (25, 0, 64, 44));
HomeLabel.Text = "Set as default";
HomeLabel.Font = UIFont.FromName (PlatformConstants.PrimaryFont + "-Medium", 11);
HomeLabel.TextColor = PlatformConstants.PrimaryColor;
HomeLabel.Lines = 0;
HomeLabel.SizeToFit ();
view.AddSubview (HomeIcon);
view.AddSubview (HomeLabel);
HomeIcon.TranslatesAutoresizingMaskIntoConstraints = false;
HomeLabel.TranslatesAutoresizingMaskIntoConstraints = false;
var hSpaceLeading = NSLayoutConstraint.Create (HomeIcon, NSLayoutAttribute.Leading,
NSLayoutRelation.Equal, view, NSLayoutAttribute.Leading, 1, 6);
view.AddConstraint (hSpaceLeading);
var HomeIconCenterY = NSLayoutConstraint.Create (HomeIcon, NSLayoutAttribute.CenterY,
NSLayoutRelation.Equal, view, NSLayoutAttribute.CenterY, 1, 0);
view.AddConstraint (HomeIconCenterY);
var HomeLabelCenterY = NSLayoutConstraint.Create (HomeLabel, NSLayoutAttribute.CenterY,
NSLayoutRelation.Equal, view, NSLayoutAttribute.CenterY, 1, 0);
view.AddConstraint (HomeLabelCenterY);
var hSpace = NSLayoutConstraint.Create (HomeLabel, NSLayoutAttribute.Left,
NSLayoutRelation.Equal, HomeIcon, NSLayoutAttribute.Right, 1, 4);
view.AddConstraint (hSpace);
var HomeLabelWidth = NSLayoutConstraint.Create (HomeLabel, NSLayoutAttribute.Width,
NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, 80);
view.AddConstraint (HomeLabelWidth);
view.LayoutIfNeeded ();
view.TouchUpInside += delegate {
SetAsHome (commonApiCall, controller, status, view).ContinueWith (t => Console.WriteLine (t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
};
return new UIBarButtonItem (view);
}
Any help is appreciated. Thank you.
Since iOS Auto Layout has been introduced to the UINavigationBar and UIToolbar elements. So the best way to fix your problem is to add the proper constraints.
Here you can find some more help and details on the issue:
https://forums.developer.apple.com/thread/80075
Hope this solves your problem.
Related
I have a web view application which has a top menu bar. It all was working properly until Iphone X.
As you can see it has a top menu bar, and it needs some space on top to clear the speaker of the iphone X. Is there any way to make the web view smaller? I tried with constraints but I couldnt quite get it working.
Can I make the webview smaller at the top and add some background color/gradient or something? As you can see in the picture when I scroll down I can see content by the sides of the speaker and above the menu bar (which should be at the very top of the webview)
This is the start of my class definition:
public partial class WebViewController : UIViewController
{
LoadingOverlay loadPop;
bool loadPopStatus = false;
public override bool PrefersStatusBarHidden(){
return true;
}
static bool UserInterfaceIdiomIsPhone
{
get { return UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone; }
}
protected WebViewController(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
NSUserDefaults.StandardUserDefaults.Synchronize();
var username = NSUserDefaults.StandardUserDefaults.StringForKey("username");
var login_token = NSUserDefaults.StandardUserDefaults.StringForKey("login_token");
var refresh_token = NSUserDefaults.StandardUserDefaults.StringForKey("refresh_token");
var company_name = NSUserDefaults.StandardUserDefaults.StringForKey("company");
// Intercept URL loading to handle native calls from browser
WebView.ShouldStartLoad += HandleShouldStartLoad;
//Change status bar background
//WebView.ScrollView.ContentInset = new UIEdgeInsets(20, 20, 20, 20);
//WebView.ScrollView.BackgroundColor = UIColor.Clear;
//WebView.BackgroundColor = UIColor.Clear;
//WebView.ScrollView.ContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.Never;
You can see some of my failed attempts commented out in my webviewcontroller definition. I tried insents and other stuff
You can set the correct constraints to this WebView to make it smaller. The top and bottom constraints of the WebView should connect to the TopLayoutGuide and BottomLayoutGuide, so that iPhone X's "head" and "foot" will not be used.
I will show my Storyboard screenshot for these four constraints below:
But use code to create the constraints may be more clearly:
// Disable this property to enable autolayout
MyWebView.TranslatesAutoresizingMaskIntoConstraints = false;
var leadConstraint = NSLayoutConstraint.Create(MyWebView, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, View, NSLayoutAttribute.Leading, 1.0f, 0);
var topConstraint = NSLayoutConstraint.Create(MyWebView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, TopLayoutGuide, NSLayoutAttribute.Bottom, 1.0f, 0);
var trailingConstraint = NSLayoutConstraint.Create(MyWebView, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, View, NSLayoutAttribute.Trailing, 1.0f, 0);
var bottomConstraint = NSLayoutConstraint.Create(MyWebView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, BottomLayoutGuide, NSLayoutAttribute.Top, 1.0f, 0);
View.AddConstraints(new NSLayoutConstraint[] { leadConstraint, topConstraint, trailingConstraint, bottomConstraint });
This will make a space at the top and bottom of the iPhone X which we should not use and we just call it safe area.
If you want to make it look like a component of the WebView, you can set the View's Background color the same as your WebView's. It seems purple red from your screenshot. Maybe like this:
View.BackgroundColor = UIColor.Purple;
I have uicollectionview and each cell has a SelectedBackgroundView property with just the background colour like this:
SelectedBackgroundView = new UIView { BackgroundColor = UIColor.Green };
How would I set the width of the selectedbackgroundview? I need it to be half the default value.
I have tried:
SelectedBackgroundView.Frame = new CGRect(SelectedBackgroundView.Frame.X, SelectedBackgroundView.Frame.Y, SelectedBackgroundView.Frame.Width / 2, SelectedBackgroundView.Frame.Height / 2);
But this just distorts the view
This where I put the code:
[Export ("initWithFrame:")]
public PhotoCell(CGRect frame) : base(frame)
{
//BackgroundView = new UIView { BackgroundColor = UIColor.Clear };
SelectedBackgroundView = new UIView { BackgroundColor = UIColor.Green };
this.AddConstraint(NSLayoutConstraint.Create(this.SelectedBackgroundView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1, this.Bounds.Height / 2));
imageView = new UIImageView(frame); // set as you want
ContentView.AddSubview(imageView);
}
Why not add constraints?
You can specify the width and height constraints as NSLayoutConstraints and then add them to your UICollectionViewCell using the AddConstraint method. Here's an example in F#:
myCell.AddConstraint(NSLayoutConstraint.Create(SelectedBackgroundView, NSLayoutAttribute.Height, NSLayoutRelation.Equal,null,NSLayoutAttribute.NoAttribute, 1, myHeightValue))
It would be very similar, if not identical in C#
This code solved my problem:
SelectedBackgroundView.Frame = new CGRect(SelectedBackgroundView.Frame.X + 5, SelectedBackgroundView.Frame.Y + 5, SelectedBackgroundView.Frame.Width-10, SelectedBackgroundView.Frame.Height-10);
How to create design chatting like whatsapp (ios xamarin).
Just like in the picture below:
My code:
ContentView.AddConstraints(NSLayoutConstraint.FromVisualFormat("H:|[bubble]",
0,"bubble", BubbleImageView));
ContentView.AddConstraints(NSLayoutConstraint.FromVisualFormat("V:|-2-[bubble]-2-|",0,"bubble", BubbleImageView
));
BubbleImageView.AddConstraints(NSLayoutConstraint.FromVisualFormat("H:[bubble(>=48)]",0,"bubble", BubbleImageView));
//setting layout for Image Picture
var vSpaceTopAttch = NSLayoutConstraint.Create(ImgPicture, NSLayoutAttribute.Top, NSLayoutRelation.Equal, BubbleImageView, NSLayoutAttribute.Top, 1, 10);
ContentView.AddConstraint(vSpaceTopAttch);
//setting layout for Message Label
var vSpaceTop = NSLayoutConstraint.Create(MessageLabel, NSLayoutAttribute.Top, NSLayoutRelation.Equal, BubbleImageView, NSLayoutAttribute.Top, 1, 10);
ContentView.AddConstraint(vSpaceTop);
var vSpaceBottom = NSLayoutConstraint.Create(MessageLabel, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, BubbleImageView, NSLayoutAttribute.Bottom, 1, -10);
ContentView.AddConstraint(vSpaceBottom);
var msgLeading = NSLayoutConstraint.Create(MessageLabel, NSLayoutAttribute.Leading, NSLayoutRelation.GreaterThanOrEqual, BubbleImageView, NSLayoutAttribute.Leading, 1, 16);
ContentView.AddConstraint(msgLeading);
var msgCenter = NSLayoutConstraint.Create(MessageLabel, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, BubbleImageView, NSLayoutAttribute.CenterX, 1, 3);
ContentView.AddConstraint(msgCenter);
Result from this code:
Position image are behind BubbleImageView.
How to design the layout like whatsapp in ios xamarin?
Have you tried bringing the subview with the image to the front with:
ContentView.BringSubviewToFront(yourImageSubView);
?
In my xamarin iOS app I have a list view, I want to show the loading icon when it is being loading. But, I do not want to disable the whole page. I want the user to still go back if they wish to, using back navigation.
I used this as a reference.
So, I'm trying to set the CGRect Frame, to leave the navigation on the top active and disable the rest of the page during loading status.
I am using something like this: new CGRect(30, 0,0, 0) to leave 30 units from the top but it doesnt work. Can anyone help me out to have a frame to leave just navigation bar and cover rest of the page?
AutoLayout is a much better way to accomplish this task than using frames. Unless you need to target REALLY, REALLY old versions of iOS, AutoLayout is generally the way to go.
I'm assuming you are using a UIViewController and not a UITableViewController. This is an important distinction, because the UITableViewController only allows you to add to the UITableView which makes this task much more challenging.
Add this AddAnOverlay method to your UIViewController class, then call it whenever you want to display an overlay. You will probably need to put overlay in an instance variable so that you can remove it later. Remove it by calling overlay.RemoveFromSuperview() and you're done.
void AddAnOverlay()
{
var overlay = new UIView();
overlay.BackgroundColor = UIColor.Black.ColorWithAlpha(0.45f); // or whatever colo
overlay.TranslatesAutoresizingMaskIntoConstraints = false;
var label = new UILabel();
label.TranslatesAutoresizingMaskIntoConstraints = false;
label.Text = "Loading Fantastic Things!";
var spinner = new UIActivityIndicatorView();
spinner.TranslatesAutoresizingMaskIntoConstraints = false;
spinner.StartAnimating();
overlay.AddSubview(spinner);
overlay.AddConstraint(NSLayoutConstraint.Create(overlay, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, spinner, NSLayoutAttribute.CenterX, 1, 0));
overlay.AddConstraint(NSLayoutConstraint.Create(overlay, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, spinner, NSLayoutAttribute.CenterY, 1, 0));
overlay.AddSubview(label);
// can adjust space between by changing -30 to whatever
overlay.AddConstraint(NSLayoutConstraint.Create(spinner, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, label, NSLayoutAttribute.Top, 1, -30));
overlay.AddConstraint(NSLayoutConstraint.Create(overlay, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, label, NSLayoutAttribute.CenterX, 1, 0));
View.AddSubview(overlay);
View.AddConstraint(NSLayoutConstraint.Create(TopLayoutGuide, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, overlay, NSLayoutAttribute.Top, 1, 0));
View.AddConstraint(NSLayoutConstraint.Create(View, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, overlay, NSLayoutAttribute.CenterX, 1, 0));
View.AddConstraint(NSLayoutConstraint.Create(View, NSLayoutAttribute.Width, NSLayoutRelation.Equal, overlay, NSLayoutAttribute.Width, 1, 0));
View.AddConstraint(NSLayoutConstraint.Create(BottomLayoutGuide, NSLayoutAttribute.Top, NSLayoutRelation.Equal, overlay, NSLayoutAttribute.Bottom, 1, 0));
}
Notice the TopLayoutGuide and BottomLayoutGuide in the NSLayoutConstraint. These represent the top and bottom of your current view controller, so they can be used to size things so they don't hide navigation bars, tab bars, etc.
You have to add the overlay to the table view, which leads you to a centering problem. For this there are some options: recalculate the position of the overlay when scrolling, add an additional layer behind the table view which you reference with autolayout for positioning, ...
I'm using autolayout and you should avoid giving actual numbers, but it is also possible using bounds. Also be aware of if the user navigates away you have to cancel the task!
UPDATE
Now Solved The problem was that when I was updating the bottomConstraint I was setting the Constant to the bottom padding property. Sounds reasonable but of course the Constant should have been set to 0 - BottomPadding. That explains why the bottom of the text was being not visible, it was being constrained beyond its clipping container.
I have a simple UIView custom control called PaddedLabel that wraps (not inherits) a UILabel
The view hierarchy is
PaddedLabel -> UILabel
When the constraints on the UILabel have their constants updated the outer View does not chnage height. It is as if the outer UIView is seeing only the Height of the Label as the Height it needs rather than the Height of the Label plus constants. This is how it looks
In UpdateConstraints I add some constraints and if there is a Text value I set the Constant on the Constraint to the value I want for padding else I set the Constant to 0.
public override void UpdateConstraints()
{
base.UpdateConstraints();
if (this.constraintsApplied == false)
{
this.leftConstraint =
NSLayoutConstraint.Create(this.NestedLabel, NSLayoutAttribute.Left, NSLayoutRelation.Equal, this, NSLayoutAttribute.Left, 1.0f, this.LeftPadding);
this.AddConstraint(this.leftConstraint);
this.rightConstraint =
NSLayoutConstraint.Create(this.NestedLabel, NSLayoutAttribute.Right, NSLayoutRelation.Equal, this, NSLayoutAttribute.Right, 1.0f, 0 - this.RightPadding);
this.AddConstraint(this.rightConstraint);
this.topConstraint =
NSLayoutConstraint.Create(this.NestedLabel, NSLayoutAttribute.Top, NSLayoutRelation.Equal, this, NSLayoutAttribute.Top, 1.0f, this.TopPadding);
this.AddConstraint(this.topConstraint);
this.bottomConstraint =
NSLayoutConstraint.Create(this.NestedLabel, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, this, NSLayoutAttribute.Bottom, 1.0f, 0 - this.BottomPadding);
this.AddConstraint(this.bottomConstraint);
this.constraintsApplied = true;
}
if (this.Text.HasValue())
{
this.topConstraint.Constant = this.TopPadding;
// The following code was the problem.
// It should have been 0 - this.BottomPadding Now corrected
// this.bottomConstraint.Constant = this.BottomPadding;</del>
this.bottomConstraint.Constant = 0 - this.BottomPadding;
}
else
{
this.topConstraint.Constant = 0;
this.bottomConstraint.Constant = 0;
}
}
When the Text property is set I set the Text property on the inner UILabel and call SetNeedsUpdateConstraints
public string Text
{
get
{
return this.text;
}
set
{
if (this.text == value)
{
return;
}
this.text = value;
this.nestedLabel.Text = value;
this.SetNeedsUpdateConstraints();
}
}
If you want the PaddedLabel view to expand and fit around the inside UILabel, change the bottom constraint. You want to tie the bottom of PaddedLabel to the bottom of the UILabel, so as the UILabel grows it makes PaddedLabel expand! The way it is now, you're telling the UILabel to squish itself inside of the PaddedLabel view.
Reverse the bottomConstraint and you should be set.