2016-10-05 102 views
-1

我想定義一個可在整個應用程序中使用的導航抽屜。我遵循所選答案的指示,作爲我的第一種方法:Same Navigation Drawer in different Activities如何在多個活動中使用導航抽屜

我做了一些修改,即從覆蓋的onCreate中調用onCreateDrawer。我更新了我的後續活動,以擴展DashboardActivity(示例中的「基本活動」)。當我啓動我的第二個活動時,我得到一個空指針異常,抱怨當onCreateDrawer嘗試設置在抽屜上偵聽的切換時,導航用戶界面不存在。

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.widget.DrawerLayout.setDrawerListener(android.support.v4.widget.DrawerLayout$DrawerListener)' on a null object reference

這裏是基地(儀表盤)和隨後的(記錄鍛鍊)活動 - 請詢問是否有你想看到其他代碼。在Android Studio中創建新的Nav Drawer Activity時,抽屜的UI和相關活動的代碼是開箱即用的。

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

     onCreateDrawer(); 

     Realm realm = Realm.getDefaultInstance(); 

     RealmQuery<Exercise> query = realm.where(Exercise.class); 
     RealmResults<Exercise> result = query.findAll(); 
     Log.d(TAG, "There are " + result.size() + " exercises ready for use."); 

     FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 
     fab.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       Intent logWorkoutIntent = new Intent(getApplicationContext(), LogWorkoutActivity.class); 
       startActivity(logWorkoutIntent); 
      } 
     }); 

     //TODO: Remove this sign out button 
     Button signOutButton = (Button) findViewById(R.id.button_sign_out); 
     signOutButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       FirebaseAuth.getInstance().signOut(); 
       Intent intent = new Intent(getApplicationContext(), LoginActivity.class); 
       startActivity(intent); 
       Toast.makeText(getApplicationContext(), "Signed out", Toast.LENGTH_LONG).show(); 
      } 
     }); 

     //TODO: Remove this data tester 
     updateUserName(); 
    } 

    //@Override 
    protected void onCreateDrawer() { 
     Log.d(TAG, "onCreateDrawer called"); 
     //super.onCreate(savedInstanceState); 

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

     mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); 

     ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
       this, mDrawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); 
     mDrawerLayout.setDrawerListener(toggle); 
     toggle.syncState(); 

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

... 

-

LogWorkoutActivity.java 
public class LogWorkoutActivity extends DashboardActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     //setContentView(R.layout.activity_log_workout); 
     setContentView(R.layout.activity_log_workout); 
     super.onCreateDrawer(); 
     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 

     FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 
     fab.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) 
         .setAction("Action", null).show(); 
      } 
     }); 
     //getSupportActionBar().setDisplayHomeAsUpEnabled(true); 
    } 

} 

回答

0

我認爲你缺少ID爲drawer_layout抽屜在activity_log_workout佈局。

爲了使此方法起作用,您必須在所有應具有抽屜的活動佈局中有一個ID爲drawer_layout的DrawerLayout。

我也注意到你的代碼有一些奇怪的東西。在DashboardActivity的所有活動中,您首先設置setContentView(R.id.activity_dashboard),然後調用onCreateDrawer(),然後再更改內容視圖並創建抽屜。我認爲這是一個非常不理想的方法。

我建議你創建一個BaseDrawerActivity類來封裝抽屜創建和UI綁定邏輯。然後,您只需在需要抽屜的活動中進行擴展。你可以這樣做:

public abstract class BaseDrawerActivity extends AppCompatActivity { 

    // move all your drawer related fields here 

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

     setContentView(getLayoutResId()); 

     // the same method you have right now 
     onCreateDrawer(); 
    } 


    /* 
    * Extending activities use this class to supply the 
    * id of their layout file. This way you can set the view 
    * only once and there is no need to create the drawer twice. 
    */ 
    @LayoutResId 
    public abstract int getLayoutResId(); 

} 
+0

非常感謝您的詳細解答。我想我沒有仔細觀察控制流程。 (我對Android非常陌生,而且這是我第一次將自己的類加以分類)。您能否提供有關爲此實現XML的任何見解?當我考慮將導航抽屜抽象爲自己的類時,我不確定UI如何工作,因爲抽屜需要將實際內容包裝在XML中。 – justinraczak

+0

@justinraczak抽屜的XML應該總是包含在你想要一個NavigationDrawer的每個活動中。所以,如果你回到我的答案,並複製我寫在那裏的XML。這應該是您想要包含NavigationDrawer的每個Activity的基礎。這裏是鏈接:http://stackoverflow.com/a/19451842/2767703 –

+0

@KevinvanMierlo謝謝 - 我卸載了一些我正在玩的,現在試試這個。 – justinraczak