Я пытаюсь заставить андроид мигать как предупреждение пользователю (весь экран). Чтобы заставить его мигать, я вставил ImageView в действие, равное размеру дисплея и белому цвету, который изменит его видимость с видимого на исчезнувший. Я изучал возможность создания внешнего потока, но позже обнаружил, что внешние потоки не могут изменять компоненты пользовательского интерфейса. Мне нужно приостановить поток между изменениями флэш-памяти, что означает, что я не смогу поместить его в основной поток пользовательского интерфейса. Как мне реализовать что-то подобное?
Я добавил часть своего кода ниже:
XML
<ImageView
android:id = "@+id/alertScreen"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:visibility = "gone"
app:srcCompat = "@android:color/white" />
Main.java
public static boolean flashOn = false;
public static boolean endFlash = false;
public static Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.aircraft_main);
AircraftMain.context = getApplicationContext();
flash = (Button) findViewById(R.id.flashTest);
flash.setOnClickListener(flashBtnOnClickListener);
}
View.OnClickListener flashBtnOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View arg0) {
AsyncTask.execute(new Runnable() {
public void run(){
AlertFlash alert = new AlertFlash(3);
alert.run();
ImageView v = findViewById(R.id.alertScreen);
while (endFlash != true) {
if (flashOn = true) {
v.setVisibility(View.VISIBLE);
} else {
v.setVisibility(View.GONE);
}
}
}
});
}
};
AlertFlash.java
public class AlertFlash implements Runnable {
public static volatile int flashes;
boolean suspendFlag, end;
public AlertFlash (int flashNo) {
flashes = flashNo * 2;
suspendFlag = false;
end = false;
}
public void run() {
for (int i = 0; i<=flashes; i++) {
if (suspendFlag = false) {
AircraftMain.flashOn = true;
suspendFlag = true;
}
else {
AircraftMain.flashOn = false;
suspendFlag = false;
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
end = true;
}
}




Используя Activity.runOnUiThread(), вы можете изменять элементы пользовательского интерфейса из фонового потока.
Вот как я бы поступил в вашей ситуации. Внутри Main.java я бы начал с создания простого метода для изменения видимости переданного представления, особенно в потоке пользовательского интерфейса:
private void setViewVisibility(final View view, final int visibility) {
runOnUiThread(new Runnable() {
@Override
public void run() {
view.setVisibility(visibility);
}
});
}
Затем я бы изменил цикл while на следующий:
while (endFlash != true) {
if (flashOn = true) {
setViewVisibility(v, View.VISIBLE);
} else {
setViewVisibility(v, View.GONE);
}
}
Обновлено:, чтобы предотвратить проблемы с циклом while, мы можем полностью обойти его, передав activity и view при создании объекта AlertFlash. См. ниже.
public class AlertFlash implements Runnable {
public static volatile int flashes;
boolean suspendFlag, end;
private Activity activity;
private View view;
public AlertFlash (int flashNo, Activity activity, View view) {
flashes = flashNo * 2;
suspendFlag = false;
end = false;
this.activity = activity;
this.view = view;
}
public void run() {
for (int i = 0; i<=flashes; i++) {
if (suspendFlag = false) {
AircraftMain.flashOn = true;
suspendFlag = true;
}
else {
AircraftMain.flashOn = false;
suspendFlag = false;
}
final int visibility = AircraftMain.flashOn ? View.VISIBLE : View.GONE;
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
view.setVisibility(visibility);
}
});
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
end = true;
}
}
Я не могу сказать наверняка по тому, на что я здесь смотрю. Где для endFlash устанавливается значение true?
Я изменил это. В AlertFlash.java я изменил конечное условие на Main.endFlash = true, которое изменяет условие остановки в файле Main.java. Но кажется, что цикл while выполняется только после полного запуска AlertFlash.java. Следовательно, он не выполняет цикл while, потому что было вызвано условие остановки. Куда можно переместить цикл while, чтобы он выполнялся на каждой итерации цикла for AlertFlash.
Смотрите мою последнюю правку. Попробуйте передать действие и представление непосредственно в объект AlertFlash, а затем измените видимость представления там. В этом случае цикл while не нужен.
В классе alertflash есть ошибка if (suspendFlag = false) {должно быть if (! SuspendFlag) {
Спасибо. При реализации этого кажется, что только первый результат «мигает», даже если он выполняет полный цикл for. Следует ли переместить цикл while в другое место?