1

画面の色をランダムに変更し、色の 16 進コードをテキストビューに表示する単純なアプリを実装しました。たくさんの検索 (特に、stackoverflow に関する多くの投稿) の後、私が望むことを行うコードがほとんどできました。1つだけ矛盾があります。色が点滅するランナブルをクリックして再起動すると、中断したところから「再開」します。つまり、最初は完全な遅延は行われず、停止したときにおそらく中断された時間を遅延させるだけのようです。

私の完全なコードは以下のとおりです。現在、短押しで画面の色の点滅を開始し、長押しで停止します。

package com.example.colorflashingproject;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.view.Menu;
import android.view.View;
import android.os.Handler;
import android.widget.TextView;

public class MainActivity extends Activity {

//initialize a boolean variable (true or false only) 
//to check whether the overlay is tinted or not
boolean isTinted = false;
boolean colorIsFlashing = false;

//initialize a handler that we will use to loop a section of code
//that constantly changes the color of the screen
public Handler mHandler = new Handler();

//this creates the UI and screen view, and sets up some
//other aspects of the program
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //set the current view in the user interface as our xml file:
    setContentView(R.layout.activity_main);

    //set the background color, and the initial overlay tint:
    ((View)findViewById(R.id.background_view)).setBackgroundColor(0xFF000000);
    ((View)findViewById(R.id.overlay_view)).setBackgroundColor(0x00000000);

    //create the overlayView variable that replesents our overlay for tinting
    View overlayView = findViewById(R.id.overlay_view);

    //implement a method that will listen for a short press
    overlayView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //implement function to change tint of our overlay
            if (!colorIsFlashing) {
                colorIsFlashing = true;
                mHandler.post(startColorFlashing);
            } else {

            }
        }
    });     

    //implement a method that will listen for long press:
    overlayView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {

            //stop the color flashing if it was started:
            if (colorIsFlashing) {
                colorIsFlashing = false;
                stopColorFlashing();
            }

            //return true tells the system that the long press registered
            //return false doesn't. A false return would cause
            //the long click to register as a short click as well
            return true;
        }
    });

}


//this function generates a random color and sets it to the screen
public void randomChangeTint(){
    //generate random color components:
    int randa = (int) Math.round((int) 0xff * (float) Math.random());
    int randr = (int) Math.round((int) 0xff * (float) Math.random());
    int randg = (int) Math.round((int) 0xff * (float) Math.random());
    int randb = (int) Math.round((int) 0xff * (float) Math.random());
    int randColor = Color.argb(randa, randr, randg, randb); 

    //convert color integer to string:
    String strColor = String.format("#%08X", randColor);

    //set overlay to our generated random color:
    ((View)findViewById(R.id.overlay_view)).setBackgroundColor(randColor);
    ((TextView)findViewById(R.id.textView2)).setText(strColor);
}


//this is our 'runnable' that randomly sets the screen color over
//an interval of time in milliseconds (timeInterval)
public Runnable startColorFlashing = new Runnable(){
    //set overlay view to randomly switch colors
    int timeInterval=600;
    public void run() {
        if (colorIsFlashing){
            randomChangeTint();
        } else {

        }
        mHandler.postDelayed(this, timeInterval);
    }
};


//this method stops the color flashing:
public void stopColorFlashing() {

    //pauses the runnable:
    mHandler.removeCallbacksAndMessages(startColorFlashing);

    //re-initializes the runnable as an empty one
    startColorFlashing = new Runnable(){
        public void run() {
            //empty, nothing here
        }
    };
}
}

私が省略した場合

    //re-initializes the runnable as an empty one
    startColorFlashing = new Runnable(){
        public void run() {
            //empty, nothing here
        }
    };

stopColorFlashing() の一部であり、画面を複数回続けて短く押すと、ランナブルが何度も開始されたように見えます。停止した後、短く押して再起動すると、停止した場所から再開しているように見えます。「あらためて」始めてほしい。

Thread.start() と Thread.pause() でいくつか試してみましたが、わかりません。ランナブルを「殺す」または「破壊する」方法はありますか?

私はJavaが初めてで(matlabを知っています)、アイデアや推奨事項を歓迎します。私のコードは非常に貧弱で非効率的に書かれていると確信しています。

4

1 に答える 1

1

OK、スクリーンセーバーモードで1分ごとに時間表示を移動する方法のAOSPデスククロックの例に従うことで解決策を見つけました。私が考えるキーは、Handler の removeMessages メソッドでした (それは Method ですよね?)。また、Runnable で UI の更新を常に投稿するのではなく、呼び出した UI 更新メソッド generateRandomColor() を呼び出して遅延メッセージをハンドラーに送信し、ハンドラーがメソッド generateRandomColor() を再度呼び出すため、ループが発生します。これはまだ最善の方法ではないかもしれませんが、簡潔で機能します。

以下のコードは、私がやりたかったことを正確に実行します。これが、ハンドラーに関する同様の問題を探している人に役立つことを願っています...

package com.example.testproject04;

/* import necessary libraries for 
 * our objects classes and widgets 
 * that we use here
 */
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.view.View;
import android.os.Handler;
import android.widget.TextView;
import android.os.Message;

/* declare the main class/activity of this program */
public class MainActivity extends Activity {

/* initialize a boolean variable (true or false only) to 
 * check whether the screen is flashing new colors or not */
boolean colorIsFlashing = false;

/* update interval in milliseconds */
public int updateDelay = 800; 

/* 'message' to change color (used by handler) */
int CHANGE_COLOR_MSG = 0x0; 

/* this creates the UI and screen view, 
 * and sets up some other aspects of the program */
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    /* set the current view in the 
     * user interface as our xml file:
     */
    setContentView(R.layout.activity_main);

    /* set the background color, 
     * and the initial overlay tint:
     */
    ((View)findViewById(R.id.background_view)).setBackgroundColor(0xFF000000);
    ((View)findViewById(R.id.overlay_view)).setBackgroundColor(0x00000000);

    /* create the overlayView variable that 
     * represents our overlay for tinting
     */
    View overlayView = findViewById(R.id.overlay_view);

    /* implement a method that will listen for a short press, 
     * when short press occurs, if the screen is not currently 
     * flashing, it will start flashing periodically
     */
    overlayView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (!colorIsFlashing){
                colorIsFlashing = true;
                mHandler.sendEmptyMessageDelayed(CHANGE_COLOR_MSG, updateDelay);
            } 
        }
    }); 

    /* implement a listener for long presses on the screen, 
     * when a long press occurs, 
     * if the screen is flashing, it will stop 
     */
    overlayView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            if (colorIsFlashing) {
                colorIsFlashing = false;
                mHandler.removeMessages(CHANGE_COLOR_MSG);
            }
            return true;
        }
    }); 

}

/* initialize a handler that we will use 
 * to change the color of the screen 
 */
private final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message m) {
        if (m.what == CHANGE_COLOR_MSG) {
            generateRandomColor();
        }
    }
};

/* this function generates a random color
 *  and sets it to the screen 
 */
public void generateRandomColor(){
    if (!colorIsFlashing) return;

    /* generate random color components: */
    int randa = (int) Math.round((int) 0xff * (float) Math.random());
    int randr = (int) Math.round((int) 0xff * (float) Math.random());
    int randg = (int) Math.round((int) 0xff * (float) Math.random());
    int randb = (int) Math.round((int) 0xff * (float) Math.random());
    int randColor = Color.argb(randa, randr, randg, randb); 

    /* convert color integer to string: */
    String strColor = String.format("#%08X", randColor);

    /* set overlay to our generated random color
     *  and update textview to display color in hex code
     */
    ((View)findViewById(R.id.overlay_view)).setBackgroundColor(randColor);
    ((TextView)findViewById(R.id.textView2)).setText(strColor);

    mHandler.sendEmptyMessageDelayed(CHANGE_COLOR_MSG, updateDelay);
}

}

追加の検索タグ/情報: UI スレッド内のコードのループ、ハンドラーを使用した Android アクティビティのループの停止、ハンドラーからのメッセージの削除、ハンドラーへの遅延メッセージの送信

于 2013-03-20T18:02:45.403 に答える