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

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

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

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

Android

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

Android Studio

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

Q&A

解決済

1回答

2611閲覧

android studio あるタイミングでのsetText()について

sakuramoti

総合スコア20

Java

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

Android

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

Android Studio

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

0グッド

1クリップ

投稿2018/04/16 11:52

編集2018/04/16 14:36

#前提、実現したいこと
画面に四角形にテキストボックスを4つ表示しその中にcanvasを配置しています(xmlファイルに記述)。またcanvas上をボールが動き壁(画面の端のテキストボックス)に当たったらそこのテキストを変更するということをしたいです。

#当該のソースコード

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/wood" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > //ここのtextViewの文字列を変更したいです。 <TextView android:layout_width="match_parent" android:layout_height="20dp" android:background="#CCffffff" android:id="@+id/bar_top" /> <LinearLayout android:layout_width="match_parent" android:layout_height="470dp" android:orientation="horizontal"> <TextView android:layout_width="20dp" android:layout_height="470dp" android:background="#CCffffff" android:id="@+id/bar_left" /> <com.example.yyoshida.mygameprot.SimulationView android:id="@+id/canvas" android:layout_width="345dp" android:layout_height="470dp" /> <TextView android:layout_width="20dp" android:layout_height="470dp" android:background="#CCffffff" android:id="@+id/bar_right" /> </LinearLayout> <TextView android:layout_width="match_parent" android:layout_height="20dp" android:background="#CCffffff" android:id="@+id/bar_bottom" /> </LinearLayout> </RelativeLayout>

該当部

lang

1public class SimulationView extends SurfaceView implements SurfaceHolder.Callback { 2 private SurfaceHolder holder; 3 private Bitmap backGroundBitmap; 4 private Paint myPaint; 5 private Ball ball; 6 private int windowsWidth, windowsHeight; 7 private TextView textView; 8 private MainActivity main; 9 10//コンストラクタ 11 public SimulationView(Context c) { 12 super(c); 13 init(); 14 } 15 16 public SimulationView(Context context, AttributeSet attrs) { 17 super(context, attrs); 18 init(); 19 } 20 21 public SimulationView(Context context, AttributeSet attrs, int defStyleAttr) { 22 super(context, attrs, defStyleAttr); 23 init(); 24 } 25 26 public void init() { 27 holder = getHolder(); 28 holder.addCallback(this); 29 ball = new Ball(); 30 setFocusable(true); 31 requestFocus(); 32 main = new MainActivity(); 33 } 34 35 public void update() {//当たり判定とボールの移動 36 //右壁 37 if (x < 0) { 38 checkBar = 1; 39 main.countUpBarText(checkBar); 40 dx = -dx; 41 } 42 //左壁 43 if (x + ballWidth > windowsWidth) { 44 checkBar = 2; 45 main.countUpBarText(checkBar); 46 dx = -dx; 47 } 48 //上壁 49 if (y < 0) { 50 checkBar = 3; 51 main.countUpBarText(checkBar); 52 dy = -dy; 53 } 54 //下壁 55 if (y + ballHeight > windowsHeight) { 56 checkBar = 4; 57 main.countUpBarText(checkBar); 58 dy = -dy; 59 } 60 x += dx; 61 y += dy; 62 } 63 }

lang

1 2public class MainActivity extends AppCompatActivity { 3 private TextView textView; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 setBarText(); 10 } 11 12 13 public void setBarText() {//textviewの文字を設定 14 int number = 0; 15 String text = ""; 16 17 for (int key = 1; key < 5; key++) { 18 if (key == 1) { 19 textView = findViewById(R.id.bar_left); 20 } else if (key == 2) { 21 textView = findViewById(R.id.bar_right); 22 } else if (key == 3) { 23 textView = findViewById(R.id.bar_top); 24 } else { 25 textView = findViewById(R.id.bar_bottom); 26 } 27//最初にランダムでテキスト設定 28 number = (int) (Math.random() * 10); 29 text = String.valueOf(number); 30 textView.setText(text); 31 } 32 } 33 34 35//壁に当たった時に呼ばれる 36 public void countUpBarText(int key){//textviewを変更する 37 String barText = ""; 38 int countUp = 0; 39 Log.d("test","test"); 40//ここまでは実行される 41 if(key == 1){ 42 textView = findViewById(R.id.bar_left); 43 }else if(key == 2){ 44 textView = findViewById(R.id.bar_right); 45 }else if(key == 3){ 46 textView = findViewById(R.id.bar_top); 47 }else { 48 textView = findViewById(R.id.bar_bottom); 49 } 50//ここは実行されず止まってしまう 51 Log.d("test","test2"); 52 barText = (String)textView.getText(); 53 //countUp = Integer.getInteger(barText);エラーがでる。 54 countUp++; 55 56 textView = findViewById(R.id.bar_right); 57 textView.setText("String.valueOf(countUp)"); 58 } 59} 60

#試したこと
setTextを使っての変更(止まってしまう)

ボールが壁に当たったタイミングでtextviewを変更できるようにできませんか?
java android ともに初心者で変なことをしているかもしれませんがどなたか教えていただけませんか。

#追加
このようにupdateを実行しています。

@Override public void surfaceCreated(SurfaceHolder holder) { windowsWidth = getWidth(); windowsHeight = getHeight(); draw(); startnow(); } public void draw(){ Canvas c = getHolder().lockCanvas(); //背景の描画 backGroundBitmap= BitmapFactory.decodeResource(getResources(), R.drawable.wood); //bitmap大きさ設定 backGroundBitmap = Bitmap.createScaledBitmap(backGroundBitmap, windowsWidth, windowsHeight, false); c.drawBitmap(backGroundBitmap, 0, 0, myPaint); //ボールの描画 c.drawBitmap(ball.myBitmap, ball.x, ball.y, myPaint); holder.unlockCanvasAndPost(c); } public void startnow(){ ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); executor.scheduleAtFixedRate(new Runnable() { @Override public void run() { ball.update(); Log.d("test", "ループ"); draw(); } }, 100, 100, TimeUnit.MICROSECONDS); }

#構成

public class SimulationView{ class Ball { public void update() {} } }

のようになっています。

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

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

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

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

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

kakajika

2018/04/16 13:23

止まった時にコンソールにエラーログなどはでていませんか?また、SimulationViewのupdateは自前のThreadやTimer内で実行していますか?
sakuramoti

2018/04/16 13:43

updateの部分を追加いたしました。止まった時エラーは出ていないと思います。
keicha_hrs

2018/04/16 13:59

main = new MainActivity() とかやってるのが原因ですよね・・・
sakuramoti

2018/04/16 14:05 編集

SimulationView class でfindViewbyidをするとnullpointerexeptionになってしまったのでこうやってみました。 どのようにすればよいか教えていただけないでしょうか?
kakajika

2018/04/16 14:05

あ、ほんとですね^^;
keicha_hrs

2018/04/16 14:25 編集

update()ってどこにあるメソッドなのですか?SimulationViewクラス?それとも、Ballクラス?
keicha_hrs

2018/04/16 15:31 編集

これは二重苦状態になっていますね。まずMainActivityのインスタンスを新たに生成している点ですが、これを参照して呼び出したメソッドの中でfindViewById()を用いても、正しい結果は得られません。そもそも、ActivityのインスタンスはAndroidフレームワークがその管理下で作成するもので、ユーザーが任意に作成してはいけないものです。それから、update()をScheduledExecutorServiceによる実装タスクの中から呼び出している点。ここで実装したRunnableは別スレッドでの動作になりますが、Activity上に描画されているコンポーネントは、Activityと同じスレッド(UIスレッドと呼ばれます)でなければ操作できません。この二重の問題のために、申し訳ないけどすぐに答えを出せません。ちょっと考えてはみますが・・・
sakuramoti

2018/04/16 21:00

かしこまりました。お時間を割いてくださり大変ありがとうございます。
guest

回答1

0

ベストアンサー

ざっとですが、こうしたらどうかという案を考えてみました。まずコードです。変更点とその周辺のみを記述しています。

MainActivity.java

Java

1 2 @Override 3 protected void onCreate(Bundle savedInstanceState) { 4 super.onCreate(savedInstanceState); 5 setContentView(R.layout.activity_main); 6 7 // MainActivityのインスタンスを渡す処理を追加 8 SimulationView simView = findViewById(R.id.canvas); 9 simView.getMainActivity(this); 10 11 setBarText(); 12 } 13 14

SimulationView.java

Java

1 2 public void init() { 3 4 5 // main = new MainActivity(); // これはやめる 6 } 7 8 // MainActivityのインスタンスを受け取るメソッドを追加 9 void getMainActivity(MainActivity m) { 10 main = m; 11 } 12 13 public void startnow() { 14 ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); 15 executor.scheduleAtFixedRate(new Runnable() { 16 @Override 17 public void run() { 18 main.runOnUiThread(ball); // runOnUiThread()に変更 19 Log.d("test", "ループ"); 20 draw(); 21 } 22 }, 100, 100, TimeUnit.MICROSECONDS); 23 } 24 25 // BallにRunnableを実装 26 class Ball implements Runnable { 27 28 // run()の中でupdate()を呼ぶ 29 @Override 30 public void run() { 31 update(); 32 } 33 34 void update() { 35 // この中は変更なし 36 } 37 } 38

MainActivityの持つメソッドを呼ぶために、SimulationViewにgetMainActivity()というメソッドを追加します。このメソッドを介して、MainActivityのインスタンスを受け取って保存します。newするのではなくすでに存在するインスタンスを受け取って参照することで、countUpBarText()も正常に動くはずです。

それから、scheduleAtFixedRate()の問題を解決するため、まずBallにRunnableを実装します。Ballの中にrun()をオーバーライドして、その中からupdate()を呼び出すようにします。

そして、scheduleAtFixedRate()に記述したrun()の中では、update()を直接呼ぶのではなく、runOnUiThread()を呼び出すように変更します。これは、メソッド名を呼んで字の如くで、UIスレッドで処理して欲しい内容を他スレッドから渡すためのメソッドです。これはActivityが持つメソッドなので、mainを参照して呼び出します。その引数として、Runnableを実装したBallのインスタンスを渡すようにします。

こんな感じでどうでしょうかね?テストしていない(できない)ので動く保証はできませんが・・・。


(2017/04/19追記)
kakajikaさんのご指摘を受けて書き直したものです。前のものは残しておきます。

MainActivity.java

Java

1// SimulationView.OnSimulationUpdateListenerを実装(implements) 2public class MainActivity extends AppCompatActivity implements SimulationView.OnSimulationUpdateListener { 3 4 @Override 5 protected void onCreate(Bundle savedInstanceState) { 6 super.onCreate(savedInstanceState); 7 setContentView(R.layout.activity_main); 8 9 // Listenerをセットする 10 SimulationView simview = findViewById(R.id.canvas); 11 simview.setOnSimulationUpdateListener(this); 12 13 setBarText(); 14 } 15 16 17 //壁に当たった時に呼ばれる 18 @Override 19 public void countUpBarText(int key) {//textviewを変更する 20 // この中は変更なし 21 } 22} 23

SimulationView.java

Java

1public class SimulationView extends SurfaceView implements SurfaceHolder.Callback { 2 3 //private MainActivity main; // これはやめる 4 private OnSimulationUpdateListener mListener; // 追加 5 6 void setOnSimulationUpdateListener(OnSimulationUpdateListener listener) { 7 mListener = listener; 8 } 9 10 public void startnow() { 11 ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); 12 executor.scheduleAtFixedRate(new Runnable() { 13 @Override 14 public void run() { 15 post(ball); // post()に変更 16 Log.d("test", "ループ"); 17 draw(); 18 } 19 }, 100, 100, TimeUnit.MICROSECONDS); 20 } 21 22 class Ball implements Runnable { 23 24 // run()の中でupdate()を呼ぶ 25 @Override 26 public void run() { 27 update(); 28 } 29 30 void update() { 31 //右壁 32 if (x < 0) { 33 checkBar = 1; 34 mListener.countUpBarText(checkBar); // mListenerを参照 35 dx = -dx; 36 } 37 38 // 以降、同様にmainをmListenerに置き換える 39 40 } 41 } 42 43 interface OnSimulationUpdateListener { 44 void countUpBarText(int key); 45 } 46}

interfaceの解説をするのはちょっと辛いので、書籍やネットの資料を参考にしてください。やっていることの趣旨としては、前とさほど違いはありません。

> kakajikaさん

こんなところでどうでしょうか・・・。(あまり自信ない)

投稿2018/04/17 16:25

編集2018/04/19 13:04
keicha_hrs

総合スコア6768

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

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

kakajika

2018/04/19 04:34

できればMainActivityをそのまま渡すのは密結合になってしまって避けたいので、interface(例えばOnSimulationUpdateListener)で定義してMainActivityにそれを実装する、という形がいいかなと思います。メインスレッドでの実行は、Activityを経由しなくてもView::postで可能です。
keicha_hrs

2018/04/19 13:29 編集

以前も密結合についてご指摘を受けたことがあったので、またやってしまいました。無用に混乱させて、質問者様においては申し訳ないです。
kakajika

2018/04/19 14:08

回答修正ありがとうございます、いいと思います! つい気になってツッコミ入れてしまって、すみません。
sakuramoti

2018/04/19 16:54

返信遅くなり申し訳ありません。 またkeicha_hrs さん kakajikaさん 回答ありがとうございます! 無事に止まることなくcountUpできました。 このような実装方法は始めてでしたので大変勉強になりました。View の操作はmainからということを忘れないようにします。 お二方アドバイス本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問