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

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

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

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

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

Q&A

解決済

1回答

3819閲覧

Android java ボタンをクリックすると、Textviewを動的変更させたい

circular2016

総合スコア52

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

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

0グッド

0クリップ

投稿2020/08/17 13:03

Android Studio、Android javaを使って、初めてのモバイルアプリを作成しています。

【実現したいこと】
DBに文字列が登録されている状態で(実装済み)、以下の画面があります。

イメージ説明

「再生開始」ボタンを押下すると、
登録された文字列が、先頭から5文字ずつ順番にTextviewに切り替え表示されるようにしたいです。
ユーザーがその都度ボタンを押下して切り替えるのではなく、自動的に切り替えさせたいです。

例えば、
登録されている文字列:「あああああいいいいいうううううえええええおおおおお」の場合、
ユーザーがボタンを押下

あああああ を表示

n秒後、いいいいい に切り替え表示

さらにn秒後、ううううう に切り替え表示

さらにさらにn秒後、えええええ に切り替え表示
以下続く...

【わからないこと】
「ユーザーがその都度ボタンを押下して切り替えるのではなく、
自動的に切り替えさせたい」
のですが、その実装方法がわかりません。

どのような言葉で検索すれば良いか自体がわからないため、
こんな単語で検索すれば良いですとか、このメソッドを使えば良い、
というのをご助言頂きたく思います。

よろしくお願いいたします。

参考(現在のJavaファイル)

java

1 2package com.example.textapp; 3 4import androidx.appcompat.app.AppCompatActivity; 5 6import android.content.Intent; 7import android.os.Bundle; 8import android.view.View; 9import android.widget.Button; 10import android.widget.TextView; 11 12import java.util.HashMap; 13import java.util.Map; 14 15public class ScTextPlay extends AppCompatActivity implements View.OnClickListener{ 16 17 //再生状態 1=停止状態、2=再生状態 18 private int state=1; 19 private Text text; 20 private StringBuilder sb = new StringBuilder(); 21 22 @Override 23 protected void onCreate(Bundle savedInstanceState) { 24 super.onCreate(savedInstanceState); 25 setContentView(R.layout.activity_sc_text_play); 26 27 //「再生」ボタンのオブジェクトを取得とイベントリスナ登録 28 Button playButton = (Button)findViewById(R.id.playButton); 29 playButton.setOnClickListener(this); 30 31 //リセットボタンのオブジェクトを取得し、リスナ登録する 32 Button resetButtonPlay = (Button)findViewById(R.id.resetButtonPlay); 33 resetButtonPlay.setOnClickListener(this); 34 35 //インテントを取得(呼び出し元から封筒を受け取る) 36 Intent intent = getIntent(); 37 38 //インテントからBundleを取得(封筒を開封する) 39 Bundle bundle = intent.getExtras(); 40 41 //Bundleから「TEXT_DATA」というキーで設定しているTextオブジェクトを取得 42 text = (Text)bundle.getSerializable("TEXT_DATA"); 43 44 ((TextView)findViewById(R.id.textViewPlay)).setText(text.getText()); 45 sb.append(text.getText()); 46 } 47 48 @Override 49 public void onClick(View v) { 50 //押されたボタンのIDを取得 51 int id = v.getId(); 52 Button playButton = (Button)findViewById(R.id.playButton); 53 Button resetButtonPlay = (Button)findViewById(R.id.resetButtonPlay); 54 55 switch (id) { 56 case R.id.playButton: //「再生開始」ボタンを押した場合 57 if(state == 1){//停止状態の場合、再生開始 58 state = 2; 59 //ボタン名変化 60 playButton.setText(getResources().getString(R.string.play)); 61 //リセットボタン有効化 62 resetButtonPlay.setEnabled(true); 63 getSplitPosition(sb); 64 65 }else{//再生状態の場合、再生停止 66 state = 1; 67 //ボタン名変化 68 playButton.setText(getResources().getString(R.string.stop)); 69 //リセットボタン無効化 70 resetButtonPlay.setEnabled(false); 71 } 72 break; 73 74 case R.id.resetButtonPlay: //「リセット」ボタンを押した場合 75 76 break; 77 } 78 } 79

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

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

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

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

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

guest

回答1

0

ベストアンサー

周期処理を実装するには、Handler、Timer、Thread、AsyncTaskなどいくつか方法があります(AsyncTaskは最新APIレベルで非推奨となったので用いない方が良いでしょう)。

このうち、Handlerを用いる例として、そちらのコードに載せた形でサンプルを書いてみました。

java

1public class MainActivity extends AppCompatActivity implements View.OnClickListener { 2 final Handler handler = new Handler(); 3 int count; 4 //再生状態 1=停止状態、2=再生状態 5 private int state = 1; 6 boolean start = false; 7 int i = 0; 8 9 @Override 10 protected void onCreate(Bundle savedInstanceState) { 11 super.onCreate(savedInstanceState); 12 setContentView(R.layout.activity_main); 13 14 (この辺省略) 15 16 } 17 18 @Override 19 public void onClick(View v) { 20 //押されたボタンのIDを取得 21 int id = v.getId(); 22 Button playButton = (Button) findViewById(R.id.playButton); 23 Button resetButtonPlay = (Button) findViewById(R.id.resetButtonPlay); 24 25 switch (id) { 26 case R.id.playButton: //「再生開始」ボタンを押した場合 27 if (state == 1) {//停止状態の場合、再生開始 28 state = 2; 29 //ボタン名変化 30 playButton.setText(getResources().getString(R.string.play)); 31 //リセットボタン有効化 32 resetButtonPlay.setEnabled(true); 33 //getSplitPosition(sb); 34 35 if (!start) { 36 // 停止状態からの開始のときだけ行う処理 37 count = 500; 38 start = true; 39 handler.post(runnable); // Runnableの処理を開始する 40 } 41 42 } else {//再生状態の場合、再生停止 43 state = 1; 44 //ボタン名変化 45 playButton.setText(getResources().getString(R.string.stop)); 46 //リセットボタン無効化 47 resetButtonPlay.setEnabled(false); 48 } 49 break; 50 51 case R.id.resetButtonPlay: //「リセット」ボタンを押した場合 52 handler.removeCallbacks(runnable); // コールバックを除去する 53 start = false; 54 break; 55 } 56 } 57 58 Runnable runnable = new Runnable() { 59 @Override 60 public void run() { 61 // 再生状態の場合、カウントダウン 62 if (state == 2) { 63 count--; 64 } 65 66 if (count == 0) { 67 /* 68 ここに5秒ごとに行う処理を記述 69 */ 70 71 count = 500; // カウンターをリセット 72 } 73 74 handler.postDelayed(this, 10); // 10ミリ秒後に自身を再実行 75 } 76 }; 77}

開始ボタンを押すと、handler.post()によって変数runnableに実装した処理が呼び出されます。この処理の末尾では、自身を10ミリ秒ごとに再呼び出しするように、handler.postDelayed()を呼び出しています。こんな感じで周期処理を実現できるでしょう。

停止状態からの開始なのか、一時停止からの再開なのかの判断が必要だったので、変数startを追加しています。

runnableの呼び出しが500回繰り返されたときに「ここに5秒ごとに行う処理を記述」というところが実行すれば、「5秒ごとに表示更新」が実現できるでしょう。一時停止したときは、runnableの周期呼び出しは止めず、countの減算だけを止めます(変数stateで判断)。周期処理を完全に除去したいときは、removeCallbacks()を呼びます。

こんな感じでもう少し肉付けすれば想定の形になるのでは。

投稿2020/08/17 14:59

keicha_hrs

総合スコア6768

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

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

circular2016

2020/08/23 12:28

keicha_hrs様 ご回答ありがとうございます! 返信が遅くなり申し訳ありません。 教えて頂いたハンドラで、最初の1周目を再生することができました! しかし、再度、再生開始ボタンを押下した時に、文字列の先頭「あああああ」からまた順次表示していきたいのですが、その挙動が変になっております。インターバルが指定のものより速くなり、かつバラバラになっています。 ハンドラーによる周期処理では、「あああああ」~「おおおおお」まで回したあと、ボタン押下によりまた「あああああ」から表示させることはできないのでしょうか? 以下はソースになります。 教えて頂けると大変助かります。 ------------------------------- package com.example.textapp; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import java.util.HashMap; import java.util.Map; public class ScTextPlay extends AppCompatActivity implements View.OnClickListener{ //再生状態 1=停止状態、2=再生状態 final Handler handler = new Handler(); private int state=1;//状態管理用 private Text text; private StringBuilder sb = new StringBuilder(); private int repeatInterval = 1000;//1秒 //最大字数 private int max = 40; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sc_text_play); //「再生」ボタンのオブジェクトを取得とイベントリスナ登録 Button playButton = (Button)findViewById(R.id.playButton); playButton.setOnClickListener(this); //リセットボタンのオブジェクトを取得し、リスナ登録する Button resetButtonPlay = (Button)findViewById(R.id.resetButtonPlay); resetButtonPlay.setOnClickListener(this); //インテントを取得(呼び出し元から封筒を受け取る) Intent intent = getIntent(); //インテントからBundleを取得(封筒を開封する) Bundle bundle = intent.getExtras(); //Bundleから「TEXT_DATA」というキーで設定しているTextオブジェクトを取得 text = (Text)bundle.getSerializable("TEXT_DATA"); ((TextView)findViewById(R.id.textViewPlay)).setText(text.getText()); sb.append(text.getText()); } @Override public void onClick(View v) { //押されたボタンのIDを取得 int id = v.getId(); Button playButton = (Button)findViewById(R.id.playButton); Button resetButtonPlay = (Button)findViewById(R.id.resetButtonPlay); switch (id) { case R.id.playButton: //「再生開始」ボタンを押した場合 //state:再生状態 1=停止状態、2=再生状態 if(state == 1){//停止状態から再生状態へ state = 2; //再生中、ボタン名は、「停止」にする。 playButton.setText(getResources().getString(R.string.stop)); playButton.setBackgroundColor(Color.parseColor("#F40254")); //リセットボタン無効化 resetButtonPlay.setEnabled(false); handler.post(runnable); }else{//再生状態から停止状態へ state = 1; //停止中、ボタン名は、「再生開始」にする playButton.setText(getResources().getString(R.string.play)); playButton.setBackgroundColor(Color.parseColor("#2196F3")); //リセットボタン有効化 resetButtonPlay.setEnabled(true); handler.removeCallbacks(runnable); // コールバックを除去する } break; case R.id.resetButtonPlay: //「リセット」ボタンを押した場合 //文字列を初期状態(開始位置を先頭)に戻す。 sb.delete(0,sb.length()); sb.append(text.getText()); break; } } Runnable runnable = new Runnable() { @Override public void run() { //文字がなくなるまで周期処理を実行する。 //whileではなく、if if (sb.length() > 0){ if(state == 2){ //文字列を分割して順に表示する。 getSplitPosition(sb);//このメソッドでsbは最終的に0になります。 } }else { state = 1; //停止中、ボタン名は、「再生開始」にする Button playButton = (Button)findViewById(R.id.playButton); Button resetButtonPlay = (Button)findViewById(R.id.resetButtonPlay); playButton.setText(getResources().getString(R.string.play)); //リセットボタン有効化 resetButtonPlay.setEnabled(true); //文字列を初期状態に戻す。 sb.delete(0,sb.length()); sb.append(text.getText()); handler.removeCallbacks(runnable); } handler.postDelayed(this, repeatInterval); //ミリ秒後に自身を再実行 } }; /* 文字列を分割する位置を取得する */ public void getSplitPosition(StringBuilder sb){ //code } } ---------------------------------------------------
circular2016

2020/08/23 12:50

申し訳ありません。 コメントした直後に自己解決できました。 run()の中で、単純にreturnを書けば良いだけでした。 ありがとうございます!! ------------------- handler.removeCallbacks(runnable); //文字列を初期状態に戻す。 sb.delete(0,sb.length()); sb.append(text.getText()); return; } handler.postDelayed(this, repeatInterval); //ミリ秒後に自身を再実行
keicha_hrs

2020/08/23 13:14

解決したのなら良かったです。Handlerによる方法は手軽な反面、カウントを継続するときは自分でコールバックを再postしなければならないので、その処理を誤るとRunnableを多重呼び出ししてカウントが早まってしまったり、呼び出しが途切れてカウントが止まってしまったりします。その辺りに注意を払う必要があります。
circular2016

2020/08/24 00:22

ありがとうございます!助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問