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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

1084閲覧

インナークラスからviewの呼び出しができずエラーになってしまいます。

ebichiri

総合スコア13

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2020/02/18 06:47

Javaを利用してAndroidStudioでのアプリ製作をおこなっております。
現在タイトルの様なエラーが起きてしまいました。

**■ レイアウトファイル **

xml

1<Button 2android:id="@+id/btn1" 3android:layout_width="wrap_content" 4android:layout_height="wrap_content" 5android:text="ボタン1" 6android:layout_gravity="center" /> 7 8<Button 9android:id="@+id/btn2" 10android:layout_width="wrap_content" 11android:layout_height="wrap_content" 12android:text="ボタン2" 13android:layout_gravity="center" />

■ Javaファイル1
[MainActivity.java]

Java

1public class MainActivity extends AppCompatActivity { 2 3 @Override 4 protected void onCreate(Bundle savedInstanceState) { 5 super.onCreate(savedInstanceState); 6 setContentView(R.layout.activity_main); 7 8 BtnClick btnClick= new BtnClick(); 9 10 Button btn1 = findViewById(R.id.btn1 ); 11 btn1.setOnClickListener(btnClick); 12 13 Button btn2 = findViewById(R.id.btn2 ); 14 btn2.setOnClickListener(btnClick); 15 } 16}

■ Javaファイル2
[BtnClick.java]

public class BtnClickimplements View.OnClickListener { View v; // ビュー int time; // タイマーを動かす時間を入れる boolean bool; // 時間の判定   int tap; // タップ @Override public void onClick(View view) { v = view; switch (v.getId()) { case R.id.btn1: time= 1000; bool = true; tap = 0; // スタートボタンの有効無効 if (bool) { v.setEnabled(false); } new Handler().postDelayed(new Runnable() { @Override public void run() { bool= false; tap = 0; v.setEnabled(true); Log.i("comment", "終了時刻になりました"); } }, time); break; case R.id.btn2: // 時間内であれば、btn2のタップをカウントアップ if (bool) { tap += 1; Log.i("comment", "現在のタップ数" + tap + "回"); } break; } } }

■起きている不具合
上記のようなコードを書きますと、
BtnClick.javaファイルのHandler内で使用している
btn1ボタンの有効化 v.setEnabled(true); の部分のみ無視されてしまいます。

Handlerを使用している理由につきましては、
初めにTimerを使用してみて同様にうまくいかず、
下記のサイト様の記事を参考に試してみた次第です。
https://re-engines.com/2019/12/19/%E3%80%90java%E3%80%91handler%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%81%BE%E3%81%A8%E3%82%81%E3%81%A6%E3%81%BF%E3%81%BE%E3%81%97%E3%81%9F/

どういったところを重点的に見ていくとよいか、アドバイスをいただけますと幸いです。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

MainActivity で BtnClick クラスのインスタンス btnClick を一つだけ作って、それを btn1 と btn2 の両方に setOnClickListener してます。で、onClick が呼ばれたときに引数 view をフィールド v にコピーしてます。この v は btn1 と btn2 で共通で、btn1 が押された時も btn2 が押された時もまず v をセットしているので、タイマーが切れる前に btn2 を押すと v の値は btn2 となり、run の中で v.setEnabled(true); されるのは btn1 ではなく btn2 になり、その後 btn1 はずっと押せないままになります。

おそらく run の中で bool や top や v にアクセスするためにフィールドにしたのだと思いますが、フィールドにするとそのインスタンスが生きてる間はずっと値が残るので要注意です。逆に bool や tap は btn1 と btn2 の両方からアクセスする必要があるため、フィールドにする必要があると言えます。とりあえずフィールドの v を消して以下のように変更すると期待通りの動きになると思います。

java

1 @Override 2 public void onClick(View view) { 3 4 final View v = view; // この行を変更

とは言え、btn1 と btn2 の onClickListener が同一のオブジェクトだったり同じメソッドというのは気持ちが悪いので、自分だったら次のように MainActivity にまとめて書くと思います。

java

1public class MainActivity extends AppCompatActivity { 2 3 private Button btn1; 4 private Button btn2; 5 6 private int time; // タイマーを動かす時間を入れる 7 private boolean bool; // 時間の判定 8 private int tap; // タップ 9 10 @Override 11 protected void onCreate(Bundle savedInstanceState) { 12 super.onCreate(savedInstanceState); 13 setContentView(R.layout.activity_main); 14 15 btn1 = findViewById(R.id.btn1); 16 btn1.setOnClickListener(new View.OnClickListener() { 17 @Override 18 public void onClick(View v) { 19 onBtn1Click(); 20 } 21 }); 22 23 btn2 = findViewById(R.id.btn2); 24 btn2.setOnClickListener(new View.OnClickListener() { 25 @Override 26 public void onClick(View v) { 27 onBtn2Click(); 28 } 29 }); 30 } 31 32 public void onBtn1Click() { 33 // time は onBtn1Click でしか使ってないので、ローカル変数でも構わないし、定数でもいいのでは 34 time = 1000; 35 bool = true; 36 tap = 0; 37 38 // onBtn1Click が押されたということは、btn1 は押せる状態だったという意味なので、 39 // bool のチェックは不要 (というか、チェックするならメソッドの先頭でやるべき) 40 btn1.setEnabled(false); 41 42 new Handler().postDelayed(new Runnable() { 43 @Override 44 public void run() { 45 bool = false; 46 tap = 0; 47 btn1.setEnabled(true); 48 Log.i("comment", "終了時刻になりました"); 49 } 50 }, time); 51 } 52 53 public void onBtn2Click() { 54 // 時間内であれば、btn2のタップをカウントアップ 55 if (bool) { 56 tap += 1; 57 Log.i("comment", "現在のタップ数" + tap + "回"); 58 } 59 } 60}

あと、厳密には画面が回転されたり、別の画面に遷移した後にタイマーが発火したらどうするかを考える必要があります。

投稿2020/02/18 07:57

hoshi-takanori

総合スコア7901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ebichiri

2020/02/18 11:09

hoshi-takanori様 迅速なご回答と丁寧な解説をありがとうございます。 まだ試せていないのですが、取り急ぎお礼申し上げます。 viewの中身が入れ替わっていた為に動かないのだという事、考えが及びませんでした。 また最後に問題点も上げていただきありがとうございます。シンプルなタイマー機能だけでは難しそうですね。 なんとかクリア出来る様に頑張ります!
ebichiri

2020/02/18 14:24

hoshi-takanori様 ローカルで動きの確認ができました!ありがとうございます。 二つとも試しまして、MainActivity内で分けて書く方法に致しました。 少し主旨がずれてしまうのですが、アクセス修飾子について質問になりまして、 こういったアプリケーションなどを作る際にはフィールド変数にprivateを付けるよう心がけた方が良いでしょうか? 何卒どうぞよろしくお願い致します。
hoshi-takanori

2020/02/18 17:42

アクセス修飾子は、自分はJavaでの習慣として、finalでないフィールドはprivate(またはprotected)にしてます。
ebichiri

2020/02/19 00:34

ありがとうございます。自分のプログラムへの取り組みの問題点が見えてきました。一つずつの部品がどう扱われるのか、動いていくか、きちんと意識を向けて勉強をしていきたいと思いますm(__)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問