Custom PageRenderer or NavigationRenderer not working (virtual missing?) - xamarin

Currently I'm working on a Win Phone 8.1 project and need some Custom Renderer for ContentPage and NavigationPages.
But when I tried to implement it i saw there is no possibility for overwrite the OnElementChanged Method. After some minutes with DotPeek I saw that those methods not are virtual like on other plattforms. So does anybody have an idea or a workaround for implementing custom rederers on Windows RT?
Tried on Xamarin.Forms: 2.0.0.6490 & 2.1.0.6529
Sincerely

You can use the Event ElementChanged.
public class MyRender: NavigationPageRenderer
{
public MyRender()
{
ElementChanged += OnElementChanged;
}
private void OnElementChanged(object sender, VisualElementChangedEventArgs visualElementChangedEventArgs)
{
// do some stuff here
}
}

Related

How to Cluster Xamarin.Forms.GoogleMaps Pin in PCL Project

Since I am doing a map based cross-platform project on Xamarin, And I'm stuck to the point where I need to cluster markers when zooming out.
things I had tried:
GoogleMapUtility Project.
And tried to use ClusterManager of GoogleMapUtility through dependency. so that I can add a pin to cluster manager From PCL project. But to initialize cluster manager I need a Native Map instance i.e. Android.Gms.Maps.GoogleMap.(don't know how to get)
I know I can achieve it with that with custom map renderer, but I cant do that coz. a lot of code related to map is already written, I don't want to rewrite a Code. So Is there any possibility that I can get a native instance of the map that I can use on dependency service.
I created CustomRenderer For Map without creating a customMap class at PCL (inherit Map class) the code is below. but it's not get triggered. What wrong I am doing here...
custom renderer code:
[assembly: ExportRenderer(typeof(Map), typeof(MarkerClusterRenderer))]
namespace SamplingApp.Droid.CustomRenderers
{
public class MarkerClusterRenderer : MapRenderer
{
ClusterManager _clusterManager;
protected override void OnMarkerCreated(Pin outerItem, Marker innerItem)
{
base.OnMarkerCreated(outerItem, innerItem);
AddToMarkerCluster();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
}
protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
}
public void AddToMarkerCluster()
{
_clusterManager = new ClusterManager(Android.App.Application.Context, NativeMap);
//[do other things here]
}
}
}
since I am is new to xamarin. little guidance is appreciated.
am I in the right direction?
Thank you in advance. and sorry for my English.
I created CustomRenderer For Map without creating a customMap class at PCL (inherit Map class) the code is below. but it's not get triggered. What wrong I am doing here...
If you want to customize the map, you need to create a custom class for map control in PCL:
public class CustomMap:Map
{
}
And use it in xaml:
<local:CustomMap WidthRequest="320" HeightRequest="200"
x:Name="MyMap"
IsShowingUser="true"
MapType="Hybrid"/>
And renderer:
[assembly:ExportRenderer(typeof(SamplingApp.CustomMap),
typeof(MarkerClusterRenderer))]
namespace SamplingApp.Droid.CustomRenderers
{
public class MarkerClusterRenderer:MapRenderer
{
...
Then, your renderer's codes will be triggered correctly.

Xamarin WebViewRenderer.OnElementChanged gets called with null native controll on Xamarin Forms 2.5

I am using my own customrenderer for Webviews it has always worked but since I upgraded Xamarin Forms nuget package to version 2.5 it crashes because it seems like the member method OnElementChanged is called with null Native control and null thisActivity. any idea how to fix it?
this is the error I get:
Unhandled Exception:
System.ArgumentNullException: Value cannot be null.
Parameter name: thisActivity
I fixed this crash by adding a constructor which takes a Androd.Content.Context and passes it down to the base class in my custom PageRenderer which contains my custom WebViewRenderer. Adding the new constructor to the webview itself wasn't helpful.
public class BaseControllerRenderer : Xamarin.Forms.Platform.Android.PageRenderer
{
public BaseControllerRenderer(Context context) : base(context)
{
}
...
From the Xamarin.Forms 2.5 release notes:
WebViewRenderer: This constructor is obsolete as of version 2.5. Please use WebViewRenderer(Context) instead.
Example constructor for the WebView custom renderer and OnElementChanged:
public CustomWebViewRenderer(Context context) : base(context)
{
Activity activity = (Activity)context;
}
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Android.Webkit.WebView webView = Control;
}
}
See also WebViewRenderer
Edit: Please note that the constructor change applies to any Android custom renderers as described in the Xamarin.Forms 2.5 release notes:
Supporting Forms Embedding required a significant number of deprecations in the Android backend. Please update any custom renderers.

How can I launch a Android Activity from Xamarin Forms Page?

I know that i can launch a Xamarin Forms page from an Native Android Activity, but how do i start a Native Android Activity from Xamarin Forms ContentPage. I tried with DependencyService but without success.
I figured it out.
First i needed to create a Interface like this in Xamarin Project
public interface IRecordVideoPage
{
void StartNativeIntentOrActivity();
}
then i launched the Native Android Activity from my Xamarin Forms Content Page using Dependency Service like this:
DependencyService.Register<IRecordVideoPage>();
DependencyService.Get<IRecordVideoPage>().StartNativeIntentOrActivity();
next I created a RecordActivity class in my Android Project that loads the Test Activity
[assembly: Xamarin.Forms.Dependency(typeof(RecordActivity))]
namespace StreamTest.Droid
{
[Activity(Label = "RecordActivity")]
public class RecordActivity : IRecordVideoPage
{
public void StartNativeIntentOrActivity()
{
var intent = new Intent(Forms.Context, typeof(Test));
Forms.Context.StartActivity(intent);
}
}
finally I set the content view in the Test class:
public class Test : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public Test() { }
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Record);
}
}
}
DependencyService is your best option. The concept behind PCL (Portable Class Library) is exactly to be platform independet.
Maybe we can help if you show the error you are getting with Dependency Service

How to apply style to application bar globally?

I checked the Application bar but no style attribute is shown. I have about 10 pages that use an app bar so it would be ideal to set a style in the Application.Resources. Is it possible to apply a style to all application bars in my application?
You can pretty much do this with a abstract class which your pages inherit from.
public abstract class BasePage : PhoneApplicationPage
{
public abstract bool UsingApplicationBar { get; }
public Color ApplicationBarColor= Colors.Gray;
public BasePage()
{
Loaded += BasePageLoaded;
}
private void BasePageLoaded(object sender, RoutedEventArgs e)
{
if (UsingApplicationBar)
{
ApplicationBar.BackgroundColor = ApplicationBarColor;
}
}
}
As far as I understand your question, you have different application bars on different pages and you want to have a style which can be applied to all. Unfortunately, binding does not work with application bars. You may have to style all of them one by one. For more information:
Windows Phone ApplicationBar BackgroundColor property style XamlParseException

Event using generic EventHandler<> not visible in Designer

I've just noticed that if I add an event using a generic eventhandler to my UserControl, the event is not visible in the designer when I add the user control to a form.
public event EventHandler<TEventArgs<int>> EventNotVisibleInDesigner;
public event EventHandler EventVisibleInDesigner;
Not particularly worrisome, but is this by-design/normal, or am I doing something wrong?
The Windows Forms designer has limited support for generic types. It will work okay when you avoid the generic type argument for EventHandler<T>:
public class TEventArgs<T> : EventArgs { }
public class MyEventArgs : TEventArgs<int> { }
public event EventHandler<MyEventArgs> EventNowAlsoVisibleInDesigner;

Resources