2017-01-31 7 views
1

私が開発しているアプリでは、ユーザー入力後にUIをリロードすることが基本的でした。私は、活動を破壊/再作成するのを避け、代わりにsetContentView()を使用したいと思っていました。fitsSystemWindows = "true"はsetContentView()を呼び出した後に機能しません

私がそれをしたとき、新しく作成されたUIはfitsSystemWindows="true"を尊重しておらず、その一部はアンドロイドのステータスバーの後ろにあります。

私はそれをテストするために、そのコード例にそれを煮詰めるために管理:

layout.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 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:id="@+id/mainContainer" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:fitsSystemWindows="true" 
    android:orientation="vertical"> 
    <Button 
     android:text="Button" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:id="@+id/button" /> 
</LinearLayout> 

MainActivity.java

import android.os.Bundle; 
import android.support.v7.app.AppCompatActivity; 
import android.view.View; 
import android.widget.Button; 

public class MainActivity extends AppCompatActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.layout); 

     Button button = (Button) findViewById(R.id.button); 
     button.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       reloadUI(); 
      } 
     }); 

    } 

    public void reloadUI() { 
     setContentView(R.layout.layout); 
    } 
} 

を私がロードしますアプリ、私は期待されたレイアウトを得る、それは画面の上に、ステータスbのすぐ下の簡単なボタンですAR:mainContainer.getMeasuredHeight()を呼び出す

enter image description here

:私は(同じXMLを示す)は、第2の時間setContentViewを呼び出すボタンをクリックすると

enter image description here

しかし、ボタンがステータスバーの後ろに取得します何が起きているかを調べると、アプリの最初の起動時に1848px(1920pxの高さの画面で、画面全体の高さは72px、ステータスバーの高さは72pxになります)が、setContentViewをもう一度呼び出すとmainContainer.getMeasuredHeight()は私に1920ピクセルを与えます。

ここに何か不足していますか?私はmainContainerを72pxのトップパディングで1848pxの高さに固執させることができましたが、このような醜いハックを避けることを好むでしょう。

+0

は、なぜあなたは再び 'setContentView'を呼び出していますか?代わりに 'viewgroup'全体を'無効にする 'ことができます。 – Wizard

+0

私はそれを試みましたが、すべてを正しくリセットしません。たとえば、私のユースケースでは、ユーザーがカスタムビュークラス内に格納されている特定の色に設定できるカスタムビューがあります。無効にするとデフォルトにリセットされず、UIが再描画されます。私は正しく無効化を処理する私のアプリケーションの一部をリファクタリングすることができますが、私はsetContentViewを使用すると、新しい状態を取得し、UIをデフォルト状態にリロードする方が速いと考えました。 – TheAthenA714

答えて

0

私は同じ問題を抱えていました。私の解決策はrootViewmarginTopまたはpaddingTopViewに手動で変更することです。

0

だから、もう一度WindowInsetsをルートビューにディスパッチするようにフレームワークに依頼してください。それは正確にViewCompat.requestApplyInsets(View)が行うことです:

View.onApplyWindowInsets(WindowInsets)の新しいディスパッチが実行されることを尋ねます。利用可能であれば、これはView.requestFitSystemWindows()に戻ります。ちょうど1行を適用

は、すべてのあなたの懸念を解決する必要があります

 


    public void reloadUI() { 
     setContentView(R.layout.layout); 
     // `R.id.mainContainer` is the id of the root view in `R.layout.layout` 
     ViewCompat.requestApplyInsets(findViewById(R.id.mainContainer)); 
    } 

 
関連する問題