問題は、toucheventが終了するとrestore positionコマンドが呼び出され、元の位置に戻されるという問題があります。私は問題が私の財産変更イベントにあると思う。DraggableViewの復元位置コマンドC#Xamarin
2番目の問題は、最も近い番号のラベルに引っかかり、センター自体を適切に並べ替えることができるはずだが、どうすればいいのかわからない。私はこれを行う方法についてのヒントがほしいと思う。
グリッド
<Grid BackgroundColor="White" ColumnSpacing="10" RowSpacing="10">
<Label Text="Red" FontSize="Medium" HorizontalOptions="Center" />
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<BoxView Color="Black" Grid.Column="1" Grid.RowSpan="1"/>
<BoxView Color="Gray" Grid.Column="2" Grid.RowSpan="1"/>
<Label Text="9" Font ="60" Grid.Row="1" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
<Label Text="8" Font ="60" Grid.Row="2" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
<Label Text="7" Font ="60" Grid.Row="3" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
<Label Text="6" Font ="60" Grid.Row="4" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
<Label Text="5" Font ="60" Grid.Row="5" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
<Label Text="4" Font ="60" Grid.Row="6" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
<Label Text="3" Font ="60" Grid.Row="7" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
<Label Text="2" Font ="60" Grid.Row="8" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
<Label Text="1" Font ="60" Grid.Row="9" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
<Label Text="0" Font ="60" Grid.Row="10" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" />
<local:DraggableView x:Name="dragView" DragMode="LongPress" DragDirection="All" Grid.Row="3" Grid.RowSpan="3" Grid.Column="3" >
<local:DraggableView.Content>
<BoxView x:Name="image" BackgroundColor="Pink" />
</local:DraggableView.Content>
</local:DraggableView>
</Grid>
クロスプラットフォームのコード、Xamarin
public partial class DraggableView : ContentView
{
public event EventHandler DragStart = delegate { };
public event EventHandler DragEnd = delegate { };
public static readonly BindableProperty DragDirectionProperty = BindableProperty.Create(
propertyName: "DragDirection",
returnType: typeof(DragDirectionType),
declaringType: typeof(DraggableView),
defaultValue: DragDirectionType.All,
defaultBindingMode: BindingMode.TwoWay);
public DragDirectionType DragDirection
{
get { return (DragDirectionType)GetValue(DragDirectionProperty); }
set { SetValue(DragDirectionProperty, value); }
}
public static readonly BindableProperty DragModeProperty = BindableProperty.Create(
propertyName: "DragMode",
returnType: typeof(DragMode),
declaringType: typeof(DraggableView),
defaultValue: DragMode.LongPress,
defaultBindingMode: BindingMode.TwoWay);
public DragMode DragMode
{
get { return (DragMode)GetValue(DragModeProperty); }
set { SetValue(DragModeProperty, value); }
}
public static readonly BindableProperty IsDraggingProperty = BindableProperty.Create(
propertyName: "IsDragging",
returnType: typeof(bool),
declaringType: typeof(DraggableView),
defaultValue: false,
defaultBindingMode: BindingMode.TwoWay);
public bool IsDragging
{
get { return (bool)GetValue(IsDraggingProperty); }
set { SetValue(IsDraggingProperty, value); }
}
public static readonly BindableProperty RestorePositionCommandProperty = BindableProperty.Create(nameof(RestorePositionCommand), typeof(ICommand), typeof(DraggableView), default(ICommand), BindingMode.TwoWay, null, OnRestorePositionCommandPropertyChanged);
static void OnRestorePositionCommandPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var source = bindable as DraggableView;
if (source == null)
{
return;
}
source.OnRestorePositionCommandChanged();
}
private void OnRestorePositionCommandChanged()
{
OnPropertyChanged("RestorePositionCommand");
}
public ICommand RestorePositionCommand
{
get
{
return (ICommand)GetValue(RestorePositionCommandProperty);
}
set
{
SetValue(RestorePositionCommandProperty, value);
}
}
public void DragStarted()
{
DragStart(this, default(EventArgs));
IsDragging = true;
}
public void DragEnded()
{
IsDragging = false;
DragEnd(this, default(EventArgs));
}
Androidのコードの一部
public class DraggableViewRenderer : VisualElementRenderer<Xamarin.Forms.View>
{
float originalX;
float originalY;
float dX;
float dY;
bool firstTime = true;
bool touchedDown = false;
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
LongClick -= HandleLongClick;
}
if (e.NewElement != null)
{
LongClick += HandleLongClick;
var dragView = Element as DraggableView;
dragView.RestorePositionCommand = new Command(() =>
{
if (!firstTime)
{
SetX(originalX);
SetY(originalY);
}
});
}
}
private void HandleLongClick(object sender, LongClickEventArgs e)
{
var dragView = Element as DraggableView;
if (firstTime)
{
originalX = GetX();
originalY = GetY();
firstTime = false;
}
dragView.DragStarted();
touchedDown = true;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var dragView = Element as DraggableView;
base.OnElementPropertyChanged(sender, e);
}
protected override void OnVisibilityChanged(AView.View changedView, [GeneratedEnum] ViewStates visibility)
{
base.OnVisibilityChanged(changedView, visibility);
if (visibility == ViewStates.Visible)
{
}
}
// What happens when you toch
public override bool OnTouchEvent(MotionEvent e)
{
float x = e.RawX;
float y = e.RawY;
var dragView = Element as DraggableView;
switch (e.Action)
{
case MotionEventActions.Down:
if (dragView.DragMode == DragMode.Touch)
{
if (!touchedDown)
{
if (firstTime)
{
originalX = GetX();
originalY = GetY();
firstTime = false;
}
dragView.DragStarted();
}
touchedDown = true;
}
dX = x - this.GetX();
dY = y - this.GetY();
break;
case MotionEventActions.Move:
if (dragView.DragDirection == DragDirectionType.All || dragView.DragDirection == DragDirectionType.Horizontal)
{
SetX(x - dX);
}
if (dragView.DragDirection == DragDirectionType.All || dragView.DragDirection == DragDirectionType.Vertical)
{
SetY(y - dY);
}
break;
case MotionEventActions.Up:
touchedDown = false;
dragView.DragEnded();
break;
case MotionEventActions.Cancel:
touchedDown = false;
break;
}
return true;
}
public override bool OnInterceptTouchEvent(MotionEvent e)
{
BringToFront();
return true;
}
}
iOSのパート
public class DraggableViewRenderer : VisualElementRenderer<View>
{
bool longPress = false;
bool firstTime = true;
double lastTimeStamp = 0f;
UIPanGestureRecognizer panGesture;
CGPoint lastLocation;
CGPoint originalPosition;
UIGestureRecognizer.Token panGestureToken;
void DetectPan()
{
var dragView = Element as DraggableView;
if (longPress || dragView.DragMode == DragMode.Touch)
{
if (panGesture.State == UIGestureRecognizerState.Began)
{
dragView.DragStarted();
if (firstTime)
{
originalPosition = Center;
firstTime = false;
}
}
CGPoint translation = panGesture.TranslationInView(Superview);
var currentCenterX = Center.X;
var currentCenterY = Center.Y;
if (dragView.DragDirection == DragDirectionType.All || dragView.DragDirection == DragDirectionType.Horizontal)
{
currentCenterX = lastLocation.X + translation.X;
}
if (dragView.DragDirection == DragDirectionType.All || dragView.DragDirection == DragDirectionType.Vertical)
{
currentCenterY = lastLocation.Y + translation.Y;
}
Center = new CGPoint(currentCenterX, currentCenterY);
if (panGesture.State == UIGestureRecognizerState.Ended)
{
dragView.DragEnded();
longPress = false;
}
}
}
protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
RemoveGestureRecognizer(panGesture);
panGesture.RemoveTarget(panGestureToken);
}
if (e.NewElement != null)
{
var dragView = Element as DraggableView;
panGesture = new UIPanGestureRecognizer();
panGestureToken = panGesture.AddTarget(DetectPan);
AddGestureRecognizer(panGesture);
dragView.RestorePositionCommand = new Command(() =>
{
if (!firstTime)
{
Center = originalPosition;
}
});
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var dragView = Element as DraggableView;
base.OnElementPropertyChanged(sender, e);
}
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
base.TouchesBegan(touches, evt);
lastTimeStamp = evt.Timestamp;
Superview.BringSubviewToFront(this);
lastLocation = Center;
}
public override void TouchesMoved(NSSet touches, UIEvent evt)
{
if (evt.Timestamp - lastTimeStamp >= 0.5)
{
longPress = true;
}
base.TouchesMoved(touches, evt);
}
}
私はあなたが何を意味するかわからないんだけど、これはどのよう適切に実装していない私のonrestoreコマンドを使用して、私の問題を解決できますか? ELI5できますか? –
これはxamarin.formsでカスタムコントロールを作成するためのヒントです。コマンドの問題については、自分のアップデートを参照してください。 –
私はdragonativeについて少し混乱しています、私はちょうど新しいdragviewネイティブの元のOntouchevent関数を置くと思いますか? –