Ta sama szuflada nawigacji w różnych działaniach


206

Zrobiłem działającą szufladę nawigacji, tak jak pokazano w samouczku na stronie developer.android.com . Ale teraz chcę użyć jednej szuflady nawigacji, którą utworzyłem w pliku NavigationDrawer.class dla wielu działań w mojej aplikacji.

Moje pytanie brzmi: czy ktokolwiek tutaj może zrobić mały samouczek, który wyjaśnia, jak używać jednej szuflady nawigacji do wielu działań.

Przeczytałem go najpierw w tej szufladzie nawigacji Android w odpowiedzi na wiele działań

ale to nie zadziałało w moim Projekcie

public class NavigationDrawer extends Activity {
public DrawerLayout drawerLayout;
public ListView drawerList;
private ActionBarDrawerToggle drawerToggle;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawerToggle = new ActionBarDrawerToggle((Activity) this, drawerLayout, R.drawable.ic_drawer, 0, 0) {

        public void onDrawerClosed(View view) {
            getActionBar().setTitle(R.string.app_name);
        }

        public void onDrawerOpened(View drawerView) {
            getActionBar().setTitle(R.string.menu);
        }
    };
    drawerLayout.setDrawerListener(drawerToggle);

    getActionBar().setDisplayHomeAsUpEnabled(true);
    getActionBar().setHomeButtonEnabled(true);

    layers = getResources().getStringArray(R.array.layers_array);
    drawerList = (ListView) findViewById(R.id.left_drawer);
    View header = getLayoutInflater().inflate(R.layout.drawer_list_header, null);
    drawerList.addHeaderView(header, null, false);
    drawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, android.R.id.text1,
            layers));
    View footerView = ((LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
            R.layout.drawer_list_footer, null, false);
    drawerList.addFooterView(footerView);

    drawerList.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
            map.drawerClickEvent(pos);
        }
    });
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    if (drawerToggle.onOptionsItemSelected(item)) {
        return true;
    }
    return super.onOptionsItemSelected(item);

}

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    drawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    drawerToggle.onConfigurationChanged(newConfig);
}
}

W tym działaniu chcę mieć szufladę nawigacji, dlatego rozszerzam „NavigationDrawer”, aw niektórych innych działaniach chcę użyć tej samej szuflady nawigacji

  public class SampleActivity extends NavigationDrawer {...}

Nie wiem co zmienić ...


1
Przykłady możesz znaleźć tutaj .
Naddy

Odpowiedzi:


188

Jeśli chcesz szuflady nawigacji, powinieneś użyć fragmentów. W zeszłym tygodniu wykonałem ten samouczek i działa świetnie:

http://developer.android.com/training/implementing-navigation/nav-drawer.html

Możesz również pobrać przykładowy kod z tego samouczka, aby zobaczyć, jak to zrobić.


Bez fragmentów:

To jest Twój kod BaseActivity:

public class BaseActivity extends Activity
{
    public DrawerLayout drawerLayout;
    public ListView drawerList;
    public String[] layers;
    private ActionBarDrawerToggle drawerToggle;
    private Map map;

    protected void onCreate(Bundle savedInstanceState)
    {
        // R.id.drawer_layout should be in every activity with exactly the same id.
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

        drawerToggle = new ActionBarDrawerToggle((Activity) this, drawerLayout, R.drawable.ic_drawer, 0, 0) 
        {
            public void onDrawerClosed(View view) 
            {
                getActionBar().setTitle(R.string.app_name);
            }

            public void onDrawerOpened(View drawerView) 
            {
                getActionBar().setTitle(R.string.menu);
            }
        };
        drawerLayout.setDrawerListener(drawerToggle);

        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);

        layers = getResources().getStringArray(R.array.layers_array);
        drawerList = (ListView) findViewById(R.id.left_drawer);
        View header = getLayoutInflater().inflate(R.layout.drawer_list_header, null);
        drawerList.addHeaderView(header, null, false);
        drawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, android.R.id.text1,
                layers));
        View footerView = ((LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
                R.layout.drawer_list_footer, null, false);
        drawerList.addFooterView(footerView);

        drawerList.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
                map.drawerClickEvent(pos);
            }
        });
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        if (drawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        return super.onOptionsItemSelected(item);

    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        drawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        drawerToggle.onConfigurationChanged(newConfig);
    }
}

Wszystkie pozostałe działania, które muszą mieć szufladę nawigacji, powinny rozszerzyć to działanie zamiast samego działania, na przykład:

public class AnyActivity extends BaseActivity
{
    //Because this activity extends BaseActivity it automatically has the navigation drawer
    //You can just write your normal Activity code and you don't need to add anything for the navigation drawer
}

XML

<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">
    <!-- The main content view -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <!-- Put what you want as your normal screen in here, you can also choose for a linear layout or any other layout, whatever you prefer -->
    </FrameLayout>
    <!-- The navigation drawer -->
    <ListView android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#111"/>
</android.support.v4.widget.DrawerLayout>

Edytować:

Sam napotkałem pewne trudności, więc oto rozwiązanie, jeśli otrzymasz wyjątki NullPointerExceptions. W BaseActivity zmień funkcję onCreate na protected void onCreateDrawer(). Reszta może pozostać taka sama. W działaniach rozszerzających BaseActivity ustaw kod w następującej kolejności:

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity);
    super.onCreateDrawer();

Pomogło mi to rozwiązać problem, mam nadzieję, że to pomoże!

W ten sposób możesz utworzyć szufladę nawigacji z wieloma czynnościami, jeśli masz jakieś pytania, możesz je zadać.


Edycja 2:

Jak powiedział @GregDan, BaseActivitymożesz również zastąpić setContentView()i wywołać tamCreateDrawer:

@Override 
public void setContentView(@LayoutRes int layoutResID) 
{ 
    super.setContentView(layoutResID); 
    onCreateDrawer() ;
}

7
Nie chcę używać działań nad fragmentami, chcę po prostu używać różnych działań, które korzystają z tej samej szuflady nawigacji. Chcę aktywności, ponieważ tam mogę używać różnych rodzajów układu, takich jak widok machnięcia, widok mapy ...
MEX

135
Posiadanie tylko jednego działania może być zniechęcającym zadaniem dla każdej dość złożonej aplikacji. Korzystanie z działań daje wiele darmowych rzeczy z systemu - więc jest to ważny punkt, w jaki sposób korzystać z wielu działań. Nie mogę sobie wyobrazić jednej komunikacji obsługującej działanie między dowolną liczbą kombinacji fragmentów - to po prostu nie zadziała.
slott,

1
Przepraszam, że tyle czasu zajęło mi udzielenie odpowiedzi. Zredagowałem swoją odpowiedź. Myślę, że to samouczek, którego szukałeś. Mam nadzieję że to pomoże.
Kevin van Mierlo

2
@KevinvanMierlo czy możesz mi powiedzieć, co masz na myśli przez: R.id.drawer_layout powinien być w każdej aktywności z dokładnie tym samym identyfikatorem. Ponieważ zrobiłem dokładnie to, co tu powiedziałeś, i otrzymuję wyjątek NullPointerException w metodzie onCreate () działania, które rozszerza tę BaseActivity ..
Loolooii

1
@ KevinvanMierlo btw, myślę, że zapomniałeś tych 2 linii? super.onCreate (saveInstanceState); setContentView (R.layout.activity_base);
Loolooii

34

Znalazłem najlepszą implementację. Jest w aplikacji Google I / O 2014 .

Używają tego samego podejścia co Kevin. Jeśli potrafisz oderwać się od wszystkich niepotrzebnych rzeczy w aplikacji we / wy, możesz wyodrębnić wszystko, czego potrzebujesz, a Google zapewnia, że ​​jest to prawidłowe użycie wzoru szuflady nawigacji. Każde działanie opcjonalnie ma DrawerLayoutswój główny układ. Interesującą częścią jest sposób nawigacji do innych ekranów. Jest zaimplementowany w BaseActivitynastępujący sposób:

private void goToNavDrawerItem(int item) {
        Intent intent;
        switch (item) {
            case NAVDRAWER_ITEM_MY_SCHEDULE:
                intent = new Intent(this, MyScheduleActivity.class);
                startActivity(intent);
                finish();
                break;

Różni się to od powszechnego sposobu zastępowania bieżącego fragmentu transakcją fragmentu. Ale użytkownik nie dostrzega różnicy wizualnej.


To… Nie mogę zrozumieć, w jaki sposób rozpoczynają nowe działania i działa bezbłędnie. Jest to duża aplikacja do pracy.
hitch.united

@ hitch.united To dlatego, że używają wielu fragmentów i tylko kilku działań.
Joaquin Iurchuk

@ hitch.united prawdopodobnie zastępują animację działania za pomocą overridePendingTransitions.
EpicPandaForce

jest ładowanie fragmentów zamiast działań podklas?
Vikas Pandey,

Oto plik z października 2014 r .: github.com/google/iosched/blob/…
denvercoder9

8

Tak więc odpowiedź jest spóźniona o kilka lat, ale ktoś może ją docenić. Android dał nam nowy widget, który ułatwia korzystanie z jednej szuflady nawigacji z kilkoma czynnościami.

android.support.design.widget.NavigationView jest modułowy i ma własny układ w folderze menu. Sposób, w jaki go używasz, polega na zawijaniu układów XML w następujący sposób:

  1. Układ główny to android.support.v4.widget.DrawerLayout, który zawiera dwoje dzieci: <include ... />dla układu, który jest zawijany (patrz 2) i android.support.design.widget.NavigationView.

    <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_main"
        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_main"
        app:menu="@menu/activity_main_drawer" />

nav_header_main jest po prostu LinearLayout z orientacją = pionową dla nagłówka Drawar nawigacji.

Activity_main_drawer to menu xml w twoim katalogu res / menu. Może zawierać elementy i grupy do wyboru. Jeśli korzystasz z Galerii AndroidStudio, kreator stworzy dla ciebie podstawową i będziesz mógł zobaczyć, jakie masz opcje.

  1. Układ paska aplikacji jest zwykle teraz android.support.design.widget.CoordinatorLayout i będzie obejmował dwoje dzieci: android.support.design.widget.AppBarLayout (który zawiera android.support.v7.widget.Toolbar) i <include ... >dla twoja rzeczywista treść (patrz 3).

    <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"
        tools:context="yourpackage.MainActivity">
    
     <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        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>
    
    <include layout="@layout/content_main" />

  2. Układ treści może być dowolnym układem. Jest to układ zawierający główną treść działania (bez szuflady nawigacji lub paska aplikacji).

Fajną rzeczą w tym wszystkim jest to, że możesz zawijać każdą aktywność w tych dwóch układach, ale nawigacja NavigationView (patrz krok 1) zawsze wskazuje na kreator_ aktywności (lub cokolwiek innego). Oznacza to, że będziesz mieć tę samą (*) szufladę nawigacji dla wszystkich działań.

  • Nie będą to te same wystąpienia NavigationView, ale, szczerze mówiąc, nie było to możliwe nawet przy opisanym powyżej rozwiązaniu BaseActivity.

stackoverflow odcina część otaczających nawiasów xml, ale wszystko jest w porządku.
jwehrle

ale jak traktujesz funkcjonalność jak przyciski? musisz napisać ten sam kod w każdej czynności?
Laur89

Tak, ponieważ są to osobne wystąpienia. Możesz jednak stworzyć superklasę dla swoich działań, aby rozszerzyć i umieścić tam jeden kod.
jwehrle

@jwehrle, czy możesz napisać przykład na temat tworzenia superklasy dla naszych działań?
CDrosos

publiczna klasa abstrakcyjna MyBaseActivity rozszerza AppCompatActivity implementuje NavigationView.OnNavigationItemSelectedListener {// implementuje następujące: Zastąpienie wartości logicznej onNavigationItemSelected (element @NonNull MenuItem) {}} klasa publiczna MyActivity rozszerza MyBaseActivity {}
jwehrle

7

Najłatwiejszy sposób ponownego wykorzystania wspólnej szuflady nawigacji wśród grupy działań

app_base_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

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

    </FrameLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/menu_test"
        />
</android.support.v4.widget.DrawerLayout>

AppBaseActivity.java

/*
* This is a simple and easy approach to reuse the same 
* navigation drawer on your other activities. Just create
* a base layout that conains a DrawerLayout, the 
* navigation drawer and a FrameLayout to hold your
* content view. All you have to do is to extend your 
* activities from this class to set that navigation 
* drawer. Happy hacking :)
* P.S: You don't need to declare this Activity in the 
* AndroidManifest.xml. This is just a base class.
*/
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

public abstract class AppBaseActivity extends AppCompatActivity implements MenuItem.OnMenuItemClickListener {
    private FrameLayout view_stub; //This is the framelayout to keep your content view
    private NavigationView navigation_view; // The new navigation view from Android Design Library. Can inflate menu resources. Easy
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mDrawerToggle;
    private Menu drawerMenu;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.app_base_layout);// The base layout that contains your navigation drawer.
        view_stub = (FrameLayout) findViewById(R.id.view_stub);
        navigation_view = (NavigationView) findViewById(R.id.navigation_view);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, 0, 0);
        mDrawerLayout.setDrawerListener(mDrawerToggle);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        drawerMenu = navigation_view.getMenu();
        for(int i = 0; i < drawerMenu.size(); i++) {
          drawerMenu.getItem(i).setOnMenuItemClickListener(this);
        }
        // and so on...
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

    /* Override all setContentView methods to put the content view to the FrameLayout view_stub
     * so that, we can make other activity implementations looks like normal activity subclasses.
     */
    @Override
    public void setContentView(int layoutResID) {
        if (view_stub != null) {
            LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
            ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);
            View stubView = inflater.inflate(layoutResID, view_stub, false);
            view_stub.addView(stubView, lp);
        }
    }

    @Override
    public void setContentView(View view) {
        if (view_stub != null) {
            ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);
            view_stub.addView(view, lp);
        }
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        if (view_stub != null) {
            view_stub.addView(view, params);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Pass the event to ActionBarDrawerToggle, if it returns
        // true, then it has handled the app icon touch event
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        // Handle your other action bar items...

        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.item1:
                // handle it
                break;
            case R.id.item2:
                // do whatever
                break;
            // and so on...
        }
        return false;
    }
}

Czy możesz podać przykład działania wykorzystującego to działanie podstawowe?
CDrosos

Nie pamiętam żadnych szczegółów na ten temat, myślę, że po prostu rozszerzenie AppBaseActivity i setContentViewdomyślny sposób powinny działać.
Levon Petrosyan

6

Dla każdego, kto chce zrobić to, o co prosi oryginalny plakat, rozważ użycie fragmentów zamiast tego, jak powiedział Kevin. Oto doskonały samouczek, jak to zrobić:

https://github.com/codepath/android_guides/wiki/Fragment-Navigation-Drawer

Jeśli zdecydujesz się zamiast tego używać działań zamiast fragmentów, napotkasz problem ponownego tworzenia szuflady nawigacji za każdym razem, gdy przejdziesz do nowej aktywności. Powoduje to brzydkie / wolne renderowanie szuflady nawigacji za każdym razem.


5

Moja sugestia jest taka: nie używaj w ogóle działań, zamiast tego używaj fragmentów i umieszczaj je w pojemniku (na przykład Układ liniowy), w którym wyświetlasz swój pierwszy fragment.

Kod jest dostępny w samouczkach dla programistów Androida, wystarczy dostosować.

http://developer.android.com/training/implementing-navigation/nav-drawer.html

Wskazane jest, abyś używał coraz większej liczby fragmentów w swojej aplikacji i powinny istnieć tylko cztery podstawowe działania lokalne dla Twojej aplikacji, o których wspominasz w pliku AndroidManifest.xml oprócz zewnętrznych (na przykład FacebookActivity):

  1. SplashActivity: nie używa fragmentu i używa motywu FullScreen.

  2. LoginSignUpActivity: W ogóle nie wymaga NavigationDrawer i żadnego przycisku Wstecz, więc po prostu użyj zwykłego paska narzędzi, ale wymagane będą co najmniej 3 lub 4 fragmenty. Używa motywu bez paska akcji

  3. Aktywność HomeActivity lub DashBoard: używa motywu bez paska akcji. Tutaj potrzebujesz szuflady nawigacji, a wszystkie kolejne ekrany będą fragmentami lub fragmentami zagnieżdżonymi, aż do widoku liścia, ze wspólną szufladą. Wszystkie ustawienia, profil użytkownika itp. Będą tutaj jako fragmenty tego działania. Fragmenty tutaj nie zostaną dodane do tylnego stosu i zostaną otwarte z pozycji menu szuflady. W przypadku fragmentów, które wymagają szuflady zamiast szuflady, poniżej znajduje się czwarty rodzaj aktywności.

  4. Aktywność bez szuflady. Ta aktywność ma przycisk Wstecz u góry, a fragmenty w środku będą miały ten sam pasek akcji. Te fragmenty zostaną dodane do stosu, ponieważ pojawi się historia nawigacji.

[Dalsze wskazówki patrz: https://stackoverflow.com/a/51100507/787399 ]

Happy Coding !!


To jest starszy post. Możesz użyć fragmentów, aby mieć zawsze jedną aktywność. Ciągle zastępujesz fragmenty w jednym przeznaczonym do tego pojemniku. Umieść tylny stos, gdy potrzebujesz nawigacji do tyłu, lub pop wszystkie fragmenty, gdy potrzebujesz fragmentu, który zostanie pokazany jako pierwszy.
Abhinav Saxena

@ Cabuxa.Mapache Proszę sprawdzić załączony link do mojej odpowiedzi, aby uzyskać dalszą pomoc. Wziąłem wspólną BaseActivity, która pomaga udostępniać ActionBar ToolBar i NavigatonDrawer oraz inne komponenty we wszystkich dołączonych do niego fragmentach.
Abhinav Saxena

1

zaktualizuj ten kod w baseactivity. i nie zapomnij dołączyć drawer_list_header do swojej aktywności xml.

super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
setContentView(R.layout.drawer_list_header);

i nie używaj request () w swojej działalności. ale szuflada nadal nie jest widoczna po kliknięciu obrazu .. i przeciągnięcie jej spowoduje wyświetlenie bez elementów listy. Próbowałem dużo, ale bez powodzenia. potrzebuję ćwiczeń do tego ...


1

Dzięki odpowiedzi @Kevin van Mierlo możesz także wdrożyć kilka szuflad. Na przykład domyślne menu znajdujące się po lewej stronie (start) i kolejne opcjonalne menu, znajdujące się po prawej stronie, które jest wyświetlane tylko po załadowaniu określonych fragmentów.

Byłem w stanie to zrobić.


1
package xxxxxx;



import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.widget.SearchView;
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;


public class loginhome extends AppCompatActivity {
    private Toolbar toolbar;
    private NavigationView navigationView;
    private DrawerLayout drawerLayout;

    // Make sure to be using android.support.v7.app.ActionBarDrawerToggle version.
    // The android.support.v4.app.ActionBarDrawerToggle has been deprecated.
    private ActionBarDrawerToggle drawerToggle;

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

        // Initializing Toolbar and setting it as the actionbar
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);


        //Initializing NavigationView


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

        //Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {

            // This method will trigger on item Click of navigation menu

            public boolean onNavigationItemSelected(MenuItem menuItem) {


                //Checking if the item is in checked state or not, if not make it in checked state
                if(menuItem.isChecked()) menuItem.setChecked(false);
                else menuItem.setChecked(true);

                //Closing drawer on item click
                drawerLayout.closeDrawers();

                //Check to see which item was being clicked and perform appropriate action
                switch (menuItem.getItemId()){


                    //Replacing the main content with ContentFragment Which is our Inbox View;
                    case R.id.nav_first_fragment:
                        Toast.makeText(getApplicationContext(),"First fragment",Toast.LENGTH_SHORT).show();
                         FirstFragment fragment = new FirstFragment();
                        android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
                        fragmentTransaction.replace(R.id.frame,fragment);
                        fragmentTransaction.commit();
                        return true;

                    // For rest of the options we just show a toast on click
                    case R.id.nav_second_fragment:
                        Toast.makeText(getApplicationContext(),"Second fragment",Toast.LENGTH_SHORT).show();
                        SecondFragment fragment2 = new SecondFragment();
                        android.support.v4.app.FragmentTransaction fragmentTransaction2 = getSupportFragmentManager().beginTransaction();
                        fragmentTransaction2.replace(R.id.frame,fragment2);
                        fragmentTransaction2.commit();
                        return true;

                    default:
                        Toast.makeText(getApplicationContext(),"Somethings Wrong",Toast.LENGTH_SHORT).show();
                        return true;

                }
            }
        });

        // Initializing Drawer Layout and ActionBarToggle
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.drawer_open, R.string.drawer_close){

            @Override
            public void onDrawerClosed(View drawerView) {
                // Code here will be triggered once the drawer closes as we dont want anything to happen so we leave this blank
                super.onDrawerClosed(drawerView);
            }

            @Override
            public void onDrawerOpened(View drawerView) {
                // Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank

                super.onDrawerOpened(drawerView);
            }
        };

        //Setting the actionbarToggle to drawer layout
        drawerLayout.setDrawerListener(actionBarDrawerToggle);

        //calling sync state is necessay or else your hamburger icon wont show up
        actionBarDrawerToggle.syncState();







    }

użyj tego do pliku toolbar.xml

<?xml version="1.0" encoding="utf-8"?>

    <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:elevation="4dp"
        android:id="@+id/toolbar"
        android:theme="@style/ThemeOverlay.AppCompat.Dark"


        >

    </android.support.v7.widget.Toolbar>

użyj tego do nagłówka nawigacji, jeśli chcesz użyć

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="192dp"
    android:background="?attr/colorPrimaryDark"
    android:padding="16dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark"
    android:orientation="vertical"
    android:gravity="bottom">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:id="@+id/navhead"
        android:orientation="vertical"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true">

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            android:textColor="#ffffff"
            android:text="tanya"
            android:textSize="14sp"
            android:textStyle="bold"

            />

        <TextView
            android:id="@+id/email"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ffffff"
            android:layout_marginLeft="16dp"
            android:layout_marginTop="5dp"
            android:text="tanya.com"
            android:textSize="14sp"
            android:textStyle="normal"

            />
    </LinearLayout>
    <de.hdodenhof.circleimageview.CircleImageView
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_below="@+id/imageView"
        android:layout_marginTop="15dp"

        android:src="@drawable/face"
        android:id="@+id/circleView"
        />



</RelativeLayout>

1

Robię to w Kotlinie w ten sposób:

open class BaseAppCompatActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {

protected lateinit var drawerLayout: DrawerLayout
protected lateinit var navigationView: NavigationView
@Inject
lateinit var loginService: LoginService

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    Log.d("BaseAppCompatActivity", "onCreate()")
    App.getComponent().inject(this)
    drawerLayout = findViewById(R.id.drawer_layout) as DrawerLayout

    val toolbar = findViewById(R.id.toolbar) as Toolbar
    setSupportActionBar(toolbar)

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

    val toggle = ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)

    drawerLayout.addDrawerListener(toggle)
    toggle.syncState()
    toggle.isDrawerIndicatorEnabled = true

    val navigationViewHeaderView = navigationView.getHeaderView(0)
    navigationViewHeaderView.login_txt.text = SharedKey.username
}
private inline fun <reified T: Activity> launch():Boolean{
    if(this is T) return closeDrawer()
    val intent = Intent(applicationContext, T::class.java)
    startActivity(intent)
    finish()
    return true
}

private fun closeDrawer(): Boolean {
    drawerLayout.closeDrawer(GravityCompat.START)
    return true
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
    val id = item.itemId

    when (id) {
        R.id.action_tasks -> {
            return launch<TasksActivity>()
        }
        R.id.action_contacts -> {
            return launch<ContactActivity>()
        }
        R.id.action_logout -> {
            createExitDialog(loginService, this)
        }
    }
    return false
}
}

Działania dla szuflady muszą to dziedziczyć BaseAppCompatActivity, wywoływać super.onCreatepo ustawieniu zawartości (w rzeczywistości można ją przenieść na jakąś metodę init) i mieć w swoim układzie odpowiednie elementy dla identyfikatorów


Chciałem wypróbować twoje rozwiązanie, ale pojawia się błąd: „Ta aktywność ma już pasek akcji dostarczony przez dekorację okna”. Chcę przełączać się między 3 czynnościami, a każdy ma swój własny pasek aplikacji. Czy uważasz, że to możliwe?
David

Myślę, że w takim przypadku musisz przenieść pasek działania do fragmentów. W naszej aplikacji korzystaliśmy z motywu NoActionBar i zapewnialiśmy pasek narzędzi dla zgodności, o ile pamiętam.
Pavlus,

@Pavlus, jak wyglądałby kod przy drugim działaniu? klasa trackActivity: BaseAppCompatActivity () {?
Craig P

0

Moja odpowiedź jest tylko konceptualna bez żadnego kodu źródłowego. To może być przydatne dla niektórych czytelników, takich jak ja, aby zrozumieć.

Zależy to od Twojego początkowego podejścia do architektury aplikacji. Istnieją w zasadzie dwa podejścia.

  1. Tworzysz jedno działanie (działanie podstawowe), a wszystkie pozostałe widoki i ekrany będą fragmentami. Ta podstawowa aktywność zawiera implementację układów szuflady i koordynatora. Jest to właściwie mój preferowany sposób, ponieważ posiadanie małych samodzielnych fragmentów ułatwi i przyspieszy tworzenie aplikacji.

  2. Jeśli tworzenie aplikacji rozpoczęło się od działań, po jednym dla każdego ekranu, prawdopodobnie utworzysz działanie podstawowe, a wszystkie inne działania będą się na nim opierać. Działanie podstawowe będzie zawierało kod do wdrożenia szuflady i koordynatora. Każde działanie wymagające implementacji szuflady może wykraczać poza działanie podstawowe.

Osobiście wolałbym unikać używania fragmentów i działań mieszanych bez organizowania się. To utrudnia rozwój i w końcu utkniesz. Jeśli to zrobiłeś, popraw kod ponownie.


-1

Utwórz szufladę nawigacji w MainActivity za pomocą fragmentu.
Zainicjuj Szufladę nawigacji w MainActivity
teraz we wszystkich innych działaniach, których chcesz używać z tą samą Szufladą nawigacji, ustaw DrawerLayout jako podstawę, a fragment jako szufladę nawigacji. Wystarczy ustawić android: nazwa we fragmencie, wskazując na fragment pliku Java. Nie będziesz musiał inicjować fragmentu w innych działaniach.
Możesz uzyskać dostęp do Nav Drawer, przesuwając palcem w innych czynnościach, np. W aplikacji Sklep Google Play

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.