Android错误通胀视图

时间:2016-07-22 22:04:26

标签: android android-fragments layout-inflater android-inflate

我有一个包含RecyclerView的Fragment(SearchResultsFragment)。搜索结果被加载到RecyclerView(这是一系列CardViews)。

当用户选择CardView时,它们将被带到另一个片段(EventDetailsFragment),在该片段中加载来自所选卡的数据。所有这一切都运行正常,我现在唯一的问题是,当用户选择手机上的后退按钮时,应用程序崩溃,给我一个XML文件无法膨胀的错误。

我怀疑这可能与我的RecyclerView有关。

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

我也遇到了这个错误:

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

以下是我的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());
        }
    });

}

这是按下后退按钮时无法膨胀的XML文件:

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

编辑:这是片段被热切换的活动(MainActivity) - 取决于选择的内容:

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

}

1 个答案:

答案 0 :(得分:0)

在StackOverflow上引用此线程:Binary XML file line #26: Duplicate id, tag null, or parent id with another fragment

事实证明我的问题是我在片段布局中有一个标签。这显然是不可能的 - 解决方案是将标记更改为LinearLayout标记,并使用FragmentManager将PlaceAutocompleteFragment加载到LinearLayout中。

新XML(更改了片段代码):

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

接下来,使用FragmentManager加载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();
}

然后,覆盖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();
}