質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.02%

OnTouchを複数のボタンで使用したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,318

nasama

score 14

前提・実現したいこと

以前、StackOverflowでOnTouchでボタンの長押しをした時の処理の書き方を教えてもらい、その内容を元に、
同様の動きをするボタンが複数あり、ボタンごとに別の変数のカウントアップorダウンができるように作り変えたいと思っています。
現在のプログラムは以下の通りです。

該当のソースコード

using System;
using System.Diagnostics;
using Android.App;
using Android.OS;
using Android.Views;
using Android.Widget;


namespace test2
{
    [Activity(Label = "test2", MainLauncher = true, Icon = "@mipmap/icon")]
    public class MainActivity : Activity, View.IOnTouchListener
    {

        System.Threading.CancellationTokenSource cancellationTokenSource;
        int count = 1;
        private Button button;
        private Button button2;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            // Get our button from the layout resource,
            // and attach an event to it
            button = FindViewById<Button>(Resource.Id.myButton);
            button2 = FindViewById<Button>(Resource.Id.myButton2);
            TextView text = new TextView(this);
            //text = FindViewById<TextView>(Resource.Id.Text);


            button.SetOnTouchListener(this);
            button2.SetOnTouchListener(this);

        }
        public bool OnTouch(View v, MotionEvent e)
        {
            switch (e.Action)
            {
                case MotionEventActions.Down:

                    button.Text = string.Format("{0} clicks!", v.Id);
                    if(cancellationTokenSource != null)
                    break;
                    cancellationTokenSource = new System.Threading.CancellationTokenSource();
                    var token = cancellationTokenSource.Token;

                    System.Threading.Tasks.Task.Factory.StartNew(() =>
                    {
                        var stopwatch = Stopwatch.StartNew();
                        while (stopwatch.ElapsedMilliseconds < 1000 && 
                               token.IsCancellationRequested == false)
                        {
                            System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(10)).Wait();
                        }

                        while (token.IsCancellationRequested == false)
                        {
                            RunOnUiThread(() =>
                            {
                                button.Text = string.Format("{0} clicks!", count++);
                            });
                            System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(100)).Wait();
                        }
                    }, token)
                          .ContinueWith(_ =>
                    {
                        cancellationTokenSource.Dispose();
                        cancellationTokenSource = null;
                    });
                    break;

                case MotionEventActions.Up:
                    if (cancellationTokenSource != null)
                    {
                        cancellationTokenSource.Cancel();
                    }
                    break;
            }
            return true;
        }
    }

}


現在、button1とbutton2を作りswitchでそれぞれのボタンの分岐処理を作ろうと考えておりますが、どのようにしてそれぞれのボタンの違いを認識させればよいかわからず詰まっています。
色々と試し、記載されているプログラムを実行し、button1を押すと「2131034112 CLICKS!」button2を押すと「2131034113 CLICKS!」とボタンに表示されるところまではできました
(本来であればTextViewなどに表示させた方がわかりやすいのですが、「text.Text = v.Id.ToString();」と書こうとすると何故かエラーが出てしまうのでボタンに表示させています)。
このIdなのですが、現在ボタンを押したときに得られるIdというのは不変なのでしょうか?
switchで分岐させる場合は

switch (v.Id)
            {
                case 2131034112:
                    .............
                    break;
            }
switch (v.Id)
            {
                case 2131034113:
                    .............
                    break;
            }


こんな感じでいいのでしょうか?
サンプルコードとか色々見ましたが変数名とかが記載してあるのがほとんどだったと思うので気になり投稿しました。

追記(12/15)

回答ありがとうございます。
教えていただいたコードを使用させていただきました。

しかし、通常のtouch動作であれば作成できましたが、
MotionEvent を検知できないようで、長押しができなくなってしまいました。
そのためonTouchから入れて試しましたが、どこに}を足してもエラーが出て詰まってしまいます。
Xamarin Studioのクイック修正を使用しエラーを潰しましたが、取りきれないエラーが数多くあり、動作確認ができない状況です。

追記2(12/15)

コメントありがとうございます。
e.Event.Actionを使用することでe.Actionと同様の動きができました。
それにより、実現したい動作を作成することができました。ありがとうございました!

修正後の内容は以下のコードです。

using System;
using System.Diagnostics;
using Android.App;
using Android.OS;
using Android.Views;
using Android.Widget;


namespace test2
{
    [Activity(Label = "test2", MainLauncher = true, Icon = "@mipmap/icon")]
    public class MainActivity : Activity
    {
        System.Threading.CancellationTokenSource cancellationTokenSource;
        int count = 1;
        int count2 = 1;
        private Button button;
        private Button button2;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            // Get our button from the layout resource,
            // and attach an event to it
            button = FindViewById<Button>(Resource.Id.myButton);
            button2 = FindViewById<Button>(Resource.Id.myButton2);
            TextView text = new TextView(this);
            //text = FindViewById<TextView>(Resource.Id.Text);



            button.Touch += (object sender, View.TouchEventArgs e) =>
            {
                switch (e.Event.Action)
                {
                    case MotionEventActions.Down:

                        button.Text = string.Format("{0} clicks!",count++);
                        if (cancellationTokenSource != null)
                            break;
                        cancellationTokenSource = new System.Threading.CancellationTokenSource();
                        var token = cancellationTokenSource.Token;

                        System.Threading.Tasks.Task.Factory.StartNew(() =>
                        {
                            var stopwatch = Stopwatch.StartNew();
                            while (stopwatch.ElapsedMilliseconds < 1000 &&
                                   token.IsCancellationRequested == false)
                            {
                                System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(10)).Wait();
                            }

                            while (token.IsCancellationRequested == false)
                            {
                                RunOnUiThread(() =>
                                {
                                    button.Text = string.Format("{0} clicks!", count++);
                                });
                                System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(100)).Wait();
                            }
                        }, token)
                              .ContinueWith(_ =>
                        {
                            cancellationTokenSource.Dispose();
                            cancellationTokenSource = null;
                        });
                        break;

                    case MotionEventActions.Up:
                        if (cancellationTokenSource != null)
                        {
                            cancellationTokenSource.Cancel();
                        }
                        break;
                }
            };
            button2.Touch += (object sender, View.TouchEventArgs e) =>
            {
                switch (e.Event.Action)
                {
                    case MotionEventActions.Down:

                        button2.Text = string.Format("{0} clicks!",count2++);
                        if (cancellationTokenSource != null)
                            break;
                        cancellationTokenSource = new System.Threading.CancellationTokenSource();
                        var token = cancellationTokenSource.Token;

                        System.Threading.Tasks.Task.Factory.StartNew(() =>
                        {
                            var stopwatch = Stopwatch.StartNew();
                            while (stopwatch.ElapsedMilliseconds < 1000 &&
                                   token.IsCancellationRequested == false)
                            {
                                System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(10)).Wait();
                            }

                            while (token.IsCancellationRequested == false)
                            {
                                RunOnUiThread(() =>
                                {
                                    button2.Text = string.Format("{0} clicks!", count2++);
                                });
                                System.Threading.Tasks.Task.Delay(TimeSpan.FromMilliseconds(100)).Wait();
                            }
                        }, token)
                              .ContinueWith(_ =>
                        {
                            cancellationTokenSource.Dispose();
                            cancellationTokenSource = null;
                        });
                        break;

                    case MotionEventActions.Up:
                        if (cancellationTokenSource != null)
                        {
                            cancellationTokenSource.Cancel();
                        }
                        break;
                }
            };
        }
    }

}

※文字数制限に引っかかったので前回のコードは消しました

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

button.SetOnTouchListener(this);
button2.SetOnTouchListener(this);

ではなくて、

button.Touch += (object sender, View.TouchEventArgs e) => {
//ここに処理
};
button2.Touch += (object sender, View.TouchEventArgs e) => {
//ここに処理
};

な感じでいけませんか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/15 19:27

    回答ありがとうございます。
    教えていただいた内容を元に修正いたしました。
    よろしければご確認ください。

    キャンセル

  • 2016/12/15 20:06

    e.Event.Actionで拾えると思いますが。。。
    その前に基本的なところを学習したほうが良いように思えます。

    キャンセル

  • 2016/12/16 00:08

    e.Event.Actionで拾えました。お手数おかけいたしました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.02%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる