Xamarin Forms Проведите пальцем влево / Проведите пальцем вправо
Я хочу предвосхитить это, говоря, что я совершенно новичок в разработке мобильных приложений, Xamarin, C#, .Net.
Я работаю над созданием мобильного приложения с использованием форм Xamarain и столкнулся с проблемой отсутствия у меня жеста смахивания, по крайней мере, согласно документации, которую я видел.
Я нашел этот сайт: http://arteksoftware.com/gesture-recognizers-with-xamarin-forms/
Здесь описывается, как добавить некоторые дополнительные жесты для IOS/Android, чтобы они были доступны в контексте формы. Прежде чем я попытаюсь следовать этому, я хотел бы узнать, реализовал ли кто-нибудь другой метод смахивания в приложении Xamarin Forms и как они это сделали.
Мои цели в том, что должен быть горизонтальный макет стека. Этот макет содержит 7 кнопок, каждая кнопка отображает день текущей недели. Сдвиг влево на макете стека изменит текст кнопки на предыдущую неделю. Смахивание вправо изменит текст кнопки на следующую неделю.
Поэтому я также пытаюсь использовать MVVM для этого и XAML. Так можно ли разделить движение влево и вправо влево? Я хочу использовать ICommand для передачи определенного параметра в функцию, основанную на направлении пролистывания.
Любые примеры этого или любого совета будет принята с благодарностью.
6 ответов
Если вам удобно оплачивать стороннюю библиотеку (и вы используете Xamarin Forms, так что это хорошая возможность), MR.Gestures поддерживает все сенсорные жесты во всех представлениях Xamarin.Forms. Я использовал это успешно и был действительно счастлив этим. Это стоит очень разумных 10 евро и имеет отличную документацию.
Если вы один из тех, кто разочарован тем, что сенсорные жесты не поддерживаются в формах Xamarin, рассмотрите возможность проголосовать за это предложение в UserVoice.
Нет необходимости в сторонних библиотеках. Не нужно платить. Просто добавьте эти два класса и внедрите своих слушателей
Шаг 1: Скопируйте и вставьте эти два класса
SwipeListener.cs
using System;
using Xamarin.Forms;
namespace SwipeLib
{
public class SwipeListener : PanGestureRecognizer
{
private ISwipeCallBack mISwipeCallback;
private double translatedX = 0, translatedY = 0;
public SwipeListener(View view, ISwipeCallBack iSwipeCallBack)
{
mISwipeCallback = iSwipeCallBack;
var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += OnPanUpdated;
view.GestureRecognizers.Add(panGesture);
}
void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
View Content = (View)sender;
switch (e.StatusType) {
case GestureStatus.Running:
try {
translatedX = e.TotalX;
translatedY = e.TotalY;
} catch (Exception err) {
System.Diagnostics.Debug.WriteLine("" + err.Message);
}
break;
case GestureStatus.Completed:
System.Diagnostics.Debug.WriteLine("translatedX : " + translatedX);
System.Diagnostics.Debug.WriteLine("translatedY : " + translatedY);
if (translatedX < 0 && Math.Abs(translatedX) > Math.Abs(translatedY)) {
mISwipeCallback.onLeftSwipe(Content);
} else if (translatedX > 0 && translatedX > Math.Abs(translatedY)) {
mISwipeCallback.onRightSwipe(Content);
} else if (translatedY < 0 && Math.Abs(translatedY) > Math.Abs(translatedX)) {
mISwipeCallback.onTopSwipe(Content);
} else if (translatedY > 0 && translatedY > Math.Abs(translatedX)) {
mISwipeCallback.onBottomSwipe(Content);
} else {
mISwipeCallback.onNothingSwiped(Content);
}
break;
}
}
}
}
ISwipeCallBack.cs
using System;
using Xamarin.Forms;
namespace SwipeLib
{
public interface ISwipeCallBack
{
void onLeftSwipe(View view);
void onRightSwipe(View view);
void onTopSwipe(View view);
void onBottomSwipe(View view);
void onNothingSwiped(View view);
}
}
Шаг 2: Из ваших форм Xamarin передайте представление и интерфейс obj. Тогда вы получите результат
В моем случае я передаю ярлык
SwipeListener swipeListener = new SwipeListener(lbl_swipe, this);
Шаг 3: Реализация интерфейса ISwipeCallBack
public partial class SwipeLibPage : ContentPage, ISwipeCallBack
Пример проекта -> https://github.com/rranjithkumar100/Xamarin-Swipe-Library
Xamarin.Forms представила SwipeGestureRecognizer:
<BoxView Color="Teal" ...>
<BoxView.GestureRecognizers>
<SwipeGestureRecognizer Direction="Left" Swiped="OnSwiped"/>
</BoxView.GestureRecognizers>
</BoxView>
Вы всегда можете взглянуть на эту простую демонстрацию. И используйте его следующим образом:
GestureFrame gi = new GestureFrame
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
BackgroundColor = Color.FromHex("bf3122"),
};
gi.SwipeDown += (s, e) =>
{
DisplayAlert("Gesture Info", "Swipe Down Detected", "OK");
ViewModel.SampleCommand.Execute("Swipe Down Detected");
};
gi.SwipeTop += (s, e) =>
{
DisplayAlert("Gesture Info", "Swipe Top Detected", "OK");
ViewModel.SampleCommand.Execute("Swipe Top Detected");
};
gi.SwipeLeft += (s, e) =>
{
DisplayAlert("Gesture Info", "Swipe Left Detected", "OK");
ViewModel.SampleCommand.Execute("Swipe Left Detected");
};
gi.SwipeRight += (s, e) =>
{
DisplayAlert("Gesture Info", "Swipe Right Detected", "OK");
ViewModel.SampleCommand.Execute("Swipe Right Detected");
};
this.Content = gi;
К вашему сведению
SwipeView доступен в Xamarin.Forms 4.4.
Класс SwipeView также определяет четыре события:
SwipeStarted запускается, когда начинается смахивание. Объект SwipeStartedEventArgs, сопровождающий это событие, имеет свойство SwipeDirection типа SwipeDirection.
SwipeChanging запускается при перемещении свайпа. Объект SwipeChangingEventArgs, сопровождающий это событие, имеет свойство SwipeDirection типа SwipeDirection и свойство Offset типа double.
SwipeEnded запускается, когда заканчивается смахивание. Объект SwipeEndedEventArgs, сопровождающий это событие, имеет свойство SwipeDirection типа SwipeDirection.
CloseRequested запускается, когда элементы смахивания закрываются. Кроме того, SwipeView определяет метод Close, который закрывает элементы смахивания.
Для получения дополнительных сведений о некоторых новых функциях Xamarin Forms перейдите по этой ссылке.
Основываясь на решении @Ranjith Kumar, я придумал следующее:
public delegate void SwipedEventHandler(ISwipeListener sender, SwipedEventArgs e);
public class SwipedEventArgs : EventArgs
{
readonly double _x;
public double X => _x;
readonly double _y;
public double Y => _y;
readonly View _view;
public View View => _view;
public SwipedEventArgs(View view, double x, double y)
{
_view = view;
_x = x;
_y = y;
}
}
public interface ISwipeListener
{
event SwipedEventHandler SwipedDown;
event SwipedEventHandler SwipedLeft;
event SwipedEventHandler SwipedNothing;
event SwipedEventHandler SwipedRight;
event SwipedEventHandler SwipedUp;
double TotalX
{
get;
}
double TotalY
{
get;
}
}
public class SwipeListener : PanGestureRecognizer, ISwipeListener
{
public event SwipedEventHandler SwipedDown;
public event SwipedEventHandler SwipedLeft;
public event SwipedEventHandler SwipedNothing;
public event SwipedEventHandler SwipedRight;
public event SwipedEventHandler SwipedUp;
double _totalX = 0, _totalY = 0;
public double TotalX => _totalX;
public double TotalY => _totalY;
readonly View _view;
public SwipeListener(View view) : base()
{
_view = view;
_view.GestureRecognizers.Add(this);
PanUpdated += OnPanUpdated;
}
void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
switch (e.StatusType)
{
case GestureStatus.Running:
try
{
_totalX = e.TotalX;
_totalY = e.TotalY;
}
catch (Exception exception)
{
Debug.WriteLine(exception.Message);
}
break;
case GestureStatus.Completed:
if (_totalX < 0 && Math.Abs(_totalX) > Math.Abs(_totalY))
{
OnSwipedLeft(_totalX, _totalY);
}
else if (_totalX > 0 && _totalX > Math.Abs(_totalY))
{
OnSwipedRight(_totalX, _totalY);
}
else if (_totalY < 0 && Math.Abs(_totalY) > Math.Abs(_totalX))
{
OnSwipedUp(_totalX, _totalY);
}
else if (_totalY > 0 && _totalY > Math.Abs(_totalX))
{
OnSwipedDown(_totalX, _totalY);
}
else OnSwipedNothing(_totalX, _totalY);
break;
}
}
protected virtual void OnSwipedDown(double x, double y)
=> SwipedDown?.Invoke(this, new SwipedEventArgs(_view, x, y));
protected virtual void OnSwipedLeft(double x, double y)
=> SwipedLeft?.Invoke(this, new SwipedEventArgs(_view, x, y));
protected virtual void OnSwipedNothing(double x, double y)
=> SwipedNothing?.Invoke(this, new SwipedEventArgs(_view, x, y));
protected virtual void OnSwipedRight(double x, double y)
=> SwipedRight?.Invoke(this, new SwipedEventArgs(_view, x, y));
protected virtual void OnSwipedUp(double x, double y)
=> SwipedUp?.Invoke(this, new SwipedEventArgs(_view, x, y));
}
Недостатком является то, что вы ничего не можете сделать, пока выполняется, только после.
Может быть, это могло бы помочь кому-то.
У меня была проблема: была ContentPage с scrollview и сеткой в нем. Все, что мне нужно сделать, это обработать жесты влево / вправо. После поиска в google / stackru / github я нашел пакет Nuget с именем XamarinFormsGestures. Это мне очень помогло. Вся инструкция находится внутри ссылки. Вот мой код:
Vapolia.Lib.Ui.Gesture.SetSwipeLeftCommand(scrollviewgrid,
new Command(() => { OnLeftSwipe(); })); // What's going on when left swiped.
Vapolia.Lib.Ui.Gesture.SetSwipeRightCommand(scrollviewgrid,
new Command(() => { OnRightSwipe(); })); // What's going on when right swiped.
Вы можете использовать пакет NuGet "XamarinFormsGesture" от Vapolia (документ доступен здесь). Это бесплатно и легко в использовании.
Доступно на iOS и Android, но работает только на физических устройствах (не на симуляторе).