Xamarin Forms Redraw StackLayout on Device Orientation Change - xamarin

In my MainPage.xaml, which is a ContentPage, I have a GradientColorStack.
<local:GradientColorStack x:Name="ColorStack" StartColor="#FF0000" EndColor="#FFFF00">
This class has StackLayout as a base class and it presents a background that has a gradient color fill. I got this idea from here.
public class GradientColorStack : StackLayout
The problem is that on device orientation change, the background color fill is not re-drawn. Thus in landscape orientation there is a big gap filled with black where you can see through the GradientColorStack to the ContentPage background.
Is there a way to force the GradientColorStack to re-draw on device orientation change?

iOS Version
I added the following method to my renderer class:
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
SetNeedsDisplay();
base.OnElementPropertyChanged(sender, e);
}
This causes the Draw() method of the same class to be called on a screen orientation event. In Draw() I now find the existing CAGradientLayer (if it exists) and remove it from the super layer and then just let the Draw() routine then calculate a new CAGradientLayer as usual, which it then adds to the NativeView.Layer.Sublayers collection as usual.
Thanks to #SHUBHAM SHARMA for the tip of using SetNeedsDisplay() but this post was also required to get the solution working.
Android Version
It turns out the Android version was already working to correctly redraw the gradient layer (see tutorial). I think this is because of the following method in my renderer class:
protected override void OnElementChanged(ElementChangedEventArgs<StackLayout> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
{
return;
}
var stack = e.NewElement as GradientColorStack;
this.StartColor = stack.StartColor;
this.EndColor = stack.EndColor;
}

You can use ForceLayout() in android Renderer and SetNeedDisplay() in iOS Renderer because these function are forcefully refresh the layout.

Related

Custom switch does not show On/Off Image in Xamarin Forms

https://www.c-sharpcorner.com/article/how-to-create-and-use-a-custom-switch-control-in-xamarin-forms/
"OnImage" and "OffImage" does not work when i make a custom renderer following the guide above. I see no image when i click on or off.
In my class, I send in a HTTP url and then convert that URL to a UIImage. It works successfully as i've added breakpoints all the way. I even tried with a image in my library to see if that would change the outcome but it didnt.
public class Switch_iOS : SwitchRenderer
{
Version version = new Version(ObjCRuntime.Constants.Version);
protected override void OnElementChanged(ElementChangedEventArgs<Switch> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || e.NewElement == null)
return;
var view = (CustomSwitch)Element;
if (!string.IsNullOrEmpty(view.SwitchThumbImage))
{
if (version > new Version(6, 0))
{
Control.OnImage = FromUrl(view.SwitchThumbImage);
Control.OffImage = FromUrl(view.SwitchThumbImage);
}
else
{
Control.ThumbTintColor = view.SwitchThumbColor.ToUIColor();
}
}
}
public UIImage FromUrl(string uri)
{
using (var url = new NSUrl(uri))
using (var data = NSData.FromUrl(url))
return UIImage.LoadFromData(data);
}
}
Is "Control.OnImage" and "Control.OffImage" not working with the latest Xamarin Forms? I also intend to make a background image to the switch.
Unfortunately , about OnImage and OffImage of UISwitch , from iOS 7 has no effect.
Have a look at the apple document :
In iOS 7 and later, this property has no effect.
In iOS 6, this image represents the interior contents of the switch.
The image you specify is composited with the switch’s rounded bezel
and thumb to create the final appearance.
Instead you can use
onTintColor to set the tint color of the switch when it is turned on.
tintColor to set the tint color of the switch when it is turned off.
thumbTintColor to set the tint color of the thumb.

Change BoxView color on Tap

I have a BoxView that I want to change the color of when the user taps it. I created a BoxView called tapView and set the GestureRecognizer like so:
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += (s, e) => {
// handle the tap
OnTapGestureRecognizerTapped(s, e);
};
tapView.GestureRecognizers.Add(tapGestureRecognizer);
and my method to handle the tap:
void OnTapGestureRecognizerTapped(object sender, EventArgs args)
{
var box = (BoxView)sender;
box.Color = Color.Red;
}
However this doesn't actually change the color on the Tap. Debugging and stepping through the code it does actually update the BoxView color in the code but not on the screen. What do I need to do to make this actually update the color when touched?
Try this solution, assuming you give your BoxView the following property in your XAML x:Name="myBox"
//This code betlow the page InitializeComponent call
var boxTapHandler = new TapGestureRecognizer();
boxTapHandler.Tapped += ChangeColor;
myBox.GestureRecognizers.Add(boxTapHandler);
Change color method, similar, though referencing the BoxView by name
private void ChangeColor(object sender, EventArgs args)
{
myBox.Color = Color.red;
}
So I discovered as standalone code this works ok, but in my MVVM app it does not. I wound up creating a box on top and changing the opacity on a tap worked just fine.

How to display globe view (3D view) of Maps in Xamarn.forms

We need to show selected cities on 3D map of earth in Android, iOS & Windows.UWP using Xamarin.Forms. Currently we are using Xamarin.Forms.Maps, but it only shows 2D map of earth.
How do we go for 3D map of earth?
Note: We will require zoom-in feature of map as well.
If you want something like Google Earth you're probably going to have to create your own implementation. What you can do in Xamarin Forms however is use the existing Xamarin.Forms.Maps controls and add what's called a camera. Basically this is a viewpoint from which you look upon the map. These can be in 3D space so it looks like you have a 3D map. You can create this using custom renderers.
Within these custom renderers you will come across things like pitch, heading and distance. This image show what's what:
iOS custom renderer
[assembly: ExportRenderer(typeof(Map3d), typeof(MapView3dRenderer))]
namespace MyApp.iOS.Renderers
{
public class MapView3dRenderer : MapRenderer
{
MKMapView _nativeMap;
protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
base.OnElementChanged(e);
if (e.NewElement != null && Control != null)
{
_nativeMap = Control as MKMapView;
}
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (_nativeMap == null)
return;
if (e.PropertyName == "VisibleRegion")
UpdateCameraView();
}
void UpdateCameraView()
{
var target = new CLLocationCoordinate2D(50.890119f, 5.857798f);
//Enable 3D buildings
_nativeMap.ShowsBuildings = true;
_nativeMap.PitchEnabled = true;
// Attach the camera
var camera = MKMapCamera.CameraLookingAtCenterCoordinate(target, 650, 60, 0);
_nativeMap.Camera = camera;
}
}
}
Android
For Android I don't have a custom renderer ready but you should be able to figure it out. It also involves attaching a Camera object. This time you add it to an instance of GoogleMap.
// Create the camera
CameraPosition cameraPosition = new CameraPosition.Builder()
.Target(location)
.Tilt(45)
.Zoom(10)
.Bearing(0)
.Build();
// Convert to an update object
CameraUpdate cameraUpdate = CameraUpdateFactory.NewCameraPosition(cameraPosition);
// Attach the camera
map.MoveCamera(cameraUpdate); // map is of type GoogleMap
Check out the Android docs on how this works.

How to assign Background Image to an entry in xamarin forms for ios

I am trying to add background image to an entry in xamarin forms and i wrote code for rendering in ios and android. For android it is working and for ios it is not working.
Here I am sharing rendering code for ios:
[assembly: ExportRenderer (typeof(ExtendedUsername), typeof(RenderingEntryuname))]
namespace ifind.iOS
{
public class RenderingEntryuname: EntryRenderer
{
// Override the OnElementChanged method so we can tweak this renderer post-initial setup
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null) {
Control.TextAlignment=UITextAlignment.Center;
UIImage img=UIImage.FromFile("Images/newimg.jpg");
Control.Background=img
}
}
}
}
By default the UITextEntry used for a Forms Entry will have its border style set to UITextBorderStyle.RoundedRect and thus any background will be ignored.
Set the border style to none and your image will show up:
if (Control != null) {
Control.BorderStyle = UITextBorderStyle.None;
Control.TextAlignment=UITextAlignment.Center;
UIImage img=UIImage.FromFile("Images/newimg.jpg");
Control.Background=img
}
If the value is set to the UITextBorderStyleRoundedRect style, the custom background image associated with the text field is ignored.
Ref: UITextField

Change EditText Cursor Color in Xamarin Forms

I have an Entry in my ContentPage and am doing rendering in Xamarin Android.
Here my problem is EditText background color is white and cursor color is also white.
Here I want to change the cursor color to black.
Is there any way to change the cursor color?
Here is my code.
Entry to ExtendedEntry :
public class ExtendedEntry : Entry { }
Use ExtendedEntry in Content Page :
var txtPhoneNumber = new ExtendedEntry { Placeholder = "Phone Number", Keyboard = Keyboard.Numeric, TextColor = Color.Black };
Render the ExtendedEntry in Xamarin Android :
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms;
[assembly: ExportRenderer(typeof(ExtendedEntry), typeof(ExtendedEntryRender))]
namespace Project.Droid
{
public class ExtendedEntryRender : EntryRenderer
{
// Override the OnElementChanged method so we can tweak this renderer post-initial setup
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{ // perform initial setup
// lets get a reference to the native control
var nativeEditText = (global::Android.Widget.EditText)Control;
// do whatever you want to the textField here!
nativeEditText.SetBackgroundResource(Resource.Drawable.text_box);
}
}
}
}
Can any one help me to solve this problem?
Thanks in advance.
You can change the cursor color using:
IntPtr IntPtrtextViewClass = JNIEnv.FindClass(typeof(TextView));
IntPtr mCursorDrawableResProperty = JNIEnv.GetFieldID (IntPtrtextViewClass, "mCursorDrawableRes", "I");
JNIEnv.SetField (Control.Handle, mCursorDrawableResProperty, 0); // replace 0 with a Resource.Drawable.my_cursor
0 will keep the same color as the TextColor on your Entry.
Edit: To change the cursur color the only option is to change the theme by adding for example:
Theme = "android:style/Theme.Holo.light" in MainActivity

Resources