Grid上に配置したコントロールをドラッグで移動して、他のコントロールと場所を入れ替えたい
ここに実現したいことを箇条書きで書いてください。
- PanGestureRecognizerがWindows上の動作と同様にAndroidで動作させたい(iOSは今はどうでもいい)
スマホでありがちな画面上のコントロールを指で移動して場所を入れ替えたいだけなのです
.NET MAUIでドラッグして画面上のパーツを入れ替えるロジックを試しているのですが
Windows上で上手く行ったからと、Androidで試してみたら同じように動作せずに困っています
- xamlの方では、Grid上にイメージと、ラベルとその他関係ないのも配置
- GridにPanGestureRecognizerを配置、イベントをC#のPanGestureRecognizer_PanUpdatedに結びつけ
- ImageにPanGestureRecognizerを配置、イベントをC#のOnPanImageに結びつけ
- LabelにPanGestureRecognizerを配置、イベントをC#のOnPanLabelに結びつけ
- PanGestureRecognizer_PanUpdatedでは、イメージの動作を記述
- OnPanImageでは、イメージからのPanである事のフラグ設定
- OnPanLabelでは、ラベルからのPanである事のフラグ設定
これで、Windowsで動作させると、イメージをマウスでドラッグし、ラベル(Hello, World!と書いてある方)の上でリリースすると、イメージしたとおりにコントロール同士が入れ替わったのですが
Androidだと、GridのPanGestureRecognizerでイベントが発生せずに、ピクリとも動作しなくなります
個別のコントロールだけにPanGestureRecognizerを登録すると、移動している最中に他のコンロールに引っかかって停まってしまうし
GridだけにPanGestureRecognizerを登録すると、どのコントロールでイベントが発生したのか全くわからなくなってしまう
と言う事で、正しく動作するには一体どうすればいいのかわからなくて詰んでいる状態です
DragAndDropRecognizerだと、データのコピーが何をやっても発生してしまい、画面の文字が書き換わってしまうのでちょっと格好悪いしで
やろうとしている動作もPanGestureRecognizerで動作させるのが正しいとは思うのですが
何かヒントだけでも無いでしょうか
該当のソースコード
c#
1 2 /// <summary>タイマー</summary> 3 Timer _tim; 4 5 public MainPage() 6 { 7 InitializeComponent(); 8 9 //タイマーの設定をする 10 _tim = new Timer(); 11 _tim.Interval = 300; 12 _tim.Elapsed += _tim_Elapsed; 13 _tim.AutoReset = false; //タイマーはstart後に1回だけ発動 14 } 15 16 /// <summary> 17 /// Translateが終わった頃にグリッド上の位置を書き換えておしまい 18 /// </summary> 19 private void changePosition() 20 { 21 //イメージコントロールの元々あったGrid上の位置 22 int botColumn = baseGrid.GetColumn(bot); 23 int botRow = baseGrid.GetRow(bot); 24 25 //ラベルコントロールの元々あったGrid上の位置 26 int lblColumn = baseGrid.GetColumn(label1); 27 int lblRow = baseGrid.GetRow(label1); 28 29 //Grid上の位置を書換(イメージコントロール) 30 baseGrid.SetColumn(bot, lblColumn); 31 baseGrid.SetRow(bot, lblRow); 32 bot.TranslationX = 0; //移動量は0に戻しておく 33 bot.TranslationY = 0; 34 35 //Grid上の位置を書換(ラベルコントロール) 36 baseGrid.SetColumn(label1, botColumn); 37 baseGrid.SetRow(label1, botRow); 38 label1.TranslationX = 0; //移動量は0に戻しておく 39 label1.TranslationY = 0; 40 } 41 42 /// <summary> 43 /// タイマー発動 44 /// </summary> 45 /// <param name="sender"></param> 46 /// <param name="e"></param> 47 private void _tim_Elapsed(object sender, ElapsedEventArgs e) 48 { 49 //xaml上のスレッドに changePositiontメソッドの操作を委任 50 MainThread.BeginInvokeOnMainThread(changePosition); 51 } 52 /// <summary>true = イメージコントロール / false = ラベル</summary> 53 bool isImage = false; 54 55 /// <summary> 56 /// PanGestureRecognizer ★Androidだと、このイベントが発生しない 57 /// </summary> 58 private void PanGestureRecognizer_PanUpdated(object sender, PanUpdatedEventArgs e) 59 { 60 61 if (e.StatusType == GestureStatus.Completed) 62 { 63 //移動完了 64 65 //ここで、他のコントロールと場所を入れ替えたい 66 //1.どのコントロールの上にかぶったのか 67 //2.被さったコントロールがGrid上のcolmとrowのそれぞれ何処の位置にあるのか 68 //イメージの位置情報 69 var botPosX = bot.X; 70 var botPosY = bot.Y; 71 var botH = bot.Height; 72 var botW = bot.Width; 73 74 //文字ラベルの位置情報 75 var lblPosX = label1.X; 76 var lblPosY = label1.Y; 77 var lblH = label1.Height; 78 var lblW = label1.Width; 79 80 if(isImage == true) 81 { 82 //イメージコントロールの終了処理 83 84 var botNewX = botPosX + bot.TranslationX; 85 var botNewY = botPosY + bot.TranslationY; 86 87 if((botNewX > lblPosX && botNewX < (lblPosX+lblW)) 88 && (botNewY > lblPosY && botNewY < (lblPosY+lblH))) 89 { 90 //botがラベルの上にかぶったので、まずアニメ移動 91 bot.TranslateTo(lblPosX - botPosX +10 , lblPosY - botPosY+10, 50); 92 label1.TranslateTo(-(lblPosX - botPosX+10), -(lblPosY - botPosY + 10), 50); 93 // _tim.Start(); 94 } 95 else 96 { 97 //ラベルの上に居るので無ければ元の位置に戻す 98 bot.TranslateTo(0, 0, 50); 99 } 100 } 101 Debug.WriteLine($"mainC={e.TotalX}"); 102 } 103 else 104 { 105 //ドラッグ中の移動 106 Debug.WriteLine($"mainO={e.TotalX}"); 107 if (isImage == true) 108 { 109 bot.TranslationX = e.TotalX; 110 bot.TranslationY = e.TotalY; 111 } 112 else 113 { 114 label1.TranslationY = e.TotalY; 115 label1.TranslationX = e.TotalX; 116 } 117 } 118 } 119 120 /// <summary> 121 /// イメージコントロールのPanGestureRecognizer 122 /// </summary> 123 private void OnPanImage(object sender, PanUpdatedEventArgs e) 124 { 125 isImage = true; //イメージコントロールからのpan 126 Debug.WriteLine($"image={e.TotalX}"); 127 //bot.TranslationX = e.TotalX; 128 //bot.TranslationY = e.TotalY; 129 } 130 131 /// <summary> 132 /// ラベルコントロールのPanGestureRecognizer 133 /// </summary> 134 private void OnPanLabel(object sender, PanUpdatedEventArgs e) 135 { 136 isImage = false;//ラベルからのpan 137 Debug.WriteLine($"label={e.TotalX}"); 138 //label1.TranslationY = e.TotalY; 139 //label1.TranslationX = e.TotalX; 140 }
xaml
1 <Grid x:Name="baseGrid"> 2 <!-- PANジェスチャーはここに登録しないと、ちゃんと動作しない 個別のコントロールにPanGestureRecognizerを配置しても移動中に他のコントロールに引っかかると停まってまう --> 3 <Grid.GestureRecognizers> 4 <PanGestureRecognizer PanUpdated ="PanGestureRecognizer_PanUpdated" /> 5 </Grid.GestureRecognizers> 6 <Grid.ColumnDefinitions> 7 <ColumnDefinition Width="*" /> 8 <ColumnDefinition Width="*" /> 9 <ColumnDefinition Width="*" /> 10 <ColumnDefinition Width="*" /> 11 </Grid.ColumnDefinitions> 12 <Grid.RowDefinitions> 13 <RowDefinition Height="*" /> 14 <RowDefinition Height="*" /> 15 <RowDefinition Height="*" /> 16 <RowDefinition Height="*" /> 17 </Grid.RowDefinitions> 18 19 20 21 <Image x:Name="bot" 22 Source="dotnet_bot.png" Grid.Column="0" Grid.Row="0" ClassId="image1" 23 SemanticProperties.Description="Cute dot net bot waving hi to you!" 24 HeightRequest="200" 25 HorizontalOptions="Center" > 26 <!-- PANジェスチャーはGRIDにおいて、さらに個々のコントロール毎に配置 --> 27 <Image.GestureRecognizers > 28 <PanGestureRecognizer PanUpdated="OnPanImage" /> 29 </Image.GestureRecognizers> 30 31 </Image> 32 33 <Label Grid.Column="1" Grid.Row="1" ClassId="label1" x:Name="label1" 34 Text="Hello, World!" 35 SemanticProperties.HeadingLevel="Level1" 36 FontSize="32" 37 HorizontalOptions="Center" > 38 <!-- PANジェスチャーはGRIDにおいて、さらに個々のコントロール毎に配置 --> 39 <Label.GestureRecognizers> 40 <PanGestureRecognizer PanUpdated="OnPanLabel" /> 41 </Label.GestureRecognizers> 42 </Label> 43 44 <Label Grid.Column="2" Grid.Row="2" ClassId="image2" 45 Text="Welcome to .NET Multi-platform App UI" 46 SemanticProperties.HeadingLevel="Level2" 47 SemanticProperties.Description="Welcome to dot net Multi platform App U I" 48 FontSize="18" 49 HorizontalOptions="Center" /> 50 51 <Button Grid.Column="3" Grid.Row="3" ClassId="image3" 52 x:Name="CounterBtn" 53 Text="Click me" 54 SemanticProperties.Hint="Counts the number of times you click" 55 Clicked="OnCounterClicked" 56 HorizontalOptions="Center" /> 57 58 </Grid>
試したこと
ここに問題に対して試したことを記載してください。
補足情報(FW/ツールのバージョンなど)
- VisualStudio 2022(17.5)
- .NetMaui 7.0
- Android Emulator は Android11と12
ここにより詳細な情報を記載してください。
あなたの回答
tips
プレビュー