Отключить жесты в родительском элементе управления в iOS - PullRequest
0 голосов
/ 18 февраля 2019

У меня есть пользовательский элемент управления «контейнер» для управления жестами и элемент управления Skiasharp для рисования внутри.Функциональность, которую я ищу, заключается в том, что на первом этапе пользователь может увеличивать / перемещать изображение внутри контейнера, затем жесты контейнера отключаются, и пользователь может рисовать видимое изображение пальцами.Раньше он работал несколько месяцев назад, но когда перешел на xamarin 3.x, он начал выходить из строя.

Это код контейнера

public class GestureContainer : ContentView
{
    private const double MIN_SCALE = 1;
    private const double MAX_SCALE = 4;
    private double startScale, currentScale;
    private double startX, startY;
    private double xOffset, yOffset;

    private PanGestureRecognizer pan;
    private PinchGestureRecognizer pinchGesture;
    private TapGestureRecognizer tap;

    public static readonly BindableProperty GestureOnProperty =
       BindableProperty.Create("GestureOn", typeof(bool), typeof(GestureContainer), defaultValue: true, defaultBindingMode: BindingMode.TwoWay, propertyChanged: GestureOnChanges);

    public bool GestureOn
    {
        get
        {
            return (bool)GetValue(GestureOnProperty);
        }
        set
        {
            SetValue(GestureOnProperty, value);
        }
    }


    private static void GestureOnChanges(BindableObject bindable, object oldvalue, object newvalue)
    {
        GestureContainer gestureContainer = bindable as GestureContainer;

        if ((bool)newvalue)
            gestureContainer.SetGestures();
        else
            gestureContainer.GestureRecognizers.Clear();

    }


    public GestureContainer()
    {
        pinchGesture = new PinchGestureRecognizer();
        pan = new PanGestureRecognizer();
        tap = new TapGestureRecognizer { NumberOfTapsRequired = 2 };

        SetGestures();

        Scale = MIN_SCALE;
        TranslationX = TranslationY = 0;
    }

    private void SetGestures()
    {
        pinchGesture.PinchUpdated += OnPinchUpdated;
        GestureRecognizers.Add(pinchGesture);

        pan.PanUpdated += OnPanUpdated;
        GestureRecognizers.Add(pan);

        tap.Tapped += OnTapped;
        GestureRecognizers.Add(tap);
    }

    private void OnTapped(object sender, EventArgs e)
    {
       /**/
    }

    void RestoreScaleValues()
    {
        /**/
    }

    void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
    {
       /**/
    }

    void OnPanUpdated(object sender, PanUpdatedEventArgs e)
    {
       /**/
    }
}

Часть с "странной" функцией выглядит так:

gestureContainer.GestureRecognizers.Clear();

Когда я запускаю свойство binded в false, вызывается метод, вызывается .Clear (), но независимо от того, какие пинч / панорамирование / тап все еще работают, и это заставляет рисунок работать некорректно

РЕДАКТИРОВАТЬ

Это код XAML

<controls:GestureContainer GestureOn="{Binding OptionsVisibility, Converter={StaticResource BooleanConverter}}"  AbsoluteLayout.LayoutBounds="0,0,1,1" AbsoluteLayout.LayoutFlags="All">
                <controls:GestureContainer.Content>
                    <Grid>
                        <ffimageloading:CachedImage  
                            Rotation="{Binding Rotation}"  
                            x:Name="originalView"
                            Aspect="AspectFit"
                            DownsampleToViewSize="True"
                            Source="{Binding Imagen.ImageStream}"/>
                        <Grid IsEnabled="{Binding OptionsVisibility}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="Transparent">
                            <controls:BindableSKCanvasView x:Name="canvasView"
                                       Color="{Binding StrokeColor}"
                                       WidthStroke="{Binding StrokeWidth}"
                                       EnableTouchEvents="True"
                                       PaintSurface="OnCanvasViewPaintSurface" />
                            <Grid.Effects>
                                <skiacontrols:TouchEffect Capture="True" TouchAction="OnTouchEffectAction" />
                            </Grid.Effects>
                        </Grid>

                    </Grid>
                </controls:GestureContainer.Content>
            </controls:GestureContainer>

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

Очки, я думаю, вы пропустили:

  • Использование nameof(PropertyName) вместо "PropertyName", поскольку это помогает нам игнорировать человеческие ошибки, например: орфографические ошибки.

  • Вызов метода OnPropertyChanged в установщике, чтобы убедиться, что вы не пропустите событие PropertyChanged.

  • Вызов реализации базового класса для конструкторов, просточтобы убедиться, что все работает идеально. (Просто по привычке, я не считаю это обязательным)

Поэтому я внес необходимые изменения, и их можно найти ниже. Я изменил ихи их можно найти ниже:

 public class GestureContainer : ContentView   
 {
    private const double MIN_SCALE = 1;
    private const double MAX_SCALE = 4;
    private double startScale, currentScale;
    private double startX, startY;
    private double xOffset, yOffset;

    private PanGestureRecognizer pan;
    private PinchGestureRecognizer pinchGesture;
    private TapGestureRecognizer tap;

    public static readonly BindableProperty GestureOnProperty =
       BindableProperty.Create(nameof(GestureOn), typeof(bool), typeof(GestureContainer),
           defaultValue: true, defaultBindingMode: BindingMode.TwoWay, propertyChanged: GestureOnChanges);

    private static void GestureOnChanges(BindableObject bindable, object oldValue, object newValue)
    {
        GestureContainer gestureContainer = bindable as GestureContainer;

        if ((bool)newValue)
        {
            gestureContainer.SetGestures();
        }
        else
        {
            gestureContainer.GestureRecognizers.Clear();
        }
    }

    public bool GestureOn
    {
        get
        {
            return (bool)GetValue(GestureOnProperty);
        }
        set
        {
            SetValue(GestureOnProperty, value);
            OnPropertyChanged(nameof(GestureOn));
        }
    }

    public GestureContainer() : base()
    {
        pinchGesture = new PinchGestureRecognizer();
        pan = new PanGestureRecognizer();
        tap = new TapGestureRecognizer { NumberOfTapsRequired = 2 };

        SetGestures();

        Scale = MIN_SCALE;
        TranslationX = TranslationY = 0;
    }

    private void SetGestures()
    {
        pinchGesture.PinchUpdated += OnPinchUpdated;
        GestureRecognizers.Add(pinchGesture);

        pan.PanUpdated += OnPanUpdated;
        GestureRecognizers.Add(pan);

        tap.Tapped += OnTapped;
        GestureRecognizers.Add(tap);
    }

    private void OnTapped(object sender, EventArgs e)
    {
        /**/
    }

    private void RestoreScaleValues()
    {
        /**/
    }

    private void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
    {
        /**/
    }

    private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
    {
        /**/
    }
}
0 голосов
/ 20 февраля 2019

Кажется, создается несколько ссылок.

попробуйте написать такую ​​функцию

void clearGesture() {
  pinchGesture.PinchUpdated -= OnPinchUpdated;
  pan.PanUpdated -= OnPanUpdated;
  tap.Tapped -= OnTapped;
}

И вызвать это явно как, gestureContainer.clearGesture();

...