Я делаю простую игру для Android. У меня есть несколько представлений с кнопками, которые настроены на видимость для пропущенного в макете, и когда я хочу показать их, я просто устанавливаю видимость видимым. Вот макет:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="@+id/Container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:background="#000000"
android:orientation="vertical">
</LinearLayout>
<LinearLayout
android:id="@+id/Menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|center_vertical"
android:orientation="vertical"
android:padding="5dip"
android:visibility="gone"
android:background="@drawable/menu_design"
android:textColor="#ffffffff">
<TextView
android:id="@+id/MenuLabel"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:padding="3dip"
android:layout_margin="5dip"
android:gravity="center"
android:textColor="#ffffffff"
android:textSize="20dip"
android:text="Main Menu" />
<TextView
android:id="@+id/Op1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="contin"
android:clickable="true"
android:padding="10dip"
android:layout_margin="5dip"
android:background="@drawable/button_design"
android:gravity="center"
android:textColor="#ffffffff"
android:textSize="20dip"
android:text="Continue" />
<TextView
android:id="@+id/Op2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="restart"
android:clickable="true"
android:padding="10dip"
android:layout_margin="5dip"
android:background="@drawable/button_design"
android:gravity="center"
android:textColor="#ffffffff"
android:textSize="20dip"
android:text="New Game" />
<TextView
android:id="@+id/Sound"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="sound"
android:clickable="true"
android:padding="10dip"
android:layout_margin="5dip"
android:background="@drawable/button_design"
android:gravity="center"
android:textColor="#ffffffff"
android:textSize="20dip"
android:text="Sound" />
<TextView
android:id="@+id/Settings"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="settings"
android:clickable="true"
android:padding="10dip"
android:layout_margin="5dip"
android:background="@drawable/button_design"
android:gravity="center"
android:textColor="#ffffffff"
android:textSize="20dip"
android:text="Settings" />
</LinearLayout>
<LinearLayout
android:id="@+id/GameOver"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|center_vertical"
android:orientation="vertical"
android:padding="5dip"
android:visibility="gone"
android:background="@drawable/menu_design"
android:textColor="#ffffffff">
<TextView
android:id="@+id/Score"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:padding="10dip"
android:layout_margin="5dip"
android:gravity="center"
android:textColor="#ffffffff"
android:textSize="23dip"
android:text="Your Score:" />
<TextView
android:id="@+id/HighScore"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:padding="10dip"
android:layout_margin="5dip"
android:gravity="center"
android:textColor="#ffffffff"
android:textSize="20dip"
android:text="HighScore:" />
<TextView
android:id="@+id/LeaveGameOver"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="leaveGameOver"
android:clickable="true"
android:padding="10dip"
android:layout_margin="5dip"
android:background="@drawable/button_design"
android:gravity="center"
android:textColor="#ffffffff"
android:textSize="20dip"
android:text="Main Menu" />
</LinearLayout>
</FrameLayout>
Это работает безупречно при запуске пользователем. Когда он запускается самой игрой в другом потоке, я должен использовать runOnUiThread:
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Menu.showHighscore(score,original);
}
});
Вот showHighscores:
public static void showHighscore(int s, int hs) {
gameOver = act.findViewById(R.id.GameOver);
System.out.println("Visiblity: " + gameOver.getVisibility());
score.setText("Your Score: " + s);
highScore.setText("HighScore: " + hs);
gameOver.setVisibility(View.VISIBLE);
System.out.println("NORMAL HIGHSCORE");
System.out.println("Visiblity: " + gameOver.getVisibility());
}
Это работало нормально. Нет проблем, если я иду в другое приложение и обратно. Но проблемы возникли, когда я добавил функции, запускающие другие действия: приложение для оценки, меню согласия и промежуточные объявления.
Нет проблем в Android 9 (API 28), но в более старых версиях Android, начиная с API 27 и нижеУ меня проблемы с некоторыми обновлениями пользовательского интерфейса не происходит:
- Например, приведенный выше код (showHighscores) не будет отображать меню GameOverMenu, даже если его статус меняется на видимый.
- Если я установлю его невидимым, а не в файл XML, ИЛИ если я покажу его и скрою до того, как возникнет проблема, он появится, но будет выглядеть, будто setText не работает.
Вот что может вызвать проблему:
- Отображение формы согласия всегда будет вызывать ее, независимо от того, когда выполняется приведенный ниже код (даже в onCreate):
public void displayConsentForm() {
URL privacyUrl = null;
try {
// TODO: Replace with your app's privacy policy URL.
privacyUrl = new URL("https://r.flycricket.io/privacy.html");
} catch (MalformedURLException e) {
e.printStackTrace();
// Handle error.
}
consentForm = new ConsentForm.Builder(context, privacyUrl)
.withListener(new ConsentFormListener() {
@Override
public void onConsentFormLoaded() {
consentForm.show();
}
@Override
public void onConsentFormOpened() {
// Consent form was displayed.
}
@Override
public void onConsentFormClosed(ConsentStatus consentStatus, Boolean userPrefersAdFree) {
// Consent form was closed.
if(userPrefersAdFree==true)
{
startBuy();
}
else
{
ConsentInformation.getInstance(context).setConsentStatus(consentStatus);
}
}
@Override
public void onConsentFormError(String errorDescription) {
// Consent form error.
}
})
.withPersonalizedAdsOption()
.withNonPersonalizedAdsOption()
.withAdFreeOption()
.build();
consentForm.load();
}
- Функция «Оценить приложение» активирует ее, но только если она была вызвана взаимодействием с пользователем. Если я помещаю тот же код в конец onCreate, чтобы он выполнялся при запуске программы, это НЕ вызывает проблему:
public void rateApp(View v) {
Uri uri = Uri.parse("market://details?id=" + context.getPackageName());
Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri);
// To count with Play market backstack, After pressing back button,
// to taken back to our application, we need to add following flags to intent.
goToMarket.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY |
Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
try {
startActivity(goToMarket);
} catch (ActivityNotFoundException e) {
startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("http://play.google.com/store/apps/details?id=" + context.getPackageName())));
}
}
- Отображение вставки также вызывает ее. Я не смог подтвердить, вызывает ли это проблему в onCreate, потому что в тот момент он еще не загружался.
Я думаю, что это как-то связано с началом новой активности и возвращением изЭто. У меня нет этой проблемы, когда я приостанавливаю и возобновляю игру.
Это мои onPause и onResume:
public void onPause() {
super.onPause();
//Menu.pause();
Units.kill=true;
System.out.println("Killing");
sound.stopSounds();
while(true) {
try {
animThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
animThread=null;
}
public void onResume() {
super.onResume();
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
Units.kill = false;
animThread = new AnimationThread(this);
animThread.setDaemon(true);
animThread.setPriority(8);
animThread.start();
if(FullscreenActivity.sound.beam==true)FullscreenActivity.sound.startCannon();
//if(Units.showAds==true && billingClient.isReady()) checkPurchases();
}
Я пытался поместить код onPause в начале displayConsentForm и onResumeкод в onConsentFormClosed, но это не решило проблему.