studio programacion para móviles libros edición desarrollo desarrollar curso aprende aplicaciones android android-fragments google-maps-android-api-2 navigation-drawer android-maps-v2

para - manual de programacion android pdf



ID duplicado con fragmento (3)

Intenta reutilizar / reciclar tu diseño. Me encuentro con una "identificación duplicada" cuando uso un fragmento de mapa. Entonces en onCreateView en lugar de

final View rootView = inflater.inflate(R.layout.fragment_profile, container, false);

estoy usando

public class YourFragment extends Fragment { public YourFragment(){} ... private static View rootView; ... @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //View rootView = inflater.inflate(R.layout.fragment_layout, container, false); if (rootView != null) { ViewGroup parent = (ViewGroup) rootView.getParent(); if (parent != null) parent.removeView(rootView); } try { rootView = inflater.inflate(R.layout.fragment_layout, container, false); } catch (InflateException e) { /* map is already there, just return view as it is */ }

Estoy intentando aplicar el drawernavigation (mi primer fragmento es un mapa y los demás son solo algunos fragmentos con diseños simples). Por lo tanto, funciona bien y puedo navegar entre mis fragmentos, pero cuando regreso al primer fragmento que es un mapa, tiene un accidente

logcat:

11-20 11:03:27.306: E/AndroidRuntime(13787): FATAL EXCEPTION: main 11-20 11:03:27.306: E/AndroidRuntime(13787): android.view.InflateException: Binary XML file line #6: Error inflating class fragment 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:697) 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.view.LayoutInflater.rInflate(LayoutInflater.java:739) 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.view.LayoutInflater.inflate(LayoutInflater.java:489) 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.view.LayoutInflater.inflate(LayoutInflater.java:396) 11-20 11:03:27.306: E/AndroidRuntime(13787): at challenge.arabe.taxitaxi.HomeFragment.onCreateView(HomeFragment.java:48) 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:828) 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1032) 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.app.BackStackRecord.run(BackStackRecord.java:622) 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1382) 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.app.FragmentManagerImpl$1.run(FragmentManager.java:426) 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.os.Handler.handleCallback(Handler.java:605) 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.os.Handler.dispatchMessage(Handler.java:92) 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.os.Looper.loop(Looper.java:137) 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.app.ActivityThread.main(ActivityThread.java:4511) 11-20 11:03:27.306: E/AndroidRuntime(13787): at java.lang.reflect.Method.invokeNative(Native Method) 11-20 11:03:27.306: E/AndroidRuntime(13787): at java.lang.reflect.Method.invoke(Method.java:511) 11-20 11:03:27.306: E/AndroidRuntime(13787): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:980) 11-20 11:03:27.306: E/AndroidRuntime(13787): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:747) 11-20 11:03:27.306: E/AndroidRuntime(13787): at dalvik.system.NativeStart.main(Native Method) 11-20 11:03:27.306: E/AndroidRuntime(13787): Caused by: java.lang.IllegalArgumentException: Binary XML file line #6: Duplicate id 0x7f05000c, tag null, or parent id 0xffffffff with another fragment for com.google.android.gms.maps.MapFragment 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.app.Activity.onCreateView(Activity.java:4253) 11-20 11:03:27.306: E/AndroidRuntime(13787): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:673) 11-20 11:03:27.306: E/AndroidRuntime(13787): ... 18 more

Creo que esto es lo más importante:

Duplicate id 0x7f05000c, tag null, or parent id 0xffffffff with another fragment for com.google.android.gms.maps.MapFragment

así que este es mi código: LoginScreen: una actividad de fragmento que hace que todas las llamadas para el fragmento

public class LoginScreen extends FragmentActivity { 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; MapFragment mMap; GoogleMap googleMap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login_screen); int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext()); if(status == ConnectionResult.SUCCESS) { // what you want to do Toast.makeText(getApplicationContext(), "good connection", Toast.LENGTH_SHORT).show(); } // setUpMapIfNeeded(); // addTwitterMarq(); 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 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 Fragment fragment = null; switch (position) { case 0: fragment = new HomeFragment(); break; case 1: fragment = new FindPeopleFragment(); 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.frame_container, 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); } private void addTwitterMarq() { // TODO Auto-generated method stub LatLng pos = new LatLng(48.85078, 2.34440); googleMap.addMarker(new MarkerOptions() .title("Twitter") .snippet("Twitter HQ") .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)) .position(pos) ); } private void setUpMapIfNeeded() { // TODO Auto-generated method stub if (googleMap == null) { // Try to obtain the map from the SupportMapFragment. googleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap(); // Check if we were successful in obtaining the map. googleMap.setMyLocationEnabled(true); googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); if (googleMap != null) { // setUpMap(); drawTestJunk(); } } } private void drawTestJunk() { // TODO Auto-generated method stub UiSettings settings = googleMap.getUiSettings(); settings.setZoomControlsEnabled(true); settings.setCompassEnabled(true); settings.setTiltGesturesEnabled(false); settings.setMyLocationButtonEnabled(true); CameraUpdate camUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(45.53, -73.59), 14); googleMap.moveCamera(camUpdate); /** * "Markers" lesson */ googleMap.addMarker(new MarkerOptions() .position(new LatLng(45.538490,-73.598480)) .title("Hello world") .snippet("what does a snippet look like?") .draggable(true) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)) ); /** * skipping other "Marker" lessons, to move on to Lines, Polygons, and Circles. * Topic list for later study: * - Customized info windows * - Marker click events * - Marker drag events * - Info window click events */ /** * "Lines, Polygons, and Circles" lesson */ // LINE PolylineOptions route = new PolylineOptions() .add(new LatLng(45.538451240403596, -73.59851807077722) ) .add(new LatLng(45.5390432, -73.5997465) ) .add(new LatLng(45.5387234, -73.6000517) ) .add(new LatLng(45.5389376, -73.6005275) ) .color(Color.GREEN) ; Polyline polyline = googleMap.addPolyline(route); //you can also call PolylineOptions.addAll(Iterable<LatLng>) if the points are already in a list // POLYGON ArrayList<LatLng> hole= new ArrayList<LatLng>(); hole.add(new LatLng(45.5275, -73.5925)); hole.add(new LatLng(45.5225, -73.5925)); hole.add(new LatLng(45.5225, -73.5975)); hole.add(new LatLng(45.5275, -73.5975)); PolygonOptions rectOptions = new PolygonOptions() .add(new LatLng(45.53, -73.59), new LatLng(45.52, -73.59), new LatLng(45.52, -73.60), new LatLng(45.53, -73.60), new LatLng(45.53, -73.59)) .addHole(hole) .strokeColor(Color.RED) .fillColor(Color.BLUE); Polygon polygon = googleMap.addPolygon(rectOptions); // And sure, why not, a CIRCLE CircleOptions circleOptions = new CircleOptions() .center(new LatLng(45.525, -73.595)) .radius(100); Circle circle = googleMap.addCircle(circleOptions); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.login_screen, menu); return true; } }

y este es mi diseño principal para el fragmentoActividad:

<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" > </FrameLayout> <!-- <fragment android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" class="com.google.android.gms.maps.MapFragment"/> --> <!-- 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>

y este es el diseño xml del mapfragment:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" class="com.google.android.gms.maps.MapFragment"/> </RelativeLayout>

y este es el código mapfragment:

public class HomeFragment extends Fragment { int mCurrentPosition = -1; MapFragment mMap; GoogleMap googleMap; final static String ARG_POSITION = "position"; public HomeFragment(){} @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (savedInstanceState != null) { mCurrentPosition = savedInstanceState.getInt(ARG_POSITION); } View rootView = inflater.inflate(R.layout.fragment_map, container, false); // int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext()); // if(status == ConnectionResult.SUCCESS) { // // what you want to do // //Toast.makeText(getApplicationContext(), "good connection", Toast.LENGTH_SHORT).show(); // } setUpMapIfNeeded(); addTwitterMarq(); return rootView; } private void addTwitterMarq() { // TODO Auto-generated method stub LatLng pos = new LatLng(48.85078, 2.34440); googleMap.addMarker(new MarkerOptions() .title("Twitter") .snippet("Twitter HQ") .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)) .position(pos) ); } private void setUpMapIfNeeded() { // TODO Auto-generated method stub if (googleMap == null) { // Try to obtain the map from the SupportMapFragment. googleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap(); // Check if we were successful in obtaining the map. googleMap.setMyLocationEnabled(true); googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); if (googleMap != null) { // setUpMap(); drawTestJunk(); } } } private void drawTestJunk() { // TODO Auto-generated method stub UiSettings settings = googleMap.getUiSettings(); settings.setZoomControlsEnabled(true); settings.setCompassEnabled(true); settings.setTiltGesturesEnabled(false); settings.setMyLocationButtonEnabled(true); CameraUpdate camUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(45.53, -73.59), 14); googleMap.moveCamera(camUpdate); /** * "Markers" lesson */ googleMap.addMarker(new MarkerOptions() .position(new LatLng(45.538490,-73.598480)) .title("Hello world") .snippet("what does a snippet look like?") .draggable(true) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)) ); /** * skipping other "Marker" lessons, to move on to Lines, Polygons, and Circles. * Topic list for later study: * - Customized info windows * - Marker click events * - Marker drag events * - Info window click events */ /** * "Lines, Polygons, and Circles" lesson */ // LINE PolylineOptions route = new PolylineOptions() .add(new LatLng(45.538451240403596, -73.59851807077722) ) .add(new LatLng(45.5390432, -73.5997465) ) .add(new LatLng(45.5387234, -73.6000517) ) .add(new LatLng(45.5389376, -73.6005275) ) .color(Color.GREEN) ; Polyline polyline = googleMap.addPolyline(route); //you can also call PolylineOptions.addAll(Iterable<LatLng>) if the points are already in a list // POLYGON ArrayList<LatLng> hole= new ArrayList<LatLng>(); hole.add(new LatLng(45.5275, -73.5925)); hole.add(new LatLng(45.5225, -73.5925)); hole.add(new LatLng(45.5225, -73.5975)); hole.add(new LatLng(45.5275, -73.5975)); PolygonOptions rectOptions = new PolygonOptions() .add(new LatLng(45.53, -73.59), new LatLng(45.52, -73.59), new LatLng(45.52, -73.60), new LatLng(45.53, -73.60), new LatLng(45.53, -73.59)) .addHole(hole) .strokeColor(Color.RED) .fillColor(Color.BLUE); Polygon polygon = googleMap.addPolygon(rectOptions); // And sure, why not, a CIRCLE CircleOptions circleOptions = new CircleOptions() .center(new LatLng(45.525, -73.595)) .radius(100); Circle circle = googleMap.addCircle(circleOptions); } @Override public void onResume() { // TODO Auto-generated method stub super.onResume(); //setUpMapIfNeeded(); //addTwitterMarq(); } @Override public void onSaveInstanceState(Bundle outState) { // TODO Auto-generated method stub super.onSaveInstanceState(outState); outState.putInt(ARG_POSITION, mCurrentPosition); } public void updateArticleView(int position) { mCurrentPosition = position; } @Override public void onStart() { // TODO Auto-generated method stub super.onStart(); Bundle args = getArguments(); if (args != null) { // Set article based on argument passed in updateArticleView(args.getInt(ARG_POSITION)); } else if (mCurrentPosition != -1) { // Set article based on saved instance state defined during onCreateView updateArticleView(mCurrentPosition); } } }

¡Creo que el problema se encuentra en los métodos onResume y onCreateView! Espero que me ayudes gracias.


Creo que debe intentar recuperar la instancia de Fragments anterior en lugar de volver a crearla cada vez que se selecciona un elemento de un cajón. En su método displayView de Actividad de LoginScreen, debe hacer algo como eso en el interruptor:

Fragment fragment = null; String title = getResources().getString(SOME_FRAGMENT_TITLE); switch (position) { case 1: fragment = (YourFragment) fm.findFragmentByTag(title); if (fragment == null) fragment = new YourFragment(); break; }


utilizar esta

<fragment android:id="@+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" />

y reemplazar el método OnDestroyView y simplemente poner este código en OnDestroyView ()

public void onDestroyView() { super.onDestroyView(); Fragment fragment = (getFragmentManager().findFragmentById(R.id.map)); FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction(); ft.remove(fragment); ft.commit(); }