Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image TapGestureRecognizer not triggering in Xamarin

In my Xamarin App, I'm using Tooltips Effects (followed this article).

There are Help Icons on the page, when I click on it, the tooltips appeared and if I clicked anywhere on the Stacklayout area, it disappeared, which means it's working perfectly.

There are multiple Help Icons, and I want that If I click on any Help Icon, tooltips for this help icon only appeared and disappeared the open ones, because now, multiple tooltips can be open at a same time.

For this, I add an TapGestureRecognizer, that when someone clicks on the help icon, close the open tooltips. But, I don't know why TapGestureRecognizer doesn't even trigger.

.xaml

<StackLayout x:Name="mainstacklayout">

<StackLayout.GestureRecognizers>
    <TapGestureRecognizer Tapped="Handle_Tapped"
                          NumberOfTapsRequired="1" />
</StackLayout.GestureRecognizers>

// Code

<Image Source="drawable/help.png"
                    WidthRequest="20"
                    HeightRequest="20"
                    effects:TooltipEffect.Position="Left"
                    effects:TooltipEffect.BackgroundColor="#222222"
                    effects:TooltipEffect.TextColor="#FFFFFF"
                    effects:TooltipEffect.Text="Tooltip"
                    effects:TooltipEffect.HasTooltip="True">

        <Image.GestureRecognizers>
            <TapGestureRecognizer Tapped="Handle_Tapped"
                                  NumberOfTapsRequired="1" />
        </Image.GestureRecognizers>
</Image>

// Code

</StackLayout>

.xaml.cs

public void Handle_Tapped(object sender, EventArgs args)
{
    foreach (var c in mainstacklayout.Children)
    {
        if (TooltipEffect.GetHasTooltip(c))
        {
            TooltipEffect.SetHasTooltip(c, false);
            TooltipEffect.SetHasTooltip(c, true);
        }
    }
}
like image 202
Stavrogin Avatar asked Jul 08 '21 08:07

Stavrogin


2 Answers

There are multiple Help Icons, and I want that If I click on any Help Icon, tooltips for this help icon only appeared and disappeared the open ones, because now, multiple tooltips can be open at a same time.

According to your description, you want to make one ToolTip appear when you click one helpicon, then click to make ToolTip disappear?

You want to use TapGestureRecognizer to achieve it, but you have already implement TooltipEffect that call click event. It is seems a issue in Xamarin, more details can be found here

But I see the sample have implement ITipListener, you can click ToolTip to make ToolTip disappear, don't need to use TapGestureRecognizer

 class TipListener : Java.Lang.Object, ITipListener
    {
        public void OnTipDismissed(Android.Views.View p0, int p1, bool p2)
        {
         
        }
    }

Update:

You have implemented xamarin.forms.view click event in PlatformEffect, it block TapGestureRecognizer. Can not find way to fire TapGestureRecognizer, but I find one workaround that you can take a look.

You can use LongClick to make ToolTip appear and use Click to make ToolTip disappear.

 protected override void OnAttached()
    {
        var control = Control ?? Container;          
        control.LongClick += OnTap;
        control.Click += HideTooltip;
    }

    private void HideTooltip(object sender, EventArgs e)
    {
        var control = Control ?? Container;
        _toolTipsManager.FindAndDismiss(control);
    }

    protected override void OnDetached()
    {
        var control = Control ?? Container;
        control.LongClick -= OnTap;          
        control.Click -= OnTap;
        _toolTipsManager.FindAndDismiss(control);
    }

Update again:

You can see I have add control.LongClick += OnTap; and control.Click += HideTooltip; on OnAttached method, it is same as LongPressedCommand, the article that you provided, its ultimate goal is to add longclick.

[assembly: ResolutionGroupName("CrossGeeks")]
[assembly: ExportEffect(typeof(DroidTooltipEffect), nameof(TooltipEffect))]
namespace ToolTipSample.Droid.Effects
{
public class DroidTooltipEffect : PlatformEffect 
{
    ToolTip toolTipView;
    ToolTipsManager _toolTipsManager;
    ITipListener listener;

    public DroidTooltipEffect()
    {
        listener = new TipListener();
        _toolTipsManager = new ToolTipsManager(listener);
    }

    void OnTap(object sender, EventArgs e)
    {
        var control = Control ?? Container;        
        var text = TooltipEffect.GetText(Element);

        if (!string.IsNullOrEmpty(text))
        {
           ToolTip.Builder builder;
            var parentContent = control.RootView;
           
            var position = TooltipEffect.GetPosition(Element);
            switch (position)
            {
                case TooltipPosition.Top:
                    builder = new ToolTip.Builder(control.Context, control, parentContent as ViewGroup, text.PadRight(80, ' '), ToolTip.PositionAbove);
                    break;
                case TooltipPosition.Left:
                    builder = new ToolTip.Builder(control.Context, control, parentContent as ViewGroup, text.PadRight(80, ' '), ToolTip.PositionLeftTo);
                    break;
                case TooltipPosition.Right:
                    builder = new ToolTip.Builder(control.Context, control, parentContent as ViewGroup, text.PadRight(80, ' '), ToolTip.PositionRightTo);
                    break;
                default:
                    builder = new ToolTip.Builder(control.Context, control, parentContent as ViewGroup, text.PadRight(80, ' '), ToolTip.PositionBelow);
                    break;
            }

            builder.SetAlign(ToolTip.AlignLeft);
            builder.SetBackgroundColor(TooltipEffect.GetBackgroundColor(Element).ToAndroid());
            builder.SetTextColor(TooltipEffect.GetTextColor(Element).ToAndroid());
         
            toolTipView = builder.Build();
           
            _toolTipsManager?.Show(toolTipView);
        }
    }


    protected override void OnAttached()
    {
        var control = Control ?? Container;          
        control.LongClick += OnTap;
        control.Click += HideTooltip;
    }

    private void HideTooltip(object sender, EventArgs e)
    {
        var control = Control ?? Container;
        _toolTipsManager.FindAndDismiss(control);
    }

    protected override void OnDetached()
    {
        var control = Control ?? Container;
        control.LongClick -= OnTap;          
        control.Click -= OnTap;
        _toolTipsManager.FindAndDismiss(control);
    }

    class TipListener : Java.Lang.Object, ITipListener
    {
        public void OnTipDismissed(Android.Views.View p0, int p1, bool p2)
        {
         
        }
    }
}
 }
like image 198
Cherry Bu - MSFT Avatar answered Oct 24 '22 21:10

Cherry Bu - MSFT


  1. The first test is to change the XAML where you declare each image,

to effects:TooltipEffect.HasTooltip="False":

<Image Source="drawable/help.png"
                ...
                effects:TooltipEffect.HasTooltip="False">

If you do, does the recognizer work? If so, then you are halfway there.

Do that in the declaration of every image. This should "disable" all the tooltips.

2. Use TapGestureRecognizer to turn one on (and turn the others off).:

public void Handle_Tapped(object sender, EventArgs args)
{
    foreach (var c in mainstacklayout.Children)
    {
        // Turn off any that are on.
        if (TooltipEffect.GetHasTooltip(c))
        {
            TooltipEffect.SetHasTooltip(c, false);
        }
    }
    // Turn on the desired tooltip.
    if (sender is View activeView)
    {
        TooltipEffect.SetHasTooltip(activeView, true);

        // TODO: TooltipEffect source needs this method added;
        // it has to find the effect for activeView, and call its `OnTap` method.
        //TODO TooltipEffect.OnTap(activeView);
    }
}
like image 25
ToolmakerSteve Avatar answered Oct 24 '22 21:10

ToolmakerSteve