0

Ich habe ein Fragment (SearchResultsFragment), die eine RecyclerView enthält. Suchergebnisse werden in die RecyclerView geladen (dies ist eine Reihe von CardViews).Android Fehler Aufblasen Ansicht

Wenn der Benutzer eine CardView auswählt, werden sie in ein anderes Fragment (EventDetailsFragment) übernommen, in dem Daten von der ausgewählten Karte geladen werden. All dies funktioniert gut, das einzige Problem, das ich jetzt habe, ist, wenn der Benutzer die Zurück-Taste auf ihrem Telefon auswählt, stürzt die App ab und gibt mir einen Fehler, dass die XML-Datei nicht aufgeblasen werden kann.

Ich habe den Verdacht, dass dies etwas mit meinem RecyclerView zu tun haben könnte.

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

ich diesen Fehler auch erhalten:

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 

Hier ist der Code auf meinem 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()); 
     } 
    }); 

} 

Dies ist die XML-Datei ist, die, wenn die Zurück-Taste gedrückt aufzublasen versagt wird :

<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: Dies ist die Aktivität (MainActivity), wo Fragmente hotswapped erhalten - je nachdem, was aufgenommen wird:

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

Das Problem ist, wie Sie die Fragmente laden; Sie sehen, Sie haben ein Fragment in einem anderen Fragment - Sie müssen untersuchen, wie Sie ein Kindfragment von einem Elternfragment aufblasen – Eenvincible

+0

Können Sie den Code Ihrer Aktivität (oder welche Komponente hält die fraglichen Fragmente) zeigen? Ich habe den Verdacht, dass Sie versuchen, ein Fragment zweimal hinzuzufügen, einmal beim ersten Start der Aktivität und einmal bei der Rückkehr zur Aktivität. Wenn Sie Fragmente programmgesteuert hinzufügen, müssen Sie überprüfen, ob sie im Fragmentmanager bereits vorhanden sind. –

+0

Postleitzahl Ihrer Aktivität. Es scheint, dass android: id = "@ + id/GoogleSearchFragment" zweimal hinzugefügt wird. Einmal in XML und ein anderes Mal in Code. – Rafal

Antwort

0

mit Bezug auf diesen Thread auf Stackoverflow: Binary XML file line #26: Duplicate id, tag null, or parent id with another fragment

Es stellt sich mein Problem war, dass Ich hatte ein Tag in einem Fragment-Layout. Dies ist anscheinend nicht möglich - die Lösung bestand darin, das Tag in ein LinearLayout-Tag zu ändern und den FragmentManager zu verwenden, um das PlaceAutocompleteFragment in das LinearLayout zu laden.

Neue XML (mit dem Fragment Tag geändert):

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

nächstes die FragmentManager Verwenden Sie die PlacesAutocompleteFragment zu laden:

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

Dann überschreiben die onDestroyView Methode:

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