【问题标题】:Android Error Inflating ViewAndroid 错误膨胀视图
【发布时间】:2016-07-22 22:04:25
【问题描述】:

我有一个包含 RecyclerView 的片段 (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>

编辑:这是片段被热交换的 Activity (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();
    }

}

【问题讨论】:

  • 问题在于如何加载片段;你看,你在另一个片段中有一个片段 - 你需要研究如何从父片段中膨胀一个子片段
  • 您能否展示您的活动代码(或任何包含相关片段的组件)?我怀疑您尝试添加片段两次,一次是在活动第一次开始时,一次是在您返回活动时。如果您确实以编程方式添加任何片段,则需要检查它们是否已存在于片段管理器中。
  • 您活动的邮政编码。似乎 android:id = "@+id/GoogleSearchFragment" 添加了两次。一次在 xml 中,另一次在代码中。
  • 我为我的 MainActivity 添加了代码 - 这是交换片段的地方。
  • 你确定错误是inflate而不是它之后的代码

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


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多