重复ID,标签空,或父ID与另一个片段com.google.android.gms.maps.MapFragment [英] Duplicate ID, tag null, or parent id with another fragment for com.google.android.gms.maps.MapFragment

查看:173
本文介绍了重复ID,标签空,或父ID与另一个片段com.google.android.gms.maps.MapFragment的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有三个选项卡的应用程序。

每个标签都有自己的布局.xml文件。该main.xml中有它自己的地图片段。这是一个显示了当应用程序第一次启动。

一切工作正常,只是当我在标签之间改变。如果我试图切换回地图片段选项卡,我得到这个错误。切换到和其他标签页之间工作得很好。

什么在这里可能是错了吗?

这是我的主类和我的main.xml,以及我使用(你还可以找到底部的错误日志)相关类

主类

 包com.nfc.demo;

进口android.app.ActionBar;
进口android.app.ActionBar.Tab;
进口android.app.Activity;
进口android.app.Fragment;
进口android.app.FragmentTransaction;
进口android.os.Bundle;
进口android.widget.Toast;

公共类NFCDemoActivity延伸活动{

    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);

        动作条酒吧= getActionBar();
        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        bar.setDisplayOptions(0,ActionBar.DISPLAY_SHOW_TITLE);

        bar.addTab(酒吧
                。新标签()
                .setText(地图)
                .setTabListener(
                        新TabListener< MapFragment>(这一点,地图,
                                MapFragment.class)));
        bar.addTab(酒吧
                。新标签()
                .setText(设置)
                .setTabListener(
                        新TabListener< SettingsFragment>(这一点,设置,
                                SettingsFragment.class)));
        bar.addTab(酒吧
                。新标签()
                .setText(关于)
                .setTabListener(
                        新TabListener< AboutFragment>(这一点,约,
                                AboutFragment.class)));

        如果(savedInstanceState!= NULL){
            bar.setSelectedNavigationItem(savedInstanceState.getInt(标签,0));
        }
        //的setContentView(R.layout.main);

    }

    @覆盖
    保护无效的onSaveInstanceState(包outState){
        super.onSaveInstanceState(outState);
        outState.putInt(标签,getActionBar()getSelectedNavigationIndex());
    }

    公共静态类TabListener<吨延伸片断>器物
            ActionBar.TabListener {
        私人最终活动mActivity;
        私人最终字符串MTAG;
        私人最终类别< T> mClass;
        私人最终捆绑mArgs;
        私人片段mFragment;

        公共TabListener(活动活动,字符串变量,类< T> CLZ){
            这(活动,吊牌,CLZ,NULL);
        }

        公共TabListener(活动活动,字符串变量,类< T> CLZ,
                捆绑参数){
            mActivity =活动;
            MTAG =标签;
            mClass = CLZ;
            mArgs = ARGS;

            //检查,看看我们是否已经有了一个片段此选项卡,
            //可能是从previously保存的状态。如果是这样,停用
            //它,因为我们的初始状态是一个选项卡不显示。
            mFragment = mActivity.getFragmentManager()findFragmentByTag(MTAG)。
            如果(mFragment =空&安培;!&安培;!mFragment.isDetached()){
                FragmentTransaction英尺= mActivity.getFragmentManager()
                        .beginTransaction();
                ft.detach(mFragment);
                ft.commit();
            }
        }

        公共无效onTabSelected(TAB键,FragmentTransaction英尺){
            如果(mFragment == NULL){
                mFragment = Fragment.instantiate(mActivity,mClass.getName(),
                        mArgs);
                ft.add(android.R.id.content,mFragment,MTAG);
            } 其他 {
                ft.attach(mFragment);
            }
        }

        公共无效onTabUnselected(TAB键,FragmentTransaction英尺){
            如果(mFragment!= NULL){
                ft.detach(mFragment);
            }
        }

        公共无效onTabReselected(TAB键,FragmentTransaction英尺){
            Toast.makeText(mActivity,复选!,Toast.LENGTH_SHORT)
                         。显示();
        }
    }

}
 

的main.xml

 < XML版本=1.0编码=UTF-8&GT?;
< LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent
    机器人:方向=垂直>

    <片段
        的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
        机器人:ID =@ + ID / mapFragment
        机器人:名称=com.google.android.gms.maps.MapFragment
        机器人:layout_width =match_parent
        机器人:layout_height =match_parent/>
< / LinearLayout中>
 

相关类(MapFragment.java)

 包com.nfc.demo;

进口android.app.Fragment;
进口android.os.Bundle;
进口android.view.LayoutInflater;
进口android.view.View;
进口android.view.ViewGroup;

公共类MapFragment扩展片段{

    @覆盖
    公共查看onCreateView(LayoutInflater充气,容器的ViewGroup,
            捆绑savedInstanceState){
        super.onCreateView(充气,容器,savedInstanceState);
        返回inflater.inflate(R.layout.main,集装箱,假);
    }

    公共无效的onDestroy(){
        super.onDestroy();
    }
}
 

错误

  android.view.InflateException:二进制XML文件中的行#7:
     错误充气类片段
   在android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
   在android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
   在android.view.LayoutInflater.inflate(LayoutInflater.java:489)
   在android.view.LayoutInflater.inflate(LayoutInflater.java:396)
   在com.nfc.demo.MapFragment.onCreateView(MapFragment.java:15)
   在android.app.Fragment.performCreateView(Fragment.java:1695)
   在android.app.FragmentManagerImpl.moveToState(FragmentManager.java:885)
   在android.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1255)
   在android.app.BackStackRecord.run(BackStackRecord.java:672)
   在android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435)
   在android.app.FragmentManagerImpl $ 1.运行(FragmentManager.java:441)
   在android.os.Handler.handleCallback(Handler.java:725)
   在android.os.Handler.dispatchMessage(Handler.java:92)
   在android.os.Looper.loop(Looper.java:137)
   在android.app.ActivityThread.main(ActivityThread.java:5039)
   在java.lang.reflect.Method.invokeNative(本机方法)
   在java.lang.reflect.Method.invoke(Method.java:511)
   在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:793)
   在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
   在dalvik.system.NativeStart.main(本机方法)

致:java.lang.IllegalArgumentException异常:
     二进制XML文件行#7:重复ID 0x7f040005,标记为空,或
     父ID的0xffffffff与另一个片段为
     com.google.android.gms.maps.MapFragment
   在android.app.Activity.onCreateView(Activity.java:4722)
   在android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:680)
   ... 19更多
 

解决方案

答案马特暗示的作品,但它会导致地图重新创建和重新绘制,这并不总是可取的。 经过大量的试验和错误,我发现了一个解决方案,它为我的作品:

 私有静态视图中查看;

@覆盖
公共查看onCreateView(LayoutInflater充气,容器的ViewGroup,捆绑savedInstanceState){
    如果(查看!= NULL){
        ViewGroup中父=(ViewGroup中)view.getParent();
        如果(父!= NULL)
            parent.removeView(视图);
    }
    尝试 {
        鉴于= inflater.inflate(R.layout.map,集装箱,假);
    }赶上(InflateException E){
        / *地图已经存在,只是返回观点,因为它是* /
    }
    返回查看;
}
 

有关良好的措施,这里的map.xml(R.layout.map)与R.id.mapFragment(机器人:ID =@ + ID / mapFragment):

 < XML版本=1.0编码=UTF-8&GT?;
< LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:ID =@ + ID / mapLayout
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent>

    <片段的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
        机器人:ID =@ + ID / mapFragment
        机器人:layout_width =match_parent
        机器人:layout_height =match_parent
        类=com.google.android.gms.maps.SupportMapFragment/>
< / LinearLayout中>
 

我希望这可以帮助,但我不能保证它不产生任何不良影响。

编辑:有一些不利的影响,退出应用程序,并再次启动时,如。由于应用程序不一定完全关闭(但只是把在后台睡觉),在previous codeI提交后重新启动应用程序将失败。我已经更新了code的东西,对我的作品,无论是打算在和放大器;出图并退出并重新启动应用程序,我不是太满意的try-catch位,但它似乎工作不够好。 <击>当看到堆栈跟踪它发生,我认为我可以只检查是否映射片段是在FragmentManager,不需要在try-catch块,code更新。

更多编辑:原来你需要的try-catch毕竟。只是检查地图碎片事实并非毕竟工作这么好。 Blergh。

I have an application with three tabs.

Each tab has its own layout .xml file. The main.xml has its own map fragment. It's the one that shows up when the application first launches.

Everything works fine except for when I change between tabs. If I try to switch back to the map fragment tab, I get this error. Switching to and between other tabs works just fine.

What could be wrong here?

This is my main class and my main.xml, as well as a relevant class that I use ( you will also find the error log at the bottom )

main class

package com.nfc.demo;

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.widget.Toast;

public class NFCDemoActivity extends Activity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ActionBar bar = getActionBar();
        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);

        bar.addTab(bar
                .newTab()
                .setText("Map")
                .setTabListener(
                        new TabListener<MapFragment>(this, "map",
                                MapFragment.class)));
        bar.addTab(bar
                .newTab()
                .setText("Settings")
                .setTabListener(
                        new TabListener<SettingsFragment>(this, "settings",
                                SettingsFragment.class)));
        bar.addTab(bar
                .newTab()
                .setText("About")
                .setTabListener(
                        new TabListener<AboutFragment>(this, "about",
                                AboutFragment.class)));

        if (savedInstanceState != null) {
            bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
        }
        // setContentView(R.layout.main);

    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
    }

    public static class TabListener<T extends Fragment> implements
            ActionBar.TabListener {
        private final Activity mActivity;
        private final String mTag;
        private final Class<T> mClass;
        private final Bundle mArgs;
        private Fragment mFragment;

        public TabListener(Activity activity, String tag, Class<T> clz) {
            this(activity, tag, clz, null);
        }

        public TabListener(Activity activity, String tag, Class<T> clz,
                Bundle args) {
            mActivity = activity;
            mTag = tag;
            mClass = clz;
            mArgs = args;

            // Check to see if we already have a fragment for this tab,
            // probably from a previously saved state. If so, deactivate
            // it, because our initial state is that a tab isn't shown.
            mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
            if (mFragment != null && !mFragment.isDetached()) {
                FragmentTransaction ft = mActivity.getFragmentManager()
                        .beginTransaction();
                ft.detach(mFragment);
                ft.commit();
            }
        }

        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            if (mFragment == null) {
                mFragment = Fragment.instantiate(mActivity, mClass.getName(),
                        mArgs);
                ft.add(android.R.id.content, mFragment, mTag);
            } else {
                ft.attach(mFragment);
            }
        }

        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
            if (mFragment != null) {
                ft.detach(mFragment);
            }
        }

        public void onTabReselected(Tab tab, FragmentTransaction ft) {
            Toast.makeText(mActivity, "Reselected!", Toast.LENGTH_SHORT)
                         .show();
        }
    }

}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <fragment
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/mapFragment"
        android:name="com.google.android.gms.maps.MapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

relevant class ( MapFragment.java )

package com.nfc.demo;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MapFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        return inflater.inflate(R.layout.main, container, false);
    }

    public void onDestroy() {
        super.onDestroy();
    }
}

error

android.view.InflateException: Binary XML file line #7: 
     Error inflating class fragment
   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
   at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
   at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
   at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
   at com.nfc.demo.MapFragment.onCreateView(MapFragment.java:15)
   at android.app.Fragment.performCreateView(Fragment.java:1695)
   at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:885)
   at android.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1255)
   at android.app.BackStackRecord.run(BackStackRecord.java:672)
   at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435)
   at android.app.FragmentManagerImpl$1.run(FragmentManager.java:441)
   at android.os.Handler.handleCallback(Handler.java:725)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:137)
   at android.app.ActivityThread.main(ActivityThread.java:5039)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:511)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
   at dalvik.system.NativeStart.main(Native Method)

Caused by: java.lang.IllegalArgumentException: 
     Binary XML file line #7: Duplicate id 0x7f040005, tag null, or 
     parent id 0xffffffff with another fragment for 
     com.google.android.gms.maps.MapFragment
   at android.app.Activity.onCreateView(Activity.java:4722)
   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:680)
   ... 19 more

解决方案

The answer Matt suggests works, but it cause the map to be recreated and redrawn, which isn't always desirable. After lots of trial and error, I found a solution that works for me:

private static View view;

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

For good measure, here's "map.xml" (R.layout.map) with R.id.mapFragment (android:id="@+id/mapFragment"):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mapLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/mapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.SupportMapFragment" />
</LinearLayout>

I hope this helps, but I can't guarantee that it doesn't have any adverse effects.

Edit: There were some adverse effects, such as when exiting the application and starting it again. Since the application isn't necessarily completely shut down (but just put to sleep in the background), the previous code i submitted would fail upon restarting the application. I've updated the code to something that works for me, both going in & out of the map and exiting and restarting the application, I'm not too happy with the try-catch bit, but it seem to work well enough. When looking at the stack trace it occurred to me that I could just check if the map fragment is in the FragmentManager, no need for the try-catch block, code updated.

More edits: Turns out you need that try-catch after all. Just checking for the map fragment turned out not to work so well after all. Blergh.

这篇关于重复ID,标签空,或父ID与另一个片段com.google.android.gms.maps.MapFragment的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆