1

I wanted to install a library to Spotlight the First Page for the first time when users opens the app. For that I found this amazing library called AndroidSpotlight, but the problem is that I can't install that in Xamarin.Forms project as it's only for Xamarin.Android.

When I try to install it for Xamarin.Forms project, it gives me this error.

Package Android.Spotlight 2019.11.14.1 is not compatible with netstandard2.1 (.NETStandard,Version=v2.1). Package Android.Spotlight 2019.11.14.1 supports: monoandroid10 (MonoAndroid,Version=v1.0)

But the first page is in Xamarin.Forms, so how could I use this library their?

Views/IntroPage.xml (I want to highlight the ImageButton)

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Mobile.App.Views.IntroPage"
             xmlns:local="clr-namespace:Mobile.App.Control"
             NavigationPage.HasNavigationBar="False">

    <ContentPage.Content>
        <StackLayout>
            <StackLayout VerticalOptions="Start">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30" />
                    </Grid.RowDefinitions>

                    <Grid Grid.Row="0">
                        <ImageButton x:Name="SettingsButton"
                                     Source="drawable/icon.png"
                                     WidthRequest="20"
                                     HeightRequest="20"
                                     HorizontalOptions="StartAndExpand"
                                     VerticalOptions="CenterAndExpand"
                                     Command="{Binding SettingsButtonCommand}">
                        </ImageButton>
                    </Grid>
                </Grid>
            </StackLayout>

            <StackLayout HorizontalOptions="CenterAndExpand"
                         VerticalOptions="CenterAndExpand">
                // Code
            </StackLayout>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

UPDATE

@Jason recommended to use DependencyService.

It is working fine, but now their is a problem with Spotlight Code. In Control\SpotLightService.cs, the Target() required a Parameter called view. When I use the Xamarin.Forms.View view, it says Cannot convert form 'Xamarin.Forms.ImageButton' to 'Android.Views.View'.

But when I use Android.View, in Views/IntroPage.xml.cs I can't access SettingsButton, which I want to Spotlight.

Views/IntroPage.xml.cs

public partial class IntroPage : ContentPage
{
    public IntroPage()
    {
        DependencyService.Get<ISpotLight>().ShowIntro(SettingsButton, "settings");
    
        InitializeComponent();
    }
}

Services\ISpotLight.cs

using Xamarin.Forms;

namespace Mobile.App.Services
{
    public interface ISpotLight
    {
        void ShowIntro(View view, string usageId);
    }
}

Control\SpotLightService.cs

using code from AndroidSpotlight

[assembly: Xamarin.Forms.Dependency(typeof(SpotLightService))]
namespace Mobile.App.Droid.Control
{
    public class SpotLightService : ISpotLight
    {
        private bool isRevealEnabled = true;
        private SpotlightView spotLight;

        public void ShowIntro(Xamarin.Forms.View view, string usageId)
        {
            spotLight = new SpotlightView.Builder((Activity)Application.Context)
                .IntroAnimationDuration(400)
                .EnableRevealAnimation(isRevealEnabled)
                .PerformClick(true)
                .FadeinTextDuration(400)
                .HeadingTvColor(Color.ParseColor("#eb273f"))
                .HeadingTvSize(32)
                .HeadingTvText("Love")
                .SubHeadingTvColor(Color.ParseColor("#ffffff"))
                .SubHeadingTvSize(16)
                .SubHeadingTvText("Like the picture?\nLet others know.")
                .MaskColor(Color.ParseColor("#dc000000"))
                .Target(view)
                .LineAnimDuration(400)
                .LineAndArcColor(Color.ParseColor("#eb273f"))
                .DismissOnTouch(true)
                .DismissOnBackPress(true)
                .EnableDismissAfterShown(true)
                .UsageId(usageId)
                .ShowTargetArc(true)
                .Show();
        }
    }
}
Stavrogin
  • 135
  • 1
  • 15
  • 3
    use DependencyService to access platform specific libraries from the core Forms project – Jason Aug 09 '21 at 13:33
  • 1
    thanks, i found this article https://alexdunn.org/2017/02/21/xamarin-tips-calling-platform-specific-code-from-a-portable-class-library-xamarin-forms-dependencyservice/ .. is this what you are referring to? – Stavrogin Aug 09 '21 at 13:38
  • 3
    https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/dependency-service/ – Jason Aug 09 '21 at 13:39
  • BTW, when you look at the doc @Jason mentions, don't make the mistake I did. I clicked on "Registration and Resolution", because I didn't realize Introduction was a separate page; I thought it was just that paragraph. I clicked straight into low-level details! Be sure to click ["Introduction"](https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/dependency-service/introduction) first. (can also get there from navigation hierarchy at left side of page). – ToolmakerSteve Aug 09 '21 at 16:42
  • thanks, I used the DependencyService, but their is a small problem using it.. I updated the code above, kindly have a look.. thanks – Stavrogin Aug 09 '21 at 17:12

1 Answers1

2
  • Convert Xamarin.Forms.View to Android.Views.View , you can try the following code .

     public View ConvertFormsToNative(Xamarin.Forms.View view)
     {
           var vRenderer = Platform.CreateRendererWithContext(view, MainActivity.Instance);
           var Androidview = vRenderer.View;
           vRenderer.Tracker.UpdateLayout();
    
           var size = view.Bounds;
           var layoutParams = new ViewGroup.LayoutParams((int)size.Width, (int)size.Height);
           Androidview.LayoutParameters = layoutParams;
           view.Layout(size);
           Androidview.Layout(0, 0, (int)view.WidthRequest, (int)view.HeightRequest);
           Androidview.SetBackgroundColor(Color.Red);
           return Androidview;
      }
    

    and the target should be set as .Target(ConvertFormsToNative(view))

  • Change new SpotlightView.Builder((Activity)Application.Context) to new SpotlightView.Builder(MainActivity.Instance) .

    Instance is a field defined in MainActivity .

       public static MainActivity Instance;
       protected override void OnCreate(Bundle savedInstanceState)
       {
           base.OnCreate(savedInstanceState);
    
           Xamarin.Essentials.Platform.Init(this, savedInstanceState);
           global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
    
           Instance = this;
    
  • Move the call of Dependency service from constructor to LayoutChanged event.

       public Page1()
       {
    
           InitializeComponent();
    
           this.LayoutChanged += Page1_LayoutChanged;
    
       }
    
       bool isShown = false;
       private void Page1_LayoutChanged(object sender, EventArgs e)
       {
           if (!isShown)
           {
               DependencyService.Get<ISpotLight>().ShowIntro(SettingsButton, "settings");
               isShown = true;
           }
       }
    
ColeX
  • 14,062
  • 5
  • 43
  • 240
  • You are the best... thanks.. just a small thing, I've basically this 3 buttons (1st on top-left, 2nd on top-right, 3rd on bottom-center).. I want that this white animation line to start from where the component is.. now, all (3 of them) starts from the top-left.. why? – Stavrogin Aug 10 '21 at 08:22
  • like this https://raw.githubusercontent.com/wooplr/Spotlight/master/art/intro.gif?token=AA5ZAHdvAspW6Zj8YyyKamkV7jWXFtMHks5XaQovwA%3D%3D – Stavrogin Aug 10 '21 at 08:32
  • Could you show the running image to elaborate it ? – ColeX Aug 10 '21 at 08:37
  • I added a picture above, kindly have a look – Stavrogin Aug 10 '21 at 09:17
  • Try to change `Androidview.Layout(0, 0, (int)view.WidthRequest, (int)view.HeightRequest);` to `Androidview.Layout((int)size.X, (int)size.Y, (int)view.WidthRequest, (int)view.HeightRequest);` . – ColeX Aug 10 '21 at 09:21
  • a position just change a bit, but still 3 of them are on the top. – Stavrogin Aug 10 '21 at 09:43