I have the following CustomRenderer to apply a style to buttons in my iOS project of my cross-platform Xamarin.Forms app.
The button used to have rounded edges, white text, and a blue gradient background.
Everything has been working just fine up until I downloaded Xcode 8.1. Since moving to 8.1, the same code will not present the background gradient. Can anyone see how I could change my code to get the background gradient working again?
The border radius and text color are all working as usual - it's just the background gradient which is missing.
[assembly: ExportRenderer(typeof(CustomButton), typeof(CustomButtonRenderer))]
namespace MyApp.Forms.iOS.CustomRenderers
{
class CustomButtonRenderer : ButtonRenderer
{
public override void LayoutSubviews()
{
foreach (var layer in Control?.Layer.Sublayers.Where(layer => layer is CAGradientLayer))
{
layer.Frame = Control.Bounds;
}
base.LayoutSubviews();
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
var gradient = new CAGradientLayer();
gradient.CornerRadius = Control.Layer.CornerRadius = 10;
gradient.Colors = new CGColor[]
{
UIColor.FromRGB(153, 204, 255).CGColor,
UIColor.FromRGB(51, 102, 204).CGColor
};
var layer = Control?.Layer.Sublayers.LastOrDefault();
Control?.Layer.InsertSublayerBelow(gradient, layer);
Control.SetTitleColor(UIColor.White, UIControlState.Normal);
Control.Layer.BorderColor = UIColor.FromRGB(51, 102, 204).CGColor;
Control.Layer.BorderWidth = 1;
}
}
}
}
Ok so I have finally worked out what was going on. In the LayoutSubviews method where I was setting each layer.Frame to the value of Control.Bounds, I noticed that Control.Bounds was a rectangle full of zeros, so my gradient was therefore 0 pixels in size.
I have modified the method as follows and it now works as expected again:
public override void LayoutSubviews()
{
var newBounds = Element.Bounds.ToRectangleF();
foreach (var layer in Control?.Layer.Sublayers.Where(layer => layer is CAGradientLayer))
{
layer.Frame = new CGRect(0, 0, newBounds.Width, newBounds.Height);
}
base.LayoutSubviews();
}
I'm not sure if this is a hack, but it seems to do the job - for now...
Related
I'm developing in Xamarin and I don't know how change the height of navigation bar.
For android is easier because you've got a clear property "ActionBarSize"
I've tried a lot of things. Create a comun NavigationPage with HeightRequest property does not work
Thanks a lot
In iOS we could set a custom TitlView by using custom renderer .
using Foundation;
using UIKit;
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms;
using xxx.iOS;
using CoreGraphics;
using xxx;
using ObjCRuntime;
[assembly: ExportRenderer(typeof(ContentPage), typeof(MyPageRenderer))]
namespace xxx.iOS
{
public class MyPageRenderer: PageRenderer
{
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
var page = Element as ContentPage;
NavigationController.NavigationBar.Hidden = true;
double height = IsiphoneX();
UIView backView = new UIView()
{
BackgroundColor = UIColor.White,
Frame = new CGRect(0,20,UIScreen.MainScreen.Bounds.Width, height),
};
UIButton backBtn = new UIButton() {
Frame = new CGRect(20, height-44, 40, 44),
Font = UIFont.SystemFontOfSize(18),
} ;
backBtn.SetTitle("Back", UIControlState.Normal);
backBtn.SetTitleColor(UIColor.Blue, UIControlState.Normal);
backBtn.AddTarget(this,new Selector("GoBack"),UIControlEvent.TouchUpInside);
UILabel titleLabel = new UILabel() {
Frame=new CGRect(UIScreen.MainScreen.Bounds.Width/2-75, 0,150, height),
Font = UIFont.SystemFontOfSize(20),
Text = page.Title,
TextColor = UIColor.Black,
Lines = 0,
};
UILabel line = new UILabel() {
Frame = new CGRect(0, height, UIScreen.MainScreen.Bounds.Width, 0.5),
BackgroundColor = UIColor.Black,
};
backView.AddSubview(backBtn);
backView.AddSubview(titleLabel);
backView.AddSubview(line);
View.AddSubview(backView);
}
double IsiphoneX()
{
double height = 44; //set height as you want here !!!
if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
{
if (UIApplication.SharedApplication.Delegate.GetWindow().SafeAreaInsets.Bottom > 0.0)
{
height = 64; //set height as you want here !!!
}
}
return height;
}
[Export("GoBack")]
void GoBack()
{
NavigationController.PopViewController(true);
}
public override void ViewWillDisappear(bool animated)
{
base.ViewWillDisappear(animated);
NavigationController.NavigationBar.Hidden = false;
}
}
}
Im just set custom font on all text area but fonts creating little longer than space on place. Upper side of text cutting. I fixed it on label items with set lineheight to 1.2. But i cant doin it on my navigation title and entry boxes.
This is my navigation custom renderer:
public override void ViewDidLoad()
{
base.ViewDidLoad();
UINavigationBar.Appearance.SetBackgroundImage(new UIImage(), UIBarMetrics.Default);
UINavigationBar.Appearance.ShadowImage = new UIImage();
UINavigationBar.Appearance.BackgroundColor = UIColor.Clear;
UINavigationBar.Appearance.TintColor = UIColor.White;
UINavigationBar.Appearance.BarTintColor = UIColor.Clear;
UINavigationBar.Appearance.Translucent = true;
UINavigationBar.Appearance.SetTitleTextAttributes(new UITextAttributes()
{
Font = UIFont.FromName("CooperHewitt-Bold", 20),
TextColor = UIColor.White
});
}
I need to set line height on entry too.
You can create a custom Navigation Bar and set the style of it as you want.
in Customrenderer
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
NavigationController.NavigationBar.Hidden = true;
double height = IsiphoneX();
UIView backView = new UIView()
{
BackgroundColor = UIColor.White,
Frame = new CGRect(0,20,UIScreen.MainScreen.Bounds.Width, height),
};
UIButton backBtn = new UIButton() {
Frame = new CGRect(20, height-44, 40, 44),
Font = UIFont.SystemFontOfSize(18),
} ;
backBtn.SetTitle("Back", UIControlState.Normal);
backBtn.SetTitleColor(UIColor.Blue, UIControlState.Normal);
backBtn.AddTarget(this,new Selector("GoBack"),UIControlEvent.TouchUpInside);
UILabel titleLabel = new UILabel()
{
Frame=new CGRect(UIScreen.MainScreen.Bounds.Width/2-75, 0,150, height),
Font = UIFont.FromName("CooperHewitt-Bold", 20),
Text = "xxx",
TextColor = UIColor.Black,
Lines = 0,
};
UILabel line = new UILabel() {
Frame = new CGRect(0, height, UIScreen.MainScreen.Bounds.Width, 0.5),
BackgroundColor = UIColor.Black,
};
backView.AddSubview(backBtn);
backView.AddSubview(titleLabel);
backView.AddSubview(line);
View.AddSubview(backView);
}
double IsiphoneX()
{
double height = 44;
if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
{
if(UIApplication.SharedApplication.Delegate.GetWindow().SafeAreaInsets.Bottom > 0.0)
{
height = 64;
}
}
return height;
}
[Export("GoBack")]
void GoBack()
{
NavigationController.PopViewController(true);
}
public override void ViewWillDisappear(bool animated)
{
base.ViewWillDisappear(animated);
NavigationController.NavigationBar.Hidden = false;
}
You can set the property of title , backButton and navigationBar as you need (such as text , color ,BackgroundColor ,font e.g.)
For entry , you can also set height in CustomRenderer
using UIKit;
using xxx.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using CoreGraphics;
[assembly: ExportRenderer(typeof(Entry), typeof(MyEnterRenderer))]
namespace xxx.iOS
{
public class MyEnterRenderer:EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if(Control!=null)
{
SetNativeControl(new CustomTextField());
}
}
}
public class CustomTextField:UITextField
{
public CustomTextField()
{
Font = UIFont.SystemFontOfSize(20,2);
}
}
}
I just solved my issue with make a new view and set it as TitleView.
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
//....
x:Class="MyApp.Views.CustomNavTitle">
<StackLayout x:Name="stack" VerticalOptions="Center" HorizontalOptions="FillAndExpand" Margin="0,0,25,0">
<Label Style="{StaticResource NavigationBarTitle}" Text="{Binding .}"/>
</StackLayout>
</ContentView>
And set it if it was IOS device on my content pages constructor.
if (Device.RuntimePlatform == Device.iOS)
NavigationPage.SetTitleView(this, new CustomNavTitle() { BindingContext = Title });
And I setted "LineHeight" (as 1.2) prop and set custom font family which i want to the label in NavigationBarTitle style.
I am working on Xamarin.iOS, I want to display UIPopViewController in iphone and iPad in center Screen. The below way I try the code :
public override void ViewDidLoad()
{
base.ViewDidLoad();
showButton.TouchUpInside += (sender, e) => {
// Create a UIImage view to show in the popover
UIImageView monkeyIcon = new UIImageView(new CGRect(20, 20, 200, 200));
monkeyIcon.Image = UIImage.FromFile("Abc.png");
monkeyIcon.UserInteractionEnabled = true;
// Create a view controller to act as the popover
UIViewController popover = new UIViewController();
popover.View = monkeyIcon;
popover.ModalPresentationStyle = UIModalPresentationStyle.Popover;
// Grab Image
var image = UIImage.FromFile("298-circlex.png");
// Add a close button
var closeButton = new UIButton(new CGRect(0, 20, 200, 200));
closeButton.UserInteractionEnabled = true;
closeButton.SetTitle("Close", UIControlState.Normal);
monkeyIcon.AddSubview(closeButton);
// Wireup the close button
closeButton.TouchUpInside += (button, e2) => {
popover.DismissViewController(true, null);
};
// Present the popover
PresentViewController(popover, true, null);
// Configure the popover for the iPad, the popover displays as a modal view on the
//iPhone
UIPopoverPresentationController presentationPopover = popover.PopoverPresentationController;
if (presentationPopover != null)
{
presentationPopover.SourceView = this.View;
presentationPopover.PermittedArrowDirections = 0;
presentationPopover.SourceRect = showButton.Frame;
presentationPopover.Delegate = this;
}
};
}
[Export("adaptivePresentationStyleForPresentationController:")]
public UIModalPresentationStyle GetAdaptivePresentationStyle(UIPresentationController forPresentationController)
{
return UIModalPresentationStyle.None;
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
I tried all the answer in SO and google but nothing is help to me.
Problem 1 :
- In Iphone the PopViewController is displaying in the full Screen, but I want to center and small PopView.
Problem 2 :
- In Ipad the PopViewController is displaying in the LeftSide I want to display it Center.
Any Help will be Appreciated.
If you don't want this PopoverPresentationController to be shown full screen, you should set a size to its owner Controller: popover.PreferredContentSize = new CGSize(200, 200);. Also you should set the PopoverPresentationController's configuration firstly before you present the popover.
In Ipad the PopViewController is displaying in the LeftSide I want to
display it Center.
SourceRect means the rectangle in the specified view in which to anchor the popover. You want to show this pop in the center, set this to your View.Frame. Here is my code for you referring to:
UIPopoverPresentationController presentationPopover = popover.PopoverPresentationController;
if (presentationPopover != null)
{
presentationPopover.SourceView = this.View;
presentationPopover.PermittedArrowDirections = 0;
presentationPopover.SourceRect = View.Frame;
//Configure this Delegate first before presenting.
presentationPopover.Delegate = this;
}
PresentViewController(popover, true, null);
I have been developing a Xamarin forms application. I want to increase the height of the progress bar control. I used custom renders to change the color of the progress control. But I couldn't find any way to increase the height. Please help me. following is my Custom render class.
public class MyProgressBarRenderer:ProgressBarRenderer
{
protected override void OnElementChanged (
ElementChangedEventArgs<Xamarin.Forms.ProgressBar> e)
{
base.OnElementChanged (e);
Control.ProgressTintColor = Color.FromHex ("#254f5e").ToUIColor();
}
}
Add this override to MyProgressBarRenderer, and adjust Y as necessary....
using UIKit;
using CoreGraphics;
......
public override void LayoutSubviews()
{
base.LayoutSubviews();
var X = 1.0f;
var Y = 5.0f;
CGAffineTransform transform = CGAffineTransform.MakeScale(X,Y);
this.Transform = transform;
}
There is small issue in the iOS renderer code try using
this.Control.Transform = transform;
instead of
this.Transform = transform;
I've created a launch animation in Xamarin for an iOS app but I can't seem to get the images to fade in and out gracefully. I think I need to use the .FadeTo() method but I'm unable to apply it to my code properly. I'm trying to get the first image to fade in then fade out while the second image fades in and so on. Any help is appreciated - I'm a newb!
Here's my code:
using System.Drawing;
using MonoTouch.UIKit;
namespace MapView {
public class ImageViewController : UIViewController {
UIImageView animatedlaunchImage;
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
Title = "Animated ImageView";
View.BackgroundColor = UIColor.White;
// an animating image
animatedlaunchImage = new UIImageView();
animatedlaunchImage.AnimationImages = new UIImage[] {
UIImage.FromBundle ("Splash01.png")
, UIImage.FromBundle ("Splash02.png")
, UIImage.FromBundle ("Splash03.png")
, UIImage.FromBundle ("Splash04.png")
, UIImage.FromBundle ("Splash05.png")
} ;
animatedlaunchImage.AnimationRepeatCount = 1;
animatedlaunchImage.AnimationDuration = 3;
animatedlaunchImage.Frame = new RectangleF(0, 0, 320, 568);
View.AddSubview(animatedlaunchImage);
animatedlaunchImage.StartAnimating ();
}
}
}
Include CoreAnimation and add these lines of code after you create the UIImageView,
CATransition customTransition = new CATransition();
customTransition.FadeInDuration = 1.0f;
customTransition.FadeOutDuration = 1.0f;
customTransition.TimingFunction = CAMediaTimingFunction.FromName(
CAMediaTimingFunction.EaseInEaseOut);
customTransition.Type = CATransition.TransitionFade;
animatedlaunchImage.Layer.AddAnimation(customTransition, null);
Translated from this objective-c question.