2015-10-05 9 views
36

IntelliJ haben Änderungen an die Navigationsleiste Vorlage Aktivität in Android Studio mit weniger Codezeilen in der Aktivitätsklasse gemacht. Die neue Aktivitätsklasse sieht wie folgt aus:Umschalten zwischen Fragmenten mit onNavigationItemSelected in neuer Navigationsleiste Aktivitätsvorlage (Android Studio 1.4 an)

public class MainActivity extends AppCompatActivity 
    implements NavigationView.OnNavigationItemSelectedListener { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    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(); 
     } 
    }); 

    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); 
} 

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


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

    if (id == R.id.nav_camara) { 
     // Handle the camera action 
    } else if (id == R.id.nav_gallery) { 

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

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

    } 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; 
} 
} 

Einer der bemerkenswertesten Änderung hier ist die Methode:

onNavigationItemSelected(MenuItem item)

Die alte Navigationsleiste Vorlage Definition dieser Methode war:

onNavigationItemSelected(int position, long itemId)

Sie könnten die alte Vorlage ändern, indem die innereLöschenKlasse, die Erstellung Ihre eigenen Fragmente und Layouts und so etwas wie dies zu tun:

Fragment fragment = null; 
switch (position) { 
    case 0: 
     fragment = new FragmentA(); 
     break; 
    case 1: 
     fragment = new FragmentB(); 
     break; 
    default: 
     break; 
} 

if (fragment != null) { 
    FragmentManager fragmentManager = getSupportFragmentManager(); 
    fragmentManager.beginTransaction() 
      .replace(R.id.frame_container, fragment).commit(); 

} 

Aber das mit der neuen Vorlage nicht funktioniert (zumindest nicht von meinem kleinen Wissen). Ich habe versucht:

public boolean onNavigationItemSelected(MenuItem item) { 
    // Handle navigation view item clicks here. 
    int id = item.getItemId(); 
    Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), item.getTitle() + " clicked", Snackbar.LENGTH_SHORT); 
    Fragment fragment = null; 
    switch (id) { 
     case R.id.nav_home: 
      fragment = HomeFragment.getFragInstance(); 
      break; 

     case R.id.nav_news: 

      fragment = NewsFragment.getFragInstance(); 
      break; 


     default: 
      break; 
    } 

    if (fragment != null) { 
     FragmentTransaction transaction = fragmentManager.beginTransaction(); 
     transaction.addToBackStack(null); 
     transaction.replace(R.id.drawer_layout, fragment); 
     transaction.commit(); 


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

    } 
    return true; 
} 

aber das Layout für das home Layout ist auch in dem news Layout dargestellt. Dies ist wahrscheinlich wegen der Linie passiert:

transaction.replace(R.id.drawer_layout, fragment); 

Fragmente sollen in einem FrameLayout und der alten Navigationsleiste Layout ersetzt werden sah wie folgt aus:

<android.support.v4.widget.DrawerLayout 
xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/drawer_layout" 
android:layout_width="match_parent" 
android:layout_height="match_parent"> 

<!-- Framelayout to display Fragments --> 
<FrameLayout 
    android:id="@+id/frame_container" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" /> 

<!-- Listview to display slider menu --> 


<ListView 
    android:id="@+id/list_sliderMenu" 
    android:layout_width="240dp" 
    android:layout_height="match_parent" 
    android:layout_gravity="start" 
    android:choiceMode="singleChoice" 
    android:divider="@color/white" 
    android:dividerHeight="1dp" 
    android:listSelector="@drawable/list_selector" 
    android:background="@color/list_background"/> 

Aber die neue man sieht wie folgt aus:

<?xml version="1.0" encoding="utf-8"?> 
    <android.support.v4.widget.DrawerLayout  
    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/drawer_layout" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:fitsSystemWindows="true" 
    tools:openDrawer="start"> 

<include 
    layout="@layout/app_bar_base" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" /> 

<android.support.design.widget.NavigationView 
    android:id="@+id/nav_view" 
    android:layout_width="wrap_content" 
    android:layout_height="match_parent" 
    android:layout_gravity="start" 
    android:fitsSystemWindows="true" 
    app:headerLayout="@layout/nav_header_base" 
    app:menu="@menu/activity_base_drawer" /> 

    </android.support.v4.widget.DrawerLayout> 

Lange Rede kurzer Sinn, wie kann man die neue Vorlage ändern zu können, zwischen Fragmenten wechseln?

Antwort

69

:

  • den Code unten verwenden:

    <?xml version="1.0" encoding="utf-8"?> 
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
        xmlns:tools="http://schemas.android.com/tools" 
        xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" 
        android:layout_height="match_parent" 
        app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:showIn="@layout/app_bar_main" 
        tools:context=".MainActivity">  
        <FrameLayout 
         android:layout_width="match_parent" 
         android:layout_height="match_parent" android:id="@+id/mainFrame"> 
        </FrameLayout> 
    </RelativeLayout> 
    
  • zum onNavigationItemSelected Verfahren gehen .

    Zu allererst, fügen Sie Ihre FrameLayout auf Ihre content_main.xml Datei:

    <FrameLayout 
        android:layout_width="match_parent" 
        android:layout_height="match_parent" android:id="@+id/content_frame"/> 
    

    In Ihrem MainActivity (oder was auch immer haben Sie die Aktivität mit der Navigationsleiste genannt) definiert eine Methode namens displayView

    public void displayView(int viewId) { 
    
        Fragment fragment = null; 
        String title = getString(R.string.app_name); 
    
        switch (viewId) { 
         case R.id.nav_news: 
          fragment = new NewsFragment(); 
          title = "News"; 
    
          break; 
         case R.id.nav_events: 
          fragment = new EventsFragment(); 
          title = "Events"; 
          break; 
    
        } 
    
        if (fragment != null) { 
         FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
         ft.replace(R.id.content_frame, fragment); 
         ft.commit(); 
        } 
    
        // set the toolbar title 
        if (getSupportActionBar() != null) { 
         getSupportActionBar().setTitle(title); 
        } 
    
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
        drawer.closeDrawer(GravityCompat.START); 
    
    } 
    

    Wechsel zwischen 3 benutzerdefinierten Fragmenten; NewsFragment, EventsFragment und GalleryFragment.

    in meinem Menü activity_main_drawer Ich habe den Inhalt dieses geändert:

    <menu xmlns:android="http://schemas.android.com/apk/res/android"> 
    
    <group android:checkableBehavior="single"> 
        <item android:id="@+id/nav_news" 
         android:icon="@android:drawable/ic_menu_news" 
         android:title="News" /> 
        <item android:id="@+id/nav_events" 
         android:icon="@android:drawable/ic_menu_events" 
         android:title="Events" /> 
        <item android:id="@+id/nav_gallery" 
         android:icon="@android:drawable/ic_menu_gallery" 
         android:title="Gallery" /> 
        </group> 
    </menu> 
    

    Gehen wir zurück zum Aktivitätsklasse, in Ihrem onNavigationItemSelected Methode dies tun:

    @Override 
    public boolean onNavigationItemSelected(MenuItem item) { 
        displayView(item.getItemId()); 
        return true; 
    } 
    

    Schließlich ist die letzte Aussage in Ihrer onCreate-Methode:

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        .... 
        .... 
        displayView(R.id.nav_news); 
    } 
    

    Dies liegt daran, dass ich die erste Ansicht haben möchte, die mein Benutzer als News sieht. Ändern Sie sie zu dem, was Sie wählen.

    Presse-Event Handle zurück:

    Wie es aussieht, wenn Sie die Zurück-Taste aus einem der Fragmente drücken, werden die App exits.I möchte, dass meine App auf die Nachrichten Fragment (meine Heimat Fragment zurück gehen) wenn der Benutzer die Zurück-Taste drückt. Also tat ich dies:

    eine boolean Variable deklariert:

    private boolean viewIsAtHome; 
    

    dann in der displayView() Methode, die ich tat dies:

    public void displayView(int viewId){ 
        Fragment fragment = null; 
        String title = getString(R.string.app_name); 
    
        switch (viewId) { 
         case R.id.nav_news: 
          fragment = new NewsFragment(); 
          title = getString(R.string.news_title); 
          viewIsAtHome = true; 
    
          break; 
         case R.id.nav_events: 
          fragment = new EventsFragment(); 
          title = getString(R.string.events_title); 
          viewIsAtHome = false; 
          break; 
    
         case R.id.nav_gallery: 
          fragment = new GalleryFragment(); 
          title = getString(R.string.gallery_title); 
          viewIsAtHome = false; 
          break; 
    

    Schließlich alten onBackPressed Methode löschen und eine neue erstellen wie dies außerhalb die onCreate() methode:

    @Override 
    public void onBackPressed() { 
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
        if (drawer.isDrawerOpen(GravityCompat.START)) { 
         drawer.closeDrawer(GravityCompat.START); 
        } 
        if (!viewIsAtHome) { //if the current view is not the News fragment 
         displayView(R.id.nav_news); //display the News fragment 
        } else { 
         moveTaskToBack(true); //If view is in News fragment, exit application 
        } 
    } 
    

    Funktioniert für mich.

  • +1

    gute Arbeit .. sehr sehr hilfreich..danke –

    +1

    Danke Sir. Es hat für mich funktioniert. – Roon13

    +1

    Sehr einfach und klar! Vielen Dank ! – Nekfeu

    0

    nicht sicher, ob ich in der Lage sein zu helfen, aber wenn Sie die Layout-Vorlagen für NavigationDrawerActivity ändern möchten, können Sie es in <Path\to\Program_Files>\Android\Android Studio\plugins\android\lib\templates\activities\NavigationDrawerActivity\root\res\layout

    Ich glaube zu finden, wird es am besten sein, ein ähnliches Layout wie haben auf die folgende -

    <!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. --> 
    <android.support.v4.widget.DrawerLayout 
        xmlns:android="http://schemas.android.com/apk/res/android" 
        xmlns:tools="http://schemas.android.com/tools" 
        android:id="@+id/drawer_layout" 
        android:layout_width="match_parent" 
        android:layout_height="match_parent" 
        tools:context="${relativePackage}.${activityClass}"> 
    
        <!-- As the main content view, the view below consumes the entire 
         space available using match_parent in both dimensions. --> 
        <FrameLayout 
         android:id="@+id/container" 
         android:layout_width="match_parent" 
         android:layout_height="match_parent" /> 
    
        <!-- android:layout_gravity="start" tells DrawerLayout to treat 
         this as a sliding drawer on the left side for left-to-right 
         languages and on the right side for right-to-left languages. 
         If you're not building against API 17 or higher, use 
         android:layout_gravity="left" instead. --> 
        <!-- The drawer is given a fixed width in dp and extends the full height of 
         the container. --> 
        <NavigationView android:id="@+id/navigation_drawer" 
         android:layout_width="@dimen/navigation_drawer_width" 
         android:layout_height="match_parent" 
         android:layout_gravity="<#if buildApi gte 17>start<#else>left</#if>" /> 
    
    </android.support.v4.widget.DrawerLayout> 
    

    Und diese mit der Art und Weise arbeiten Sie die Fragment s in R.id.container früher wurden ersetzt.

    +0

    Es ist nicht das Layout ich change.I wollen möge meine eigenen Fragmente hinzufügen und sie aus der Navigationsleiste navigieren. –

    0

    benutzte ich eine Vorlage automatisch erstellt von Android Studio zu 1.4, und ich hatte wie Sie gleichen Schwierigkeiten stoßen.

    Erstens verändert I activity_main.xml

    <?xml version="1.0" encoding="utf-8"?> 
    <android.support.v4.widget.DrawerLayout 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/drawer_layout" 
    android:layout_width="match_parent" android:layout_height="match_parent" 
    android:fitsSystemWindows="true" tools:openDrawer="start"> 
    
    <!--Main--> 
    <LinearLayout 
        android:layout_width="match_parent" 
        android:layout_height="match_parent" 
        android:orientation="vertical"> 
        <!-- The ActionBar --> 
        <include 
         layout="@layout/toolbar" 
         android:layout_width="match_parent" 
         android:layout_height="wrap_content" /> 
        <FrameLayout 
         android:id="@+id/content" 
         android:layout_width="match_parent" 
         android:layout_height="match_parent"> 
        </FrameLayout> 
    </LinearLayout> 
    
    <!--Drawer--> 
    <android.support.design.widget.NavigationView 
        android:id="@+id/nav_view" 
        android:layout_width="wrap_content" 
        android:layout_height="match_parent" 
        android:layout_gravity="start" 
        android:fitsSystemWindows="true" 
        app:headerLayout="@layout/nav_header" 
        app:menu="@menu/drawer" /></android.support.v4.widget.DrawerLayout> 
    

    A DrawerLayout, die zwei Teile enthält:

    1. Hauptbildschirm (LinearLayout)
    2. der Schublade (NavigationView)

    Hauptbildschirm enthält Die ActionBar und das FrameLayout (R.id.content) werden durch ein Fragment ersetzt. Die Schublade enthält die Kopfzeile und das Menü.

    Also überschreiben wir jetzt onNavigationItemSelected und ersetzen R.id.content durch ein Fragment.

    Hier ist mein MainActivity Code:

    @Override 
    public boolean onNavigationItemSelected(MenuItem item) { 
        Fragment fragment; 
        FragmentTransaction ft = getFragmentManager().beginTransaction(); 
        // Handle navigation view item clicks here. 
        int id = item.getItemId(); 
    
        if (id == R.id.nav_A) { 
         fragment = new AFragment(); 
         ft.replace(R.id.content, fragment).commit();   
        } else if (id == R.id.nav_B){ 
         fragment = new BFragment(); 
         ft.replace(R.id.content, fragment).commit(); 
        } else if (id == R.id.nav_settings) { 
         Intent intent = new Intent(MainActivity.this, SettingsActivity.class); 
         startActivity(intent); 
        } 
    
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 
        drawer.closeDrawer(GravityCompat.START); 
        return true; 
    } 
    

    Startseite ist auch ein Fragment. Und ich habe die Hauptseite in onCreate Methode eingerichtet, obwohl ich nicht sicher bin, ob es eine bessere Möglichkeit zum Einrichten der Hauptseite gibt.

    //MainPageFragment 
        FragmentTransaction ft = getFragmentManager().beginTransaction(); 
        ft.replace(R.id.content, new MainPageFragment()).commit(); 
    

    PS. hier ist die toolbar.xml, die ActionBar

    <?xml version="1.0" encoding="utf-8"?> 
    <android.support.design.widget.CoordinatorLayout 
    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:layout_width="match_parent" 
    android:layout_height="match_parent" android:fitsSystemWindows="true" 
    tools:context="jean.yang.MainActivity"> 
    <android.support.design.widget.AppBarLayout android:layout_height="wrap_content" 
        android:layout_width="match_parent" android:theme="@style/AppTheme.AppBarOverlay"> 
        <android.support.v7.widget.Toolbar android:id="@+id/toolbar" 
         android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" 
         android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> 
    </android.support.design.widget.AppBarLayout> 
    </android.support.design.widget.CoordinatorLayout> 
    
    10

    Sie sollten nicht die DrawerLayout ändern, müssen Sie nur einen Rahmen, in dem „content_main.xml“ hinzuzufügen.

    Gehen Sie folgendermaßen vor:

    1. öffnen Sie die "content_main.xml" Datei im "Layout" Ordner. So, bezogen auf die Antwort von @ LL ich in der Lage war, dieses Problem zu lösen

      public boolean onNavigationItemSelected(MenuItem item) { 
          int id = item.getItemId(); 
          Fragment fragment; 
      
      if (id == R.id.nav_camara) { 
          fragment = new YourFragment(); 
          FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
          ft.replace(R.id.mainFrame, fragment); 
          ft.commit(); 
      } 
      else if (id == R.id.nav_gallery) { 
      
      } 
      else if (id == R.id.nav_slideshow) { 
      
      } 
      else if (id == R.id.nav_manage) { 
      
      } 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; 
      } 
      
    +1

    Thanks.Placing das FrameLayout in content_main war die wichtigste Änderung, die ich brauchte. –

    3

    einen anderen Weg:

    public boolean onNavigationItemSelected(MenuItem item) { 
        // Handle navigation view item clicks here. 
        Fragment fragment; 
        int id = item.getItemId(); 
    
        if (id == R.id.nav_camera) { 
         // Handle the camera action 
         fragment = new BlankFragment(); 
         FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
         ft.replace(R.id.container_new, fragment); 
         ft.commit(); 
        } else if (id == R.id.nav_gallery) { 
         fragment = new HorizontalView(); 
         FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
         ft.replace(R.id.container_new,fragment); 
         ft.commit(); 
        } else if (id == R.id.nav_slideshow) { 
         fragment = new FragmentVerticleView(); 
         FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
         ft.replace(R.id.container_new,fragment); 
         ft.commit(); 
    
        } else if (id == R.id.nav_manage) { 
    
        } 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; 
    } 
    

    Und dann werden Sie alle Fragmente auf Ihre Aktivität implemts müssen. In meinem Fall ist es

    MainActivity.java

    public class MainActivity extends AppCompatActivity 
        implements BlankFragment.OnFragmentInteractionListener, HorizontalView.OnFragmentInteractionListener,FragmentVerticleView.OnFragmentInteractionListener,OnNavigationItemSelectedListener 
        { 
        //coding stuff 
        } 
    

    Und die Ausnahme zu behandeln, die

    in Fragment Java-Datei Geworfen wird
    "must implement OnFragmentInteractionListener" 
    

    Sie einfach unten Methode

     public void onFragmentInteraction(Uri uri){ 
        //We can keep this empty 
    } 
    

    hinzufügen Und da gehst du! Alle setzten

    Thanks to this Tutorial to strike this