ลิ้นชักการนำทางเดียวกันในกิจกรรมต่าง ๆ


206

ฉันทำลิ้นชักการนำทางที่ใช้งานได้เหมือนที่แสดงในบทช่วยสอนบนเว็บไซต์developer.android.com แต่ตอนนี้ฉันต้องการใช้หนึ่งลิ้นชักนำทางฉันสร้างขึ้นใน NavigationDrawer.class สำหรับหลาย ๆ กิจกรรมในแอปพลิเคชันของฉัน

คำถามของฉันคือถ้าทุกคนที่นี่สามารถทำแบบฝึกหัดเล็ก ๆ น้อย ๆ ซึ่งจะอธิบายวิธีใช้หนึ่งลิ้นชักเก็บเงินการนำทางสำหรับกิจกรรมหลายรายการ

ฉันอ่านก่อนที่คำตอบนี้ ลิ้นชักการนำทาง Android ในหลาย ๆ กิจกรรม

แต่มันไม่ทำงานในโครงการของฉัน

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

ในกิจกรรมนี้ฉันต้องการให้ลิ้นชักนำทางเพื่อให้ฉันขยาย 'NavigationDrawer' และในกิจกรรมอื่น ๆ ที่ฉันต้องการให้ผู้ใช้ลิ้นชักนำทางเดียวกัน

  public class SampleActivity extends NavigationDrawer {...}

ฉันไม่รู้จะเปลี่ยน ...


1
คุณสามารถค้นหาตัวอย่างที่นี่
Naddy

1
คุณสามารถค้นหาได้จาก: stackoverflow.com/questions/33009469/ …
varotariya vajsi

คำตอบ:


188

หากคุณต้องการลิ้นชักการนำทางคุณควรใช้ชิ้นส่วน ฉันติดตามกวดวิชานี้เมื่อสัปดาห์ที่แล้วและใช้งานได้ดี:

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

คุณยังสามารถดาวน์โหลดโค้ดตัวอย่างจากบทช่วยสอนนี้เพื่อดูว่าคุณสามารถทำสิ่งนี้ได้อย่างไร


ไม่มีชิ้นส่วน:

นี่คือรหัส 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);
    }
}

กิจกรรมอื่น ๆ ทั้งหมดที่ต้องมีลิ้นชักการนำทางควรขยายกิจกรรมนี้แทนกิจกรรมเองตัวอย่างเช่น:

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>

แก้ไข:

ฉันพบปัญหาบางอย่างด้วยตัวเองดังนั้นนี่เป็นวิธีแก้ปัญหาถ้าคุณได้รับ NullPointerExceptions ใน BaseActivity protected void onCreateDrawer()เปลี่ยนฟังก์ชั่นการ ส่วนที่เหลือสามารถอยู่เดิม ในกิจกรรมที่ขยาย BaseActivity ให้ใส่รหัสตามลำดับนี้:

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

สิ่งนี้ช่วยฉันแก้ไขปัญหาของฉันหวังว่าจะช่วยได้!

นี่คือวิธีที่คุณสามารถสร้างลิ้นชักการนำทางที่มีหลายกิจกรรมหากคุณมีคำถามใด ๆ อย่าลังเลที่จะถาม


แก้ไข 2:

ตามที่กล่าวโดย @GregDan คุณBaseActivityสามารถแทนที่setContentView()และโทรไปที่ CreateDrawer ที่นั่นได้:

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

7
ฉันไม่ต้องการใช้กิจกรรมมากกว่าแฟรกเมนต์ฉันเพียงต้องการใช้กิจกรรมต่าง ๆ ซึ่งใช้ลิ้นชักการนำทางเดียวกันทั้งหมด ฉันต้องการกิจกรรมเพราะมีฉันสามารถใช้รูปแบบที่แตกต่างกันเช่นมุมมองแบบกวาดมุมมองแผนที่ ...
MEX

135
การมีเพียงกิจกรรมเดียวอาจเป็นงานที่น่ากังวลสำหรับแอพที่ค่อนข้างซับซ้อน การใช้กิจกรรมช่วยให้คุณมีของว่างมากมายจากระบบ - ดังนั้นจึงเป็นจุดที่ถูกต้องในการใช้หลายกิจกรรม ฉันนึกภาพไม่ออกว่าการสื่อสารกิจกรรมการจัดการหนึ่งรายการระหว่างชุดของชิ้นส่วนใด ๆ - มันจะไม่ทำงาน
slott

1
ฉันขอโทษที่ใช้เวลานานมากในการตอบ ฉันแก้ไขคำตอบของฉัน ฉันเชื่อว่านี่เป็นบทเรียนที่คุณกำลังมองหา หวังว่านี่จะช่วยได้
Kevin van Mierlo

2
@KevinvanMierlo คุณสามารถบอกฉันได้ว่าคุณหมายถึงอะไร: R.id.drawer_layout ควรอยู่ในทุกกิจกรรมด้วยรหัสเดียวกันทุกประการ เพราะฉันทำสิ่งที่คุณบอกที่นี่และฉันได้รับ NullPointerException ใน onCreate () วิธีการของกิจกรรมที่ขยาย BaseActivity นี้ ..
Loolooii

1
@KevinvanMierlo btw ฉันคิดว่าคุณลืม 2 บรรทัดนี้เหรอ? super.onCreate (savedInstanceState); setContentView (R.layout.activity_base);
Loolooii

34

ฉันพบว่าการใช้งานที่ดีที่สุด มันอยู่ในGoogle I / O 2014แอป

พวกเขาใช้วิธีการเดียวกับของเควิน หากคุณสามารถแยกตัวเองออกจากสิ่งที่ไม่จำเป็นทั้งหมดในแอป I / O คุณสามารถแยกทุกสิ่งที่คุณต้องการและ Google มั่นใจได้ว่าเป็นรูปแบบลิ้นชักการนำทางที่ถูกต้อง แต่ละกิจกรรมมีทางเลือกDrawerLayoutเป็นเลย์เอาต์หลัก ส่วนที่น่าสนใจคือวิธีการนำทางไปยังหน้าจออื่น ๆ มันถูกนำไปใช้ในBaseActivityลักษณะนี้:

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

สิ่งนี้แตกต่างจากวิธีทั่วไปของการแทนที่แฟรกเมนต์ปัจจุบันด้วยธุรกรรมแฟรกเมนต์ แต่ผู้ใช้ไม่เห็นความแตกต่างทางภาพ


นี่ฉัน ^ ไม่สามารถคิดออกว่าพวกเขาเริ่มกิจกรรมใหม่และทำงานได้อย่างไม่มีที่ติ มันเป็นแอพขนาดใหญ่ที่ใช้งานได้ดี
hitch.united

@ hitch.united นั่นเป็นเพราะพวกเขาใช้ชิ้นส่วนจำนวนมากและมีเพียงไม่กี่กิจกรรม
Joaquin Iurchuk

@ hitch.united overridePendingTransitionsพวกเขาอาจแทนที่การเคลื่อนไหวของกิจกรรมที่มี
EpicPandaForce

กำลังโหลดชิ้นส่วนแทนที่จะเป็นกิจกรรมย่อย
Vikas Pandey

นี่คือไฟล์จากตุลาคม 2014: github.com/google/iosched/blob/…
denvercoder9

8

ดังนั้นคำตอบนี้เป็นเวลาไม่กี่ปีที่ผ่านมา แต่บางคนอาจชื่นชมมัน Android ได้มอบวิดเจ็ตใหม่ให้เราซึ่งทำให้การใช้หนึ่งลิ้นชักการนำทางที่มีกิจกรรมหลายอย่างง่ายขึ้น

android.support.design.widget.NavigationView เป็นโมดูลและมีเลย์เอาต์ของตัวเองในโฟลเดอร์เมนู วิธีที่คุณใช้คือห่อรูปแบบ xml ด้วยวิธีต่อไปนี้:

  1. เค้าโครงเลย์เอาต์เป็น android.support.v4.widget.DrawerLayout ที่มีลูกสองคน: <include ... />สำหรับเลย์เอาต์ที่ถูกห่อ (ดู 2) และ 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 เป็นเพียง LinearLayout พร้อมปฐมนิเทศ = แนวตั้งสำหรับส่วนหัวของ Navigation Drawar ของคุณ

activity_main_drawer เป็นเมนู xml ในไดเรกทอรี res / menu ของคุณ มันสามารถมีรายการและกลุ่มที่คุณเลือก หากคุณใช้แกลเลอรี AndroidStudio ตัวช่วยสร้างจะสร้างพื้นฐานให้คุณและคุณสามารถดูว่าตัวเลือกของคุณคืออะไร

  1. เลย์เอาต์ของแถบแอปมักจะเป็น android.support.design.widget.CoordinatorLayout และจะรวมลูกสองคนไว้ด้วย: android.support.design.widget.AppBarLayout (ซึ่งมี android.support.v7.widget.Toolbar) และ<include ... >สำหรับ เนื้อหาจริงของคุณ (ดู 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. โครงร่างเนื้อหาสามารถเป็นเค้าโครงใดก็ได้ที่คุณต้องการ นี่คือเลย์เอาต์ที่มีเนื้อหาหลักของกิจกรรม (ไม่รวมแถบการนำทางหรือแถบแอป)

ทีนี้สิ่งที่ยอดเยี่ยมเกี่ยวกับสิ่งนี้คือคุณสามารถห่อแต่ละกิจกรรมในเค้าโครงสองแบบนี้ แต่ให้ NavigationView ของคุณ (ดูขั้นตอนที่ 1) ชี้ไปที่ activity_main_drawer (หรืออะไรก็ตาม) ซึ่งหมายความว่าคุณจะมีลิ้นชักนำทาง (*) เหมือนกันในทุกกิจกรรม

  • พวกเขาจะไม่เป็นอินสแตนซ์เดียวกันกับNavigationView แต่เพื่อความเป็นธรรมนั่นเป็นไปไม่ได้แม้จะมีโซลูชัน BaseActivity ที่แสดงไว้ด้านบน

stackoverflow กำลังตัดวงเล็บเหลี่ยม xml บางส่วนออก แต่สิ่งสำคัญอยู่ที่นั่น
jwehrle

แต่คุณจะใช้งานฟังก์ชั่นต่าง ๆ เช่นปุ่มได้อย่างไร? คุณต้องเขียนรหัสเดียวกันในทุกกิจกรรมหรือไม่
Laur89

ใช่เพราะสิ่งเหล่านี้เป็นกรณีที่แยกจากกัน อย่างไรก็ตามคุณสามารถสร้างคลาสซุปเปอร์สำหรับกิจกรรมของคุณเพื่อขยายและใส่รหัสนั้นในครั้งเดียว
jwehrle

@jwehrle คุณสามารถเขียนตัวอย่างเกี่ยวกับการทำซูเปอร์คลาสสำหรับกิจกรรมของเราได้หรือไม่
CDrosos

ประชาชน MyBaseActivity ระดับนามธรรมขยายการดำเนินการ AppCompatActivity NavigationView.OnNavigationItemSelectedListener {// ดำเนินการดังต่อไปนี้: ประชาชนแทนที่บูล onNavigationItemSelected (@NonNull MenuItem รายการ) {}} MyActivity ระดับสาธารณะขยาย MyBaseActivity {}
jwehrle

7

วิธีที่ง่ายที่สุดในการใช้การนำทางกลับลิ้นชักทั่วไปในกลุ่มของกิจกรรม

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

คุณสามารถให้ตัวอย่างของกิจกรรมที่ใช้กิจกรรมพื้นฐานนี้ได้หรือไม่
CDrosos

ไม่สามารถจำรายละเอียดใด ๆ เกี่ยวกับเรื่องนี้ได้ฉันคิดว่าการขยายAppBaseActivity และsetContentViewวิธีการเริ่มต้นควรจะทำได้
Levon Petrosyan

6

สำหรับคนอื่น ๆ ที่ต้องการทำสิ่งที่โปสเตอร์ต้นฉบับขอให้พิจารณาใช้ชิ้นส่วนแทนวิธีที่เควินพูด นี่คือการสอนที่ยอดเยี่ยมเกี่ยวกับวิธีการทำ:

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

หากคุณเลือกที่จะใช้กิจกรรมแทนชิ้นส่วนคุณจะพบกับปัญหาของการนำทางลิ้นชักที่ถูกสร้างขึ้นใหม่ทุกครั้งที่คุณนำทางไปยังกิจกรรมใหม่ สิ่งนี้ส่งผลให้เกิดการเรนเดอร์ที่น่าเกลียด / ช้าของลิ้นชักนำทางในแต่ละครั้ง


5

ข้อเสนอแนะของฉันคือ: อย่าใช้กิจกรรมเลยแทนที่จะใช้ชิ้นส่วนและแทนที่พวกเขาในภาชนะ (ตัวอย่างเช่นเค้าโครงเชิงเส้น) ที่คุณแสดงส่วนแรกของคุณ

รหัสนี้มีอยู่ในบทแนะนำสำหรับนักพัฒนา Android คุณเพียงแค่ต้องปรับแต่ง

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

ขอแนะนำให้คุณใช้แฟรกเมนต์ในแอปพลิเคชันของคุณมากขึ้นและควรมีกิจกรรมพื้นฐานเพียงสี่กิจกรรมในแอปพลิเคชันของคุณซึ่งคุณพูดถึงใน AndroidManifest.xml นอกเหนือจากกิจกรรมภายนอก (ตัวอย่างเช่น FacebookActivity):

  1. SplashActivity: ไม่ใช้แฟรกเมนต์และใช้ธีมเต็มหน้าจอ

  2. LoginSignUpActivity: ไม่ต้องใช้ NavigationDrawer เลยและไม่มีปุ่มย้อนกลับเช่นกันดังนั้นเพียงแค่ใช้แถบเครื่องมือปกติ แต่อย่างน้อย 3 หรือ 4 ชิ้นจะต้องมี ใช้ชุดรูปแบบแถบแอ็คชั่น

  3. หน้าหลักกิจกรรมหรือกิจกรรมแดชบอร์ด: ใช้ธีมแบบไม่มีการกระทำ ที่นี่คุณต้องการการนำทางลิ้นชักรวมถึงหน้าจอทั้งหมดที่ตามมาจะเป็นชิ้นส่วนหรือชิ้นส่วนซ้อนกันจนถึงมุมมองลีฟพร้อมกับแชร์ลิ้นชัก การตั้งค่าทั้งหมดโปรไฟล์ผู้ใช้และอื่น ๆ จะอยู่ที่นี่เป็นชิ้นส่วนในกิจกรรมนี้ แฟรกเมนต์ที่นี่จะไม่ถูกเพิ่มในสแต็กหลังและจะถูกเปิดจากรายการเมนู drawer ในกรณีของชิ้นส่วนที่ต้องการปุ่มย้อนกลับแทนที่จะเป็นลิ้นชักจะมีกิจกรรมประเภทที่สี่ด้านล่าง

  4. กิจกรรมไม่มีลิ้นชัก กิจกรรมนี้มีปุ่มย้อนกลับด้านบนและส่วนย่อยภายในจะแบ่งปันแถบการกระทำเดียวกัน แฟรกเมนต์เหล่านี้จะถูกเพิ่มในสแต็กหลังเนื่องจากจะมีประวัติการนำทาง

[สำหรับคำแนะนำเพิ่มเติมโปรดดู: https://stackoverflow.com/a/51100507/787399 ]

Happy Coding !!


นี่คือโพสต์เก่า คุณสามารถใช้ชิ้นส่วนเพื่อให้แน่ใจว่าคุณมีกิจกรรมเดียวเสมอ คุณเปลี่ยนชิ้นส่วนในภาชนะเดียวโดยเฉพาะ ใส่กลับในสแต็กเมื่อคุณต้องการการนำทางย้อนกลับหรือป๊อปอัพแฟรกเมนต์ทั้งหมดเมื่อคุณต้องการแฟรกเมนต์ที่จะแสดงเป็นอันแรก
Abhinav Saxena

@ Cabuxa.Mapache โปรดตรวจสอบลิงก์ที่แนบมากับคำตอบของฉันเพื่อรับความช่วยเหลือเพิ่มเติม ฉันใช้งาน BaseActivity ทั่วไปซึ่งช่วยแบ่งปัน ActionBar ToolBar และ NavigatonDrawer และส่วนประกอบอื่น ๆ ในส่วนย่อยทั้งหมดที่แนบมา
Abhinav Saxena

1

อัปเดตรหัสนี้ใน baseactivity และอย่าลืมใส่ drawer_list_header ในกิจกรรม xml ของคุณ

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

และไม่ใช้คำขอ () ในกิจกรรมของคุณ แต่ยังคงมองไม่เห็นลิ้นชักเมื่อคลิกที่ภาพ .. และโดยการลากจะปรากฏโดยไม่มีรายการ ฉันพยายามมาก แต่ก็ไม่ประสบความสำเร็จ ต้องการการออกกำลังกายสำหรับสิ่งนี้ ...


1

ด้วยคำตอบของ @Kevin van Mierlo คุณสามารถใช้หลายลิ้นชักได้เช่นกัน ตัวอย่างเช่นเมนูเริ่มต้นที่อยู่ทางด้านซ้าย (เริ่ม) และเมนูเพิ่มเติมที่อยู่ทางด้านขวาซึ่งจะปรากฏเฉพาะเมื่อมีการโหลดชิ้นส่วนที่แน่นอน

ฉันสามารถทำเช่นนั้นได้


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







    }

ใช้สิ่งนี้สำหรับ 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>

ใช้สิ่งนี้สำหรับส่วนหัวการนำทางหากต้องการใช้

<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

ฉันทำใน Kotlin เช่นนี้

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

กิจกรรมสำหรับ drawer ต้องสืบทอดสิ่งนี้BaseAppCompatActivityเรียกsuper.onCreateหลังจากตั้งค่าเนื้อหา (จริง ๆ แล้วสามารถย้ายไปยังวิธีการเริ่มต้นบางอย่าง) และมีองค์ประกอบที่สอดคล้องกันสำหรับรหัสในรูปแบบของพวกเขา


ฉันต้องการลองวิธีแก้ปัญหาของคุณ แต่ฉันได้รับข้อผิดพลาดนี้: "กิจกรรมนี้มีแถบการกระทำที่จัดทำโดยการตกแต่งหน้าต่าง" ฉันต้องการสลับระหว่าง 3 กิจกรรมและแต่ละกิจกรรมมีแถบแอพของตัวเอง คุณคิดว่าเป็นไปได้ไหม
davoid

ฉันคิดว่าคุณต้องย้ายแอคชั่นของคุณไปเป็นเศษเล็กเศษน้อยในกรณีนั้น ในแอพของเราเราใช้ธีม NoActionBar และจัดทำแถบเครื่องมือเพื่อความเข้ากันได้เท่าที่ฉันจำได้
Pavlus

@Pavlus โค้ดจะมีลักษณะอย่างไรในกิจกรรมที่สอง คลาส trackActivity: BaseAppCompatActivity () {?
Craig P

0

คำตอบของฉันเป็นเพียงแนวคิดที่ปราศจากซอร์สโค้ดใด ๆ มันอาจจะมีประโยชน์สำหรับผู้อ่านบางคนเช่นตัวฉันเองที่จะเข้าใจ

ขึ้นอยู่กับวิธีการเริ่มต้นของคุณในการออกแบบแอพของคุณ โดยทั่วไปมีสองวิธี

  1. คุณสร้างหนึ่งกิจกรรม (กิจกรรมพื้นฐาน) และมุมมองและหน้าจออื่น ๆ ทั้งหมดจะเป็นชิ้นส่วน กิจกรรมพื้นฐานนั้นมีการนำไปใช้งานสำหรับการจัดหน้าลิ้นชักและผู้ประสานงาน จริงๆแล้วมันเป็นวิธีที่ฉันชอบเพราะการมีชิ้นส่วนเล็ก ๆ ในตัวเองจะทำให้การพัฒนาแอปง่ายขึ้นและราบรื่นขึ้น

  2. หากคุณเริ่มต้นการพัฒนาแอพของคุณด้วยกิจกรรมหนึ่งรายการสำหรับแต่ละหน้าจอคุณอาจจะสร้างกิจกรรมพื้นฐานและกิจกรรมอื่น ๆ ทั้งหมดจะขยายออกไป กิจกรรมพื้นฐานจะมีรหัสสำหรับการใช้งานลิ้นชักและผู้ประสานงาน กิจกรรมใด ๆ ที่ต้องการการนำไปใช้งานของ drawer สามารถขยายได้จากกิจกรรมพื้นฐาน

โดยส่วนตัวฉันชอบหลีกเลี่ยงการใช้ชิ้นส่วนและกิจกรรมต่าง ๆ โดยไม่มีการจัดระเบียบ นั่นทำให้การพัฒนายากขึ้นและทำให้คุณติดขัดในที่สุด หากคุณทำเสร็จให้ทำการ refactor code ของคุณ


-1

สร้างแถบการนำทางใน MainActivity โดยใช้แฟรกเมนต์
เริ่มต้นการนำทางลิ้นชักใน MainActivity ใน
ขณะนี้ในกิจกรรมอื่น ๆ ทั้งหมดที่คุณต้องการใช้การนำทางลิ้นชักแบบเดิมที่ใส่ DrawerLayout เป็นฐานและส่วนย่อยเป็นลิ้นชักการนำทาง เพียงตั้งค่า android: ชื่อในส่วนของคุณชี้ไปที่ไฟล์ Java ส่วนของคุณ คุณไม่จำเป็นต้องเริ่มต้นส่วนย่อยในกิจกรรมอื่น ๆ
คุณสามารถเข้าถึง Nav Drawer โดยการปัดในกิจกรรมอื่น ๆ เช่นในแอพ Google Play Store

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.