-2

My Appはナビゲーションドロワーと4つのフラグメントで構成されています。 このアプリの古いバージョンではアクティビティが使用されているため、そのアクティビティをフラグメントでトランスフォームする必要があります。今、すべてのためにAndroid force画面の向きが変更されたときにフラグメントの再描画が行われます

ユーザーがテキストと背景色を設定することができますし、DialogActivityを呼び出す方法は、すべてのFragmentsと管理のためのFragments内部ダイアログで呼ばonActivityResultsを管理する唯一のMainActivityであることをうまく動作しますが、1 Fragmentに私は80 Buttonsを持っていますユーザーの変更。

画面の向きが横向きに変更されると問題が発生します。 Buttonsを押してテキストと色を設定した場合はポートレートがですが、ランドスケープでの画面の向きを変更すると、バックグラウンドのような「影」のようなものが表示され、私が持っているボタンは、私は再び画面を回転させると、変更されたボタンが見えるようになりました。 奇妙なことに、フラグメントの背景には、正しい更新が付いたボタンが表示されますが、上には表示されません...(写真を投稿すると説明が難しい)

私が変更した古いボタンは、 ...私はDBに保存しますが、風景と、私はCHE他のボタンを更新することはできません

enter image description here

CODE:

MainActivity.java

public class MainActivity extends AppCompatActivity 
     implements NavigationView.OnNavigationItemSelectedListener { 


    static String clickedButtonViewId; 

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

     setContentView(R.layout.activity_main); 

     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 


     DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
     ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
       this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); 
     drawer.setDrawerListener(toggle); 
     toggle.syncState(); 

     NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); 
     navigationView.setNavigationItemSelectedListener(this); 

     if (findViewById(R.id.content_frame) != null){ 

      getSupportFragmentManager().beginTransaction() 
        .add(R.id.content_frame, new OrarioFragment()).commit(); 
     } 
    } 

    @Override 
    public void onBackPressed() { 
     DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
     if (drawer.isDrawerOpen(GravityCompat.START)) { 
      drawer.closeDrawer(GravityCompat.START); 
     } else { 
      super.onBackPressed(); 
     } 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.main, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle action bar item clicks here. The action bar will 
     // automatically handle clicks on the Home/Up button, so long 
     // as you specify a parent activity in AndroidManifest.xml. 
     int id = item.getItemId(); 

     //noinspection SimplifiableIfStatement 
     if (id == R.id.action_settings) { 
      return true; 
     } 

     return super.onOptionsItemSelected(item); 
    } 

    @SuppressWarnings("StatementWithEmptyBody") 
    @Override 
    public boolean onNavigationItemSelected(MenuItem item) { 
     // Handle navigation view item clicks here. 
     int id = item.getItemId(); 

     FragmentManager fragmentManager = getSupportFragmentManager(); 

     if (id == R.id.nav_orario) { 

      fragmentManager.beginTransaction() 
        .replace(R.id.content_frame, new OrarioFragment()) 
        .commit(); 

     } else if (id == R.id.nav_calendario) { 

      fragmentManager.beginTransaction() 
        .replace(R.id.content_frame, new CalendarioFragment()) 
        .commit(); 

     } else if (id == R.id.nav_voti) { 

      fragmentManager.beginTransaction() 
        .replace(R.id.content_frame, new VotiFragment()) 
        .commit(); 

     } else if (id == R.id.nav_registrazioni) { 

      fragmentManager.beginTransaction() 
        .replace(R.id.content_frame, new RegistrazioniFragment()) 
        .commit(); 

     } else if (id == R.id.nav_share) { 

     } else if (id == R.id.nav_send) { 

     } 

     DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
     drawer.closeDrawer(GravityCompat.START); 
     return true; 
    } 


    public void addMateria(View v){ 

     /* Prendo il nome della risorsa cosi nel ricompilare il progetto non perdo * 
     * tutti i riferimenti ai bottoni salvati nel database      */ 

     clickedButtonViewId = getResources().getResourceEntryName(v.getId()); 

     //StartActivityForResult perche mi aspetto la materia inserita dall'altra activity 
     Intent myIntent = new Intent(MainActivity.this, ActivityAddMateria.class); 
     startActivityForResult(myIntent, 1); 
     //onStop(); 
    } 

    //Take back data from ActivityAddMateria 
    public void onActivityResult(int requestCode, int resultCode, Intent data) { 
     if(requestCode == 1) { 
      if (resultCode == RESULT_OK) { 

       MySQLiteHelper db = new MySQLiteHelper(this); 

       //Cambio subito il Button 
       int resId = getResources().getIdentifier(clickedButtonViewId, "id", getPackageName()); 
       final Button clickedtextView = (Button) findViewById(resId); 

       String result = data.getStringExtra("result"); //Take the materia from Dialog 
       int color = data.getIntExtra("color", 1); //Take the color from Dialog 

       //Controllo se il Button è già presente nel db se presente aggiorno se non presente inserisco 
       boolean modifica = db.Exists(clickedButtonViewId); 

       //Se voglio ripristinare il bottone di default 
       if (color == getResources().getColor(R.color.blue_orario)) { 

        //Ripristino la grafica di Default 
        Drawable style = setButtonColor(color); 
        clickedtextView.setBackground(style); 
        clickedtextView.setText("New"); 

        //Se la materia è nel database la cancello 
        if (modifica) { 

         db.deleteSingleMateria(clickedButtonViewId); 

        } 

       } else { 
        //Quando inserisco un normale bottone colorato 
        if (!modifica) { 

         //Materia da inserire in un nuovo spazio 
         db.addMateriaToDb(new Materia(clickedButtonViewId, result, color)); 

        } else { 

         //Materia già presente nel Button quindi aggiorno la materia 
         db.updateMateria(new Materia(clickedButtonViewId, result, color)); 
         Toast.makeText(getApplicationContext(), "Materia modificata!", 
           Toast.LENGTH_LONG).show(); 
        } 

        //Inserisco la materia nel DB dei voti_media 
        db.addMateriaVotiFromOrario(new MaterieVoti(result, 0.0)); 

        clickedtextView.setText(result); 
        //clickedtextView.setBackgroundColor(color); 
        //clickedtextView.getBackground().setColorFilter(color, PorterDuff.Mode.MULTIPLY); 
        Drawable style = setButtonColor(color); 
        clickedtextView.setBackground(style); 
       } 
      } 

      if (resultCode == RESULT_CANCELED) { 
       //Nessuna materia inserita 
      } 

     } 
    }//onActivityResult 

EDIT

[OK]を私は問題を発見しました。私は力のため

if (findViewById(R.id.content_frame) != null){ 

      getSupportFragmentManager().beginTransaction() 
        .add(R.id.content_frame, new OrarioFragment()).commit(); 
     } 

そしてMainActivityが再作成された画面の向きの変更と古い断片上同じフラグメントをロードするために示されるべき最初のフラグメントをコード行を有するMainActivityで

私は.add()を使用します。

これで、この問題を回避し始めるときに、どのようにフラグメントを表示するように設定できますか?

引き出しの管理に間違っていますか?

+0

コードを表示します。 – Bryan

+0

@ブライアンはコードを追加しただけでもっと分かります。 – Dario

+0

あなたのレイアウトも共有できますか? – JRG

答えて

1

Androidのドキュメントでは、状態の保存について説明し、アクティビティやフラグメントの状態を保存する方法についても説明しています。

の保存や、ユーザーとしての活動は、正常アプリの動作に破壊されているいくつかのシナリオがありますが、活動状態を復元「戻る」ボタンを押すか、アクティビティによってfinish()メソッドが呼び出され、自身の破壊が通知されます。また、アクティビティが停止状態で長期間使用されていない場合、またはフォアグラウンドのアクティビティがより多くのリソースを必要とする場合は、アクティビティを含むプロセスを破棄してメモリを回復できます。

ユーザーが[戻る]を押すかアクティビティが終了してアクティビティが破棄された場合、そのアクティビティがもはや必要でないことが示されているため、そのアクティビティインスタンスのシステム概念は永遠に失われます。しかし、システムが(通常のアプリケーションの動作ではなく)システムの制約のためにアクティビティを破壊した場合、実際のActivityインスタンスはなくなりますが、システムは、ユーザがそれに戻るとシステムが新しいアクティビティのインスタンスを、そのアクティビティが破棄されたときの状態を表すセーブされたデータのセットを使用して更新します。以前の状態を復元するためにシステムが使用する保存されたデータはインスタンス状態と呼ばれ、Bundleオブジェクトに格納されたキーと値のペアの集合です。

デフォルトでは、Bundleインスタンスの状態を使用して、アクティビティレイアウト内の各Viewオブジェクトに関する情報(EditTextウィジェットに入力されたテキスト値など)を保存します。 したがって、アクティビティインスタンスが破棄されて再作成された場合、レイアウトの状態はコードが不要な以前の状態に戻ります。ただし、アクティビティの進行状況を追跡するメンバー変数など、リストアしたい状態情報がさらに多くある場合があります。あなたの活動は、キーと値のペアのコレクションで状態情報を保存することができますので、

あなたの活動が停止し始めると、あなたの活動状態 を保存し、システムがonSaveInstanceState()メソッドを呼び出します。このメソッドのデフォルト実装では、EditTextウィジェット内のテキストやListViewウィジェットのスクロール位置など、アクティビティのビュー階層の状態に関する一時的な情報が保存されます。アプリは、onSauseInstanceState()コールバックをonPause()メソッドの後、onStop()の前に実装する必要があります。 onPause()でこのコールバックを実装しないでください。

注意:デフォルトの実装では、ビュー階層の状態を保存できるように、スーパークラス実装onSaveInstanceState()を呼び出す必要があります。

アクティビティの追加の状態情報を保存するには、onSaveInstanceState()をオーバーライドし、予期せずアクティビティが破棄されたイベントに保存されているBundleオブジェクトにキーと値のペアを追加する必要があります。たとえば、次のように

static final String STATE_SCORE = "playerScore"; 
static final String STATE_LEVEL = "playerLevel"; 
... 


@Override 
public void onSaveInstanceState(Bundle savedInstanceState) { 
    // Save the user's current game state 
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore); 
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel); 


    // Always call the superclass so it can save the view hierarchy state 
    super.onSaveInstanceState(savedInstanceState); 
} 

注:id属性:あなたの活動のビューの状態を復元するには、Androidシステムのためには、各ビューは、Androidから供給される固有のIDを持っている必要があります。

ユーザー設定やデータベースのデータなどの永続データを保存するには、アクティビティがフォアグラウンドにあるときに適切な機会を取る必要があります。そのような機会がない場合は、onStop()メソッドの間にそのようなデータを保存する必要があります。

は、あなたの活動状態の復元あなたの活動は、それが以前に破壊された後、あなたは、システムがあなたの活動に渡すバンドルから保存された状態を回復することができます再作成され 。 onCreate()およびonRestoreInstanceState()コールバックメソッドは、インスタンス状態情報を含む同じBundleを受け取ります。

システムがアクティビティの新しいインスタンスを作成しているか、前のアクティビティを再作成しているかにかかわらず、onCreate()メソッドが呼び出されるため、読み込む前に状態バンドルがnullかどうかを確認する必要があります。それがヌルの場合、破壊された以前のものを復元するのではなく、アクティビティーの新しいインスタンスが作成されます。

はたとえば、次のコードスニペットは、あなたがのonCreate()内のいくつかの状態データを復元することができる方法を示しています。

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); // Always call the superclass first 


    // Check whether we're recreating a previously destroyed instance 
    if (savedInstanceState != null) { 
     // Restore value of members from saved state 
     mCurrentScore = savedInstanceState.getInt(STATE_SCORE); 
     mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); 
    } else { 
     // Probably initialize members with default values for a new instance 
    } 
    ... 
} 

代わりのonCreate()時の状態を復元するのあなたはonRestoreInstanceStateを実装することもできます()メソッドは、onStart()メソッドの後に呼び出されます。あなたはバンドルがnullであるかどうかをチェックする必要はありませんので、このシステムは、復元する保存された状態がある場合にのみonRestoreInstanceState()を呼び出します:

public void onRestoreInstanceState(Bundle savedInstanceState) { 
    // Always call the superclass so it can restore the view hierarchy 
    super.onRestoreInstanceState(savedInstanceState); 


    // Restore state members from saved instance 
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE); 
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL); 
} 

注意:必ずonRestoreInstanceStateのスーパークラスの実装を呼び出します( )、デフォルトの実装ではビュー階層の状態を復元できます。

+0

はい、しかし、なぜ画面の向きが変わったときに写真のような「影」があり、なぜ画面の横長のボタンの変更が見えないのですか? もし私が肖像画に戻ってきたら、完璧に動作しますが、それは問題の風景であり、問​​題はInstanceState ....だとは思わないでしょうか? instanceStateでランドスケープで「シャドー」エフェクトを避けることはできません – Dario

+0

オリエンテーションには同じレイアウトがありますか、向きにレイアウトとレイアウトランドフォルダがありますか? – JRG

+0

同じレイアウトでは、私は異なる画面の向きに2つのレイアウトがありません。 画面の向きが変わるとフラグメントを破棄する必要がありますか? 「シャドーイング」効果は2つのフラグメントUIのオーバーラップですか? バックグラウンドのシャドウは、風景のボタンを変更するとシャドウの背景に更新が表示されますが、上に表示されません(説明するのは難しいです:D) – Dario

関連する問題