0

J'ai un fragment (SearchResultsFragment) qui contient un RecyclerView. Les résultats de la recherche sont chargés dans RecyclerView (ceci étant une série de CardViews). Lorsque l'utilisateur sélectionne CardView, il est transféré vers un autre fragment (EventDetailsFragment) dans lequel les données de la carte sélectionnée sont chargées. Tout cela fonctionne très bien, le seul problème que j'ai est maintenant, quand l'utilisateur sélectionne le bouton de retour sur leur téléphone, l'application se bloque, me donnant une erreur que le fichier XML ne peut pas être gonflé.Android Error Inflating View

Je soupçonne que cela puisse être lié à RecyclerView.

E/UncaughtException: android.view.InflateException: Binary XML file line #18: Binary XML file line #18: Error inflating class fragment 

Je reçois aussi cette erreur:

Caused by: java.lang.IllegalArgumentException: Binary XML file line #18: Duplicate id 0x7f0f0159, tag null, or parent id 0x7f0f0158 with another fragment for com.google.android.gms.location.places.ui.PlaceAutocompleteFragment 

Voici le code sur mon SearchResultsFragment:

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    View currentView = inflater.inflate(R.layout.fragment_start_search, container, false); 
    resolvingError = savedInstanceState != null && savedInstanceState.getBoolean(RESOLVING_ERROR, false); 
    initializeComponents(currentView); 
    buildGoogleApi(); 
    handlePermissions(); 
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 
     getDeviceSuggestedLocations(); 
    } 
    return currentView; 
} 

private void initializeComponents(final View currentView) { 
    searchResultsRecyclerView = (RecyclerView) currentView.findViewById(R.id.EventSearchResultsRecyclerView); 
    searchResultsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); 
    autoCompleteFragment = (PlaceAutocompleteFragment) getChildFragmentManager().findFragmentById(R.id.GoogleSearchFragment); 
    autoCompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() { 
     @Override 
     public void onPlaceSelected(Place place) { 
      currentLocation = place.getName().toString(); 
      selectedPlace = place; 
      processSearch(); 
     } 
     @Override 
     public void onError(Status status) { 
      displayMessage("Error Getting Location", status.getStatusMessage()); 
     } 
    }); 

} 

Ceci est le fichier XML qui ne parvient pas à gonfler lorsque le bouton de retour est pressée :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      xmlns:tools="http://schemas.android.com/tools" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      tools:context="Fragments.StartSearchFragment" 
      android:orientation="vertical" 
      > 
<android.support.v7.widget.CardView 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_margin="5dp" 
    > 
    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:id ="@+id/SearchLinearLayout" 
     android:orientation="vertical"> 
     <fragment 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:id = "@+id/GoogleSearchFragment" 
      android:name="com.google.android.gms.location.places.ui.PlaceAutocompleteFragment"></fragment> 
    </LinearLayout> 
</android.support.v7.widget.CardView> 
    <android.support.v7.widget.RecyclerView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:id = "@+id/EventSearchResultsRecyclerView" 
     android:layout_margin="5dp"> 
    </android.support.v7.widget.RecyclerView> 
</LinearLayout> 

EDIT: Ceci est l'activité (MainActivity) où les fragments sont hotswapped - en fonction de ce qui est choisi:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{ 
private Toolbar mainActivityToolbar; 
private TextView toolbarTextView; 
private ImageView toolbarImage; 
private FragmentManager mgr; 
private NavigationView navigationView; 
private DrawerLayout drawerLayout; 
private ActionBarDrawerToggle drawerToggle; 
private SharedPreferences activityPreferences; 
private SharedPreferences appSharedPreferences; 
private SharedPreferences.Editor editor; 

protected void onCreate(Bundle savedInstanceState) { 
    if (savedInstanceState == null) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     initializeControls(); 
     loadLandingScreenFragment(); 
    } else { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     initializeControls(); 
    } 
} 

public void initializeControls() 
{ 
    mainActivityToolbar = (Toolbar) findViewById(R.id.MainActivityToolbar); 
    toolbarTextView = (TextView) findViewById(R.id.MainActivityTextView); 
    toolbarImage = (ImageView) findViewById(R.id.MainActivityImageView); 
    drawerLayout = (DrawerLayout) findViewById(R.id.menuDrawerLayout); 
    navigationView = (NavigationView) findViewById(R.id.mainActivityNavigationView); 
    setSupportActionBar(mainActivityToolbar); 
    getSupportActionBar().setTitle(null); 
    getSupportActionBar().setHomeButtonEnabled(true); 
    getSupportActionBar().setDefaultDisplayHomeAsUpEnabled(true); 
    drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, mainActivityToolbar, R.string 
      .app_name, R 
      .string 
      .app_name); 
    drawerLayout.setDrawerListener(drawerToggle); 
    navigationView.inflateHeaderView(R.layout.navigation_menu_header); 
    navigationView.inflateMenu(R.menu.athlete_navigation_menu); 
    toolbarImage.setOnClickListener(this); 
    appSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); 
    activityPreferences = getSharedPreferences("iBaleka", MODE_PRIVATE); 
    editor = activityPreferences.edit(); 
    NavigationMenuOnItemSelectedListener listener = new NavigationMenuOnItemSelectedListener 
      (this); 
    navigationView.setNavigationItemSelectedListener(listener); 
    toolbarImage.setImageResource(R.drawable.ibaleka_logo); 
    mgr = getFragmentManager(); 
    mapComponents(); 

} 
public void loadLandingScreenFragment() 
{ 
    AthleteLandingFragment landingFragment = new AthleteLandingFragment(); 
    FragmentTransaction transaction = mgr.beginTransaction(); 
    transaction.replace(R.id.MainActivityContentArea, landingFragment, "UserStats"); 
    transaction.addToBackStack("UserStats"); 
    transaction.commit(); 
} 

private void mapComponents() 
{ 
    View headerView = navigationView.getHeaderView(0); 
    TextView athleteNameSurname = (TextView) headerView.findViewById(R.id.profileNameSurname); 
    TextView emailAddress = (TextView) headerView.findViewById(R.id.profileEmailAddress); 

    String nameSurname = appSharedPreferences.getString("Name", "") + " "+ appSharedPreferences.getString("Surname", ""); 
    athleteNameSurname.setText(nameSurname); 
    emailAddress.setText(appSharedPreferences.getString("EmailAddress", "").toLowerCase()); 

} 
@Override 
protected void onPause() { 
    editor.putString("ToolbarText", toolbarTextView.getText().toString()); 
    editor.commit(); 
    super.onPause(); 
} 
protected void onResume() { 
    super.onResume(); 
    toolbarTextView.setText(activityPreferences.getString("ToolbarText", "")); 
} 
@Override 
public void onBackPressed() { 
    if (mgr.getBackStackEntryCount() > 0) { 
     mgr.popBackStack(); 
    } else { 
     super.onBackPressed(); 
    } 

} 
+0

Le problème est comment vous chargez les fragments; vous voyez, vous avez un fragment à l'intérieur d'un autre fragment - vous devez regarder comment gonfler un fragment enfant à partir d'un fragment parent – Eenvincible

+0

Pouvez-vous montrer le code de votre activité (ou quel que soit le composant contenant les fragments en question)? Je soupçonne que vous essayez d'ajouter un fragment deux fois, une fois sur l'activité premier départ et une fois lorsque vous revenez à l'activité. Si vous ajoutez des fragments par programme, vous devez vérifier s'ils n'existent pas déjà dans le gestionnaire de fragments. –

+0

Code postal de votre activité. Il semble que Android: id = "@ + id/GoogleSearchFragment" est ajouté deux fois. Une fois en XML et une autre fois en code. – Rafal

Répondre

0

Avec référence à ce fil sur StackOverflow: Binary XML file line #26: Duplicate id, tag null, or parent id with another fragment

Il se trouve mon problème était que J'avais une étiquette à l'intérieur d'une disposition de fragment. Cela n'est apparemment pas possible - la solution consistait à changer la balise en une balise LinearLayout et à utiliser le gestionnaire de fragmentation pour charger la balise PlaceAutocompleteFragment dans LinearLayout.

Nouveau XML (avec la balise Fragment Changé):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      tools:context="Fragments.StartSearchFragment" 
      android:orientation="vertical" 
    > 
<android.support.v7.widget.CardView 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_margin="5dp" 
    > 
    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:id ="@+id/SearchLinearLayout" 
     android:orientation="vertical"> 
     <LinearLayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:id = "@+id/GoogleSearchFragment" 
      android:orientation="vertical"> 
     </LinearLayout> 
    </LinearLayout> 
</android.support.v7.widget.CardView> 
    <android.support.v7.widget.RecyclerView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:id = "@+id/EventSearchResultsRecyclerView" 
     android:layout_margin="5dp"> 
    </android.support.v7.widget.RecyclerView> 
</LinearLayout> 

Ensuite, utilisez le FragmentManager pour charger le PlacesAutocompleteFragment:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    View currentView = inflater.inflate(R.layout.fragment_start_search, container, false); 

    initializeComponents(currentView, savedInstanceState); 
    resolvingError = savedInstanceState != null && savedInstanceState.getBoolean(RESOLVING_ERROR, false); 
    buildGoogleApi(); 
    handlePermissions(); 
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 
     getDeviceSuggestedLocations(); 
    } 
    return currentView; 
} 

private void initializeComponents(View currentView, Bundle savedInstanceState) { 
    searchResultsRecyclerView = (RecyclerView) currentView.findViewById(R.id.EventSearchResultsRecyclerView); 
    searchResultsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); 
    autoCompleteFragment = new PlaceAutocompleteFragment(); 
    autoCompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() { 
      @Override 
      public void onPlaceSelected(Place place) { 
       currentLocation = place.getName().toString(); 
       selectedPlace = place; 
       processSearch(); 
      } 
      @Override 
      public void onError(Status status) { 
       displayMessage("Error Getting Location", status.getStatusMessage()); 
      } 
     }); 
    FragmentManager mgr = getFragmentManager(); 
    FragmentTransaction transaction = mgr.beginTransaction(); 
    transaction.replace(R.id.GoogleSearchFragment, autoCompleteFragment, "AutoSearchFragment"); 
    transaction.commit(); 
} 

Ensuite, remplacer la méthode onDestroyView:

@Override 
public void onDestroyView() { 
    super.onDestroyView(); 
    FragmentManager manager = getActivity().getFragmentManager(); 
    Fragment fragment = manager.findFragmentById(R.id.GoogleSearchFragment); 
    FragmentTransaction trans = manager.beginTransaction(); 
    trans.remove(fragment); 
    trans.commit(); 
}