[英]How to implement navigation drawer with fragments master detail
i have get the sample navigation drawer from this site : http://www.androidhive.info/2013/11/android-sliding-menu-using-navigation-drawer/ 我从这个网站获得了示例导航抽屉: http : //www.androidhive.info/2013/11/android-sliding-menu-using-navigation-drawer/
and the master detail from here : http://wptrafficanalyzer.in/blog/itemclick-handler-for-listfragment-in-android/ 以及来自这里的主要细节: http : //wptrafficanalyzer.in/blog/itemclick-handler-for-listfragment-in-android/
the error LogCat oncreateview(inflac....) the view can not be created 错误LogCat oncreateview(inflac ....)无法创建视图
me i have try that 我,我尝试过
//the main activiry as Activity:
package in.wptrafficanalyzer.listfragmentitemclick;
import in.wptrafficanalyzer.listfragmentitemclick.adapter.NavDrawerListAdapter;
import in.wptrafficanalyzer.listfragmentitemclick.model.NavDrawerItem;
import java.util.ArrayList;
import in.wptrafficanalyzer.listfragmentitemclick.R;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
public class MainActivity extends Activity implements CountryListFragment.ListFragmentItemClickListener {
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
// nav drawer title
private CharSequence mDrawerTitle;
// used to store app title
private CharSequence mTitle;
// slide menu items
private String[] navMenuTitles;
private TypedArray navMenuIcons;
private ArrayList<NavDrawerItem> navDrawerItems;
private NavDrawerListAdapter adapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTitle = mDrawerTitle = getTitle();
// load slide menu items
navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items);
// nav drawer icons from resources
navMenuIcons = getResources()
.obtainTypedArray(R.array.nav_drawer_icons);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.list_slidermenu);
navDrawerItems = new ArrayList<NavDrawerItem>();
// adding nav drawer items to array
// Home
navDrawerItems.add(new NavDrawerItem(navMenuTitles[0], navMenuIcons.getResourceId(0, -1)));
// Find People
navDrawerItems.add(new NavDrawerItem(navMenuTitles[1], navMenuIcons.getResourceId(1, -1)));
// Photos
navDrawerItems.add(new NavDrawerItem(navMenuTitles[2], navMenuIcons.getResourceId(2, -1)));
// Communities, Will add a counter here
navDrawerItems.add(new NavDrawerItem(navMenuTitles[3], navMenuIcons.getResourceId(3, -1), true, "22"));
// Pages
navDrawerItems.add(new NavDrawerItem(navMenuTitles[4], navMenuIcons.getResourceId(4, -1)));
// What's hot, We will add a counter here
navDrawerItems.add(new NavDrawerItem(navMenuTitles[5], navMenuIcons.getResourceId(5, -1), true, "50+"));
// Recycle the typed array
navMenuIcons.recycle();
mDrawerList.setOnItemClickListener(new SlideMenuClickListener());
// setting the nav drawer list adapter
adapter = new NavDrawerListAdapter(getApplicationContext(),
navDrawerItems);
mDrawerList.setAdapter(adapter);
// enabling action bar app icon and behaving it as toggle button
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_drawer, //nav menu toggle icon
R.string.app_name, // nav drawer open - description for accessibility
R.string.app_name // nav drawer close - description for accessibility
) {
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
// calling onPrepareOptionsMenu() to show action bar icons
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
// calling onPrepareOptionsMenu() to hide action bar icons
invalidateOptionsMenu();
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
if (savedInstanceState == null) {
// on first time display view for first nav item
displayView(0);
}
}
/**
* Slide menu item click listener
* */
private class SlideMenuClickListener implements
ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// display view for selected nav drawer item
displayView(position);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// toggle nav drawer on selecting action bar app icon/title
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action bar actions click
switch (item.getItemId()) {
case R.id.action_settings:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/***
* Called when invalidateOptionsMenu() is triggered
*/
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// if nav drawer is opened, hide the action items
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
/**
* Diplaying fragment view for selected nav drawer list item
* */
private void displayView(int position) {
// update the main content by replacing fragments
ListFragment fragment = null;
switch (position) {
case 0:
//fragment = new HomeFragment();
break;
case 1:
fragment = new CountryListFragment();
break;
case 2:
//fragment = new PhotosFragment();
break;
case 3:
// fragment = new CommunityFragment();
break;
case 4:
//fragment = new PagesFragment();
break;
case 5:
//fragment = new WhatsHotFragment();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.country_list_fragment, fragment).commit();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
setTitle(navMenuTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
} else {
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
}
}
@Override
public void setTitle(CharSequence title) {
mTitle = title;
getActionBar().setTitle(mTitle);
}
/**
* When using the ActionBarDrawerToggle, you must call it during
* onPostCreate() and onConfigurationChanged()...
*/
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggls
mDrawerToggle.onConfigurationChanged(newConfig);
}
/** Called when the activity is first created. */
@Override
public void onListFragmentItemClick(int position) {
/** Getting the orientation ( Landscape or Portrait ) of the screen */
int orientation = getResources().getConfiguration().orientation;
/** Landscape Mode */
if(orientation == Configuration.ORIENTATION_LANDSCAPE ){
/** Getting the fragment manager for fragment related operations */
FragmentManager fragmentManager = getFragmentManager();
/** Getting the fragmenttransaction object, which can be used to add, remove or replace a fragment */
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
/** Getting the existing detailed fragment object, if it already exists.
* The fragment object is retrieved by its tag name
* */
Fragment prevFrag = fragmentManager.findFragmentByTag("in.wptrafficanalyzer.country.details");
/** Remove the existing detailed fragment object if it exists */
if(prevFrag!=null)
fragmentTransaction.remove(prevFrag);
/** Instantiating the fragment CountryDetailsFragment */
CountryDetailsFragment fragment = new CountryDetailsFragment();
/** Creating a bundle object to pass the data(the clicked item's position) from the activity to the fragment */
Bundle b = new Bundle();
/** Setting the data to the bundle object */
b.putInt("position", position);
/** Setting the bundle object to the fragment */
fragment.setArguments(b);
/** Adding the fragment to the fragment transaction */
fragmentTransaction.add(R.id.detail_fragment_container, fragment,"in.wptrafficanalyzer.country.details");
/** Adding this transaction to backstack */
fragmentTransaction.addToBackStack(null);
/** Making this transaction in effect */
fragmentTransaction.commit();
}else{ /** Portrait Mode or Square mode */
/** Creating an intent object to start the CountryDetailsActivity */
Intent intent = new Intent("in.wptrafficanalyzer.CountryDetailsActivity");
/** Setting data ( the clicked item's position ) to this intent */
intent.putExtra("position", position);
/** Starting the activity by passing the implicit intent */
startActivity(intent);
}
}
}
the CountryListFragment as listfragment : CountryListFragment as listfragment:
package in.wptrafficanalyzer.listfragmentitemclick;
import android.app.Activity;
import android.app.ListFragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
public class CountryListFragment extends ListFragment{
/** List of countries to be displayed in the ListFragment */
ListFragmentItemClickListener ifaceItemClickListener;
/** An interface for defining the callback method */
public interface ListFragmentItemClickListener {
/** This method will be invoked when an item in the ListFragment is clicked */
void onListFragmentItemClick(int position);
}
/** A callback function, executed when this fragment is attached to an activity */
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try{
/** This statement ensures that the hosting activity implements ListFragmentItemClickListener */
ifaceItemClickListener = (ListFragmentItemClickListener) activity;
}catch(Exception e){
Toast.makeText(activity.getBaseContext(), "Exception",Toast.LENGTH_SHORT).show();
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/** Data source for the ListFragment */
ArrayAdapter<String> adapter = new ArrayAdapter<String>(inflater.getContext(), android.R.layout.simple_list_item_1, Country.name);
/** Setting the data source to the ListFragment */
setListAdapter(adapter);
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
/** Invokes the implementation of the method istFragmentItemClick in the hosting activity */
ifaceItemClickListener.onListFragmentItemClick(position);
}
}
layout main in folder layout 布局主要在文件夹布局中
><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
android:id="@+id/country_list_fragment"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:name="in.wptrafficanalyzer.listfragmentitemclick.CountryListFragment"
/>
<!-- 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/list_divider"
android:dividerHeight="1dp"
android:listSelector="@drawable/list_selector"
android:background="@color/list_background"/>
> </android.support.v4.widget.DrawerLayout>
layout main in the folder layout-land 布局主要在文件夹布局 - 土地
><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
android:id="@+id/country_list_fragment"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:name="in.wptrafficanalyzer.listfragmentitemclick.CountryListFragment"
/>
<FrameLayout
android:id="@+id/detail_fragment_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center"
/>
<!-- 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/list_divider"
android:dividerHeight="1dp"
android:listSelector="@drawable/list_selector"
android:background="@color/list_background"/>
></android.support.v4.widget.DrawerLayout>
I was confused by this, too. 我也对此感到困惑。 I set up the Navigation Drawer to navigate between major sections of my app.
我设置导航抽屉以在我的应用程序的主要部分之间导航。 Then I wanted one of those major sections to be set up as Master/Detail.
然后我想要将其中一个主要部分设置为Master / Detail。 I knew it was possible, since this is basically what Gmail is, but was having a hard time putting what I had already built together with what Eclipse spits out when generating a Master/Detail Activity.
我知道这是可能的,因为这基本上就是Gmail,但在生成Master / Detail Activity时,很难将我已经构建的内容与Eclipse吐出的内容放在一起。
I couldn't just launch the ItemListFragment (Master/Detail) from the MainActivity (Navigation Drawer), because ItemListFragment wants to attach to ItemListActivity, not MainActivity, and a fragment can't have two Activities. 我不能从MainActivity(导航抽屉)中启动ItemListFragment(主/细节),因为ItemListFragment想要附加到ItemListActivity而不是MainActivity,并且片段不能有两个Activity。
I finally found a tutorial on it that actually used the two design ideas together: http://blog.evizija.si/android-layout/ 我终于找到了一个实际使用这两个设计思想的教程: http : //blog.evizija.si/android-layout/
I just followed their example and got my UI working as desired in about 5 minutes. 我只是按照他们的例子,让我的UI在大约5分钟内按照需要工作。 It's actually incredibly simple.
它实际上非常简单。 You make MasterActivity look a bit more like the generated ItemListActivity (ie. implement TaskListFragment.Callbacks, copy over the onItemSelected method, and a chuck of onCreate) and you're done!
你使MasterActivity看起来更像生成的ItemListActivity(即实现TaskListFragment.Callbacks,复制onItemSelected方法,以及onCreate的一个chuck)你已经完成了!
I hope this helps solve your problem! 我希望这有助于解决您的问题! Happy coding!
快乐的编码!
(1) Make your drawer activity and fragments, lets call them MainActivity and some fragments we don't care about here. (1)让你的抽屉活动和碎片,让我们称之为MainActivity和我们在此不关心的一些片段。 Personally, I would create an empty Fragment, like ItemFragement for example, to be a place holder for the Master/Detail while I get the Drawer up and running.
就个人而言,我会创建一个空的片段,例如ItemFragement,作为Master / Detail的占位符,同时让Drawer启动并运行。 Then once the Drawer is working as desired, tackle the Master/Detail and linking them.
然后,一旦抽屉按照需要工作,解决主/细节并链接它们。
(2) Use the IDE wizard (I'm running Eclipse) to make the activities and fragments of master/detail flow. (2)使用IDE向导(我正在运行Eclipse)来创建主/详细信息流的活动和片段。 I'll refer to them by their default names: ItemListActivity, ItemListFragement, ItemDetailActivity, ItemDetailFragment.
我将通过它们的默认名称来引用它们:ItemListActivity,ItemListFragement,ItemDetailActivity,ItemDetailFragment。
(3) If you've used Master/Detail before, you know most of your logic goes into the fragment. (3)如果您之前使用过Master / Detail,那么您知道大部分逻辑都会进入片段。 This is still true when combining Master/Detail with Drawer.
将Master / Detail与Drawer结合使用时仍然如此。 Note, at this point there is no connection between our MainActivity and our Master/Detail flow, and the later may not even be accessible in the UI.
注意,此时我们的MainActivity和Master / Detail流程之间没有任何关联,后者甚至可能无法在UI中访问。
(4) Key Concept: To connect the Drawer with the List, our MainActivity is going to be the hosting Activity for ItemListFragment (rather than the current ItemListActivity). (4) 关键概念:要将抽屉与列表连接起来,我们的MainActivity将成为ItemListFragment的托管活动(而不是当前的ItemListActivity)。 To make this work, we just copy over some of the Master/Detail magic created by the wizard FROM ItemListActivity INTO MainActivity.
为了完成这项工作,我们只需复制一些由向导FROM ItemListActivity INTO MainActivity创建的Master / Detail魔法。
(5) Specifically: (5)具体:
(5A) MainActivity implements ItemListFragment.Callbacks (or EmployeeListFragment.Callbacks, AlbumListFragment.Callbacks, whatever you are listing) and implement onItemSelected method (5A)MainActivity实现ItemListFragment.Callbacks(或EmployeeListFragment.Callbacks,AlbumListFragment.Callbacks,无论你列出什么)并实现onItemSelected方法
public class MainActivity extends Activity implements OnItemClickListener, ItemListFragment.Callbacks {
(5B) Copy part of code from onCreate in ItemListActivity and paste it to onCreate in MainActivity. (5B)从ItemListActivity中复制onCreate的部分代码,并将其粘贴到MainActivity中的onCreate。 This part:
这部分:
if (findViewById(R.id.item_detail_container) != null) { // The detail container view will be present only in the // large-screen layouts (res/values-large and // res/values-sw600dp). If this view is present, then the // activity should be in two-pane mode. mTwoPane = true; // In two-pane mode, list items should be given the // 'activated' state when touched. ((ItemListFragment) getFragmentManager() .findFragmentById(R.id.item_list)) .setActivateOnItemClick(true); }
(5C) Also copy onItemSelected method from ItemListActivity and paste it into MainActivity. (5C)同样从ItemListActivity复制onItemSelected方法并将其粘贴到MainActivity中。 You will already have an onItemSelected method if you told Eclipse to "add unimplemented methods" in response to the error that would have been raised after Step 5A.
如果你告诉Eclipse“添加未实现的方法”以响应在步骤5A之后引发的错误,那么你已经有了一个onItemSelected方法。 If you don't, copy over the whole method.
如果不这样做,请复制整个方法。 ( this step edited in response to a question in comments ) Code:
( 此步骤针对评论中的问题进行了编辑 )代码:
if (mTwoPane) { // In two-pane mode, show the detail view in this activity by // adding or replacing the detail fragment using a // fragment transaction. Bundle arguments = new Bundle(); arguments.putString(ItemDetailFragment.ARG_ITEM_ID, id); ItemDetailFragment fragment = new ItemDetailFragment(); fragment.setArguments(arguments); getFragmentManager().beginTransaction() .replace(R.id.item_detail_container, fragment) .commit(); } else { // In single-pane mode, simply start the detail activity // for the selected item ID. Intent detailIntent = new Intent(this, ItemDetailActivity.class); detailIntent.putExtra(ItemDetailFragment.ARG_ITEM_ID, id); startActivity(detailIntent); }
(6) Then the last step is to have MainActivity (the Drawer) open ItemListFragment. (6)然后最后一步是让MainActivity(抽屉)打开ItemListFragment。 If you already have a placeholder Fragment launching (like ItemFragement suggested in Step 1), this is just a matter of replacing ItemFragment with ItemListFragment in the onNavigationDrawerItemSelected method.
如果您已经启动了占位符Fragment(如步骤1中建议的ItemFragement),则只需在onNavigationDrawerItemSelected方法中用ItemListFragment替换ItemFragment即可。
Hope that's clear. 希望很清楚。 If not, the original link might do a better job explaining than I did.
如果没有,原始链接可能比我更好地解释。 Just skim to the bottom where the blogger talks about adding the list activity to their drawer activity.
只是浏览一下博客谈论将列表活动添加到抽屉活动的底部。
cheers. 干杯。
UPDATE: 更新:
After being ask to do so by a moderator, I'm flagging this and another similar question (as duplicates). 在被主持人要求这样做之后,我正在标记这个和另一个类似的问题(重复)。
Those questions: 那些问题:
https://stackoverflow.com/questions/25403377/combine-navigation-drawer-and-master-detail-layout https://stackoverflow.com/questions/25403377/combine-navigation-drawer-and-master-detail-layout
Navigation Drawer and master/detail flow 导航抽屉和主/细节流程
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.