View.setVisibility (View.VISIBLE) перестает работать после запуска другого действия, только если это представление ранее не было видно на Android API <28 - PullRequest
0 голосов
/ 19 октября 2019

Я делаю простую игру для 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, но это не решило проблему.

1 Ответ

0 голосов
/ 22 октября 2019

Как указал Ришабх, у меня не должно было быть getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); после setContentView(). Вот что вызывало проблемы.

...