Jeffrey van Dijk
Jeffrey van Dijk

Reputation: 13

Xamarin Custom View OnElementChanged never runs

I got a very simple application showing a VideoView, whenever I change tabs in my application it crashes because it says "View is Null", now I found a solution online making a custom renderer (https://code.videolan.org/videolan/LibVLCSharp/-/issues/506)

When I implement that in my project like so:

using Android.Content;
using LibVLCSharp.Shared;
using LibVLCSharp.Forms.Platforms.Android;
using LibVLCSharp.Forms.Shared;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using System;

[assembly: ExportRenderer(typeof(VideoView), typeof(CustomVideoViewRenderer))]
namespace LibVLCSharp.Forms.Platforms.Android
{
    /// <summary>
    /// Xamarin.Forms custom renderer for the Android VideoView
    /// </summary>
    public class CustomVideoViewRenderer : ViewRenderer<LibVLCSharp.Forms.Shared.VideoView, LibVLCSharp.Platforms.Android.VideoView>
    {
        /// <summary>
        /// Main constructor (empty)
        /// </summary>
        /// <param name="context">Android context</param>
        public CustomVideoViewRenderer(Context context) : base(context)
        {
        }

        /// <summary>
        /// Native control management during lifecycle events
        /// </summary>
        /// <param name="e">lifecycle event</param>
        protected override void OnElementChanged(ElementChangedEventArgs<VideoView> e)
        {
            Console.WriteLine("This will never run");
            base.OnElementChanged(e);
            if (e.NewElement != null)
            {
                if (Control == null)
                {
                    SetNativeControl(new LibVLCSharp.Platforms.Android.VideoView(Context!));

                    e.NewElement.MediaPlayerChanging += OnMediaPlayerChanging;
                    if (Control!.MediaPlayer != e.NewElement.MediaPlayer)
                    {
                        OnMediaPlayerChanging(this, new MediaPlayerChangingEventArgs(Control!.MediaPlayer, e.NewElement.MediaPlayer));
                    }
                }
            }

            if (e.OldElement != null)
            {
                e.OldElement.MediaPlayerChanging -= OnMediaPlayerChanging;
            }
        }

        private void OnMediaPlayerChanging(object? sender, MediaPlayerChangingEventArgs e)
        {
            Control.MediaPlayer = e.NewMediaPlayer;
            Control.TriggerLayoutChangeListener();
        }
    }
}

Using the following in my xaml:

<shared:VideoView x:Name="somevid" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Column="1"></shared:VideoView>

It never reaches the OnElementChanged, so I must be misunderstanding how custom views work.

I thought they just had to inherit from the class you are trying to change it's default implementation of, in this case "VideoView" and you had to override OnElementChanged. I expected to atleast see the "Console.WriteLine" being called in the "OnElementChanged".

Upvotes: 1

Views: 181

Answers (1)

Jianwei Sun - MSFT
Jianwei Sun - MSFT

Reputation: 4332

You want to show a VideoView? You can use MediaElement provided by Xamarin Community Toolkit.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
             x:Class="Forms.Page4">
        <StackLayout>
            <xct:MediaElement x:Name="mediaElement"
                              Source="ms-appx:///XamarinForms101UsingEmbeddedImages.mp4"
                              HeightRequest="400"/>
        </StackLayout>
</ContentPage>

And this is the effect. For more detailed steps you can refer to this doc: Play local media.

Hope this is a workaround for you.

Upvotes: 0

Related Questions