Android Fragment没有找到ID的视图?

问题描述 投票:243回答:28

我有一个片段,我试图添加到视图中。

FragmentManager fragMgr=getSupportFragmentManager();
feed_parser_activity content = (feed_parser_activity)fragMgr
                                    .findFragmentById(R.id.feedContentContainer);
FragmentTransaction xaction=fragMgr.beginTransaction();

if (content == null || content.isRemoving()) {
    content=new feed_parser_activity(item.getLink().toString());
    xaction
        .add(R.id.feedContentContainer, content)
        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
        .addToBackStack(null)
        .commit();
    Log.e("Abstract", "DONE");
}

执行此代码时,我在调试中收到以下错误。

java.lang.IllegalArgumentException: No view found for id 0x7f080011 
   for fragment feed_parser_activity{41882f50 #2 id=0x7f080011}

feed_parser_activity是一个片段,设置为xml中的Fragment布局。 我正在使用FragmentActivity来托管持有feed_parser_layout的Fragment Layout。 我上面正确编码吗?

android android-fragments illegalargumentexception
28个回答
333
投票

我也遇到了这个问题,直到我意识到我在FragmentActivity的setContentView()方法的onCreate()中指定了错误的布局。

传入FragmentTransaction.add()的id,在你的情况下R.id.feedContentContainer,必须是setContentView()中指定的布局的子项。

你没有告诉我们你的onCreate()方法,所以也许这是同样的问题。


7
投票

我知道这已经在一个场景中得到了解答,但我的问题略有不同,我想我会分享以防其他人在我的鞋子里。

我在onCreate()内进行了一次交易,但此时视图树还没有被充气,所以你得到同样的错误。将交易代码放在onResume()中使一切运行正常。

因此,只需确保在视图树膨胀后运行您的事务代码!


7
投票

我有同样的问题,但我的问题是在方向改变时发生的。其他解决方案都没有奏效。事实证明,当我根据屏幕尺寸做两个或一个窗格布局时,我忘了从我的碎片中删除setRetainInstance(true);


6
投票

在Recycler View中使用Viewpager时,我遇到了一个令人讨厌的错误。我在特殊情况下面临的错误。我创建了一个带有Viewpager的RecyclerView的片段(使用FragmentStatePagerAdapter)。它运行良好,直到我在RecyclerView中单击一个Cell切换到不同的片段,然后使用Phone的硬件后退按钮导航回来并且App崩溃。

有趣的是,我在同一个RecyclerView中有两个Viewpage,两个距离大约5个单元(其他在屏幕上看不到,它已经关闭)。所以最初我只是将解决方案应用于第一个Viewpager并保留其他原样(Viewpager使用Fragments)。

当第一个查看寻呼机可见时,向后导航工作正常。现在,当我向下滚动到第二个然后更改片段并返回时,它崩溃了(同样的事情发生在第一个)。所以我不得不改变两个Viewpagers。

无论如何,请阅读下面的工作解决方案。崩溃错误如下:

java.lang.IllegalArgumentException: No view found for id 0x7f0c0098 (com.kk:id/pagerDetailAndTips) for fragment ProductDetailsAndTipsFragment{189bcbce #0 id=0x7f0c0098}

花了几个小时调试它。阅读完整的主题帖子,直到底部应用所有解决方案,包括确保我传递childFragmentManager。

没有任何效果。

最后,我没有使用FragmentStatePagerAdapter,而是扩展了PagerAdapter并在Viewpager中使用它而不使用片段。我相信一些有嵌套片段的BUG。无论如何,我们有选择。阅读......

以下链接非常有用:

Viewpager Without Fragments

链接可能会死,所以我在下面发布我实现的解决方案:

public class ScreenSlidePagerAdapter extends PagerAdapter {
private static final String TAG = "ScreenSlidePager";
ProductDetails productDetails;
ImageView imgProductImage;
ArrayList<Imagelist> imagelists;
Context mContext;

// Constructor
public ScreenSlidePagerAdapter(Context mContext,ProductDetails productDetails) {
    //super(fm);
    this.mContext = mContext;
    this.productDetails = productDetails;
}

// Here is where you inflate your View and instantiate each View and set their values
@Override
public Object instantiateItem(ViewGroup container, int position) {
    LayoutInflater inflater = LayoutInflater.from(mContext);
    ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.product_image_slide_cell,container,false);

    imgProductImage = (ImageView) layout.findViewById(R.id.imgSlidingProductImage);
    String url = null;
    if (imagelists != null) {
        url = imagelists.get(position).getImage();
    }

    // This is UniversalImageLoader Image downloader method to download and set Image onto Imageview
    ImageLoader.getInstance().displayImage(url, imgProductImage, Kk.options);

    // Finally add view to Viewgroup. Same as where we return our fragment in FragmentStatePagerAdapter
    container.addView(layout);
    return layout;
}

// Write as it is. I don't know much about it
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    container.removeView((View) object);
    /*super.destroyItem(container, position, object);*/
}

// Get the count
@Override
public int getCount() {
    int size = 0;

    if (productDetails != null) {
        imagelists =  productDetails.getImagelist();
        if (imagelists != null) {
            size = imagelists.size();
        }
    }
    Log.d(TAG,"Adapter Size = "+size);
    return size;
}

// Write as it is. I don't know much about it
@Override
public boolean isViewFromObject(View view, Object object) {

    return view == object;
}

}

希望这有用!!


5
投票

我的错误在于FragamentTransaction

我正在做这个t.replace(R.layout.mylayout);而不是t.replace(R.id.mylayout);

区别在于一个是布局,另一个是layout(id)的引用


5
投票

使用嵌套片段

通过使用getChildFragmentManager()而不是getActivity.getSupportFragmentManager()解决了崩溃java.lang.IllegalArgumentException:找不到我的id视图。


4
投票

以防有人犯了同样的愚蠢错误;检查您是否在某处覆盖了活动内容(即查找对setContentView的其他调用)

在我的情况下,由于粗心的复制和粘贴,我在我的片段中使用了DataBindingUtil.setContentView,而不是DataBindingUtil.inflate,这搞乱了活动的状态。


3
投票

我有同样的问题,让我发布我的代码,这样你就可以看到它,而不是做我做过的同样的事情。

@Override
protected void onResume()
{
    super.onResume();

    fragManager = getSupportFragmentManager();

    Fragment answerPad=getDefaultAnswerPad();
    setAnswerPad(answerPad);
    setContentView(R.layout.abstract_test_view);
}
protected void setAnswerPad(AbstractAnswerFragment pad)
{
    fragManager.beginTransaction()
        .add(R.id.AnswerArea, pad, "AnswerArea")
        .commit();
    fragManager.executePendingTransactions();
}

请注意,我在setContentView之前设置了碎片。糟糕!


3
投票

此页面似乎是发布有关Fragment IllegalArgumentException的建议的良好中心位置。这是你可以尝试的另外一件事。这最终对我有用:

我忘记了我有一个单独的横向布局文件。我在那里添加了我的FrameLayout容器后,片段也起作用了。


另外,如果您已经尝试过此页面上建议的所有其他内容(以及整个互联网)并且已经将您的头发拉了几个小时,请考虑将这些恼人的片段转储并返回到旧的标准布局。 (这实际上就是我在最终发现问题时正在做的事情。)你仍然可以使用容器概念。但是,您可以使用xml include标记来填充它与您在片段中使用的相同布局,而不是使用片段填充它。您可以在主布局中执行以下操作:

<FrameLayout
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <include layout="@layout/former_fragment_layout" />

</FrameLayout>

其中former_fragment_layout是您尝试在片段中使用的xml布局文件的名称。有关更多信息,请参阅Re-using Layouts with include


2
投票

在我的情况下,我在Recycler视图项中有一个SupportMapFragment(我使用较低的开销“liteMode”,这使得地图显示为非交互式,几乎像静态图像)。我正在使用正确的FragmentManager,一切似乎工作正常...有一个小列表。一旦项目列表超过屏幕高度,我滚动时就开始遇到此问题。

原来,这是因为我在一个视图中注入一个动态的SupportMapFragment,它位于另一个片段中,以解决我在尝试在XML中静态声明它时遇到的一些问题。因此,一旦视图附加到窗口,即在屏幕上可见,片段占位符布局只能用实际片段替换。所以我把我的代码用于初始化SupportMapFragment,执行Fragment替换,并在onAttachedToWindow事件中调用getMapAsync()。

我忘记做的是确保我的代码没有运行两次。即在onAttachedToWindow事件中,检查我的动态SupportMapFragment在尝试创建它的新实例并执行Fragment替换之前是否仍为null。当项目离开RecyclerView的顶部时,它会从窗口中分离,然后在您向后滚动时重新附加,因此会多次触发此事件。

一旦我添加了空检查,每个RecyclerView项目只发生一次,问题就消失了! TL; DR!


1
投票

当我尝试用onCreateView()中的片段替换视图时遇到了这个问题。像这样:

public class MyProjectListFrag extends Fragment {


    private MyProjectListFragment myProjectListFragment;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        FragmentManager mFragmentManager = getFragmentManager();
        myProjectListFragment = new MyProjectListFragment();
        mFragmentManager
                .beginTransaction()
                .replace(R.id.container_for_my_pro_list,
                        myProjectListFragment, "myProjectListFragment")
                .commit();
    }

它告诉我

11-25 14:06:04.848: E/AndroidRuntime(26040): java.lang.IllegalArgumentException: No view found for id 0x7f05003f (com.example.myays:id/container_for_my_pro_list) for fragment MyProjectListFragment{41692f40 #2 id=0x7f05003f myProjectListFragment}

然后我修复了这个问题,将replace放入onActivityCreated()。像这样:

public class MyProjectListFrag extends Fragment {

    private final static String TAG = "lch";

    private MyProjectListFragment myProjectListFragment;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        return inflater
                .inflate(R.layout.frag_my_project_list, container, false);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onActivityCreated(savedInstanceState);

        FragmentManager mFragmentManager = getFragmentManager();
        myProjectListFragment = new MyProjectListFragment();
        mFragmentManager
                .beginTransaction()
                .replace(R.id.container_for_my_pro_list,
                        myProjectListFragment, "myProjectListFragment")
                .commit();

    }
  1. 你必须在onCreateView()中返回一个视图,以便以后可以替换它
  2. 您可以在片段生命周期的以下函数中对此视图进行任何操作,如qazxsw poi

希望这可以帮助!


237
投票

嵌套Fragments并使用getSupportFragmentManager()而不是getChildFragmentManager()添加它们时也会发生此错误。


1
投票

当您从另一个片段中调用片段时,会发生这种情况。

使用 :

onActivityCreated()

1
投票

我修复了这个bug,我使用getActivity().getSupportFragmentManager().beginTransaction(); 替换commitNow()

commit()

mFragment.getChildFragmentManager() .beginTransaction() .replace(R.id.main_fragment_container,fragment) .commitNowAllowingStateLoss(); 是一种同步方法,commitNow方法是一种异步方法。


1
投票

在我的情况下,当我为同一个布局元素(片段占位符)使用不同的id时,抛出了这个异常,同时为不同的Build Variants使用了几个。出于某种原因,当你第一次更换片段时,它的效果非常好,但是如果你再试一次,你会得到这个例外。因此,如果您有不同的Build Variants布局,请确保使用相同的ID。


0
投票

如果您尝试使用commit()替换片段中的片段,但您不会膨胀可能导致问题的父片段。

在BaseFragment.java中fragmentManager

OnCreateView

用膨胀正确的片段布局替换if (savedInstanceState == null) { getFragmentManager().beginTransaction() .replace(R.id.container, new DifferentFragment()) .commit(); } return super.onCreateView(inflater, container, savedInstanceState);

super.onCreateView(inflater, container, savedInstanceState);

0
投票

在创建活动时进行片段事务时我遇到了同样的问题。

核心问题是 return inflater.inflate(R.layout.base_fragment, container, false); - 视图树尚未膨胀。但是他的解决方案不起作用 - 在onResume,onPostCreate等中也有相同的例外。

解决方案是添加回调容器片段,以便在准备就绪时发出信号:

Nick has already pointed out

然后在活动中:

public class MyContainerFragment extends Fragment {
    public static interface Callbacks {
        void onMyContainerAttached();
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        Log.d(TAG, "--- onAttach");
        ((Callbacks) activity).onMyContainerAttached();
    }

    //... rest of code
}

0
投票

在我的例子中,我使用片段类文件来声明listview适配器类。我刚刚为公共适配器类使用了不同的文件,错误消失了。


0
投票

如果你没有把public class MainActivity extends Activity implements MyContainerFragment.Callbacks { @Override public void onMyContainerAttached() { getFragmentManager() .beginTransaction() .replace(R.id.containerFrame, new MyFragment()) .commit(); } //... } 放在你的<include layout="@layout/your_fragment_layout"/>中,也会发生这个问题


0
投票

当两个具有相同ID的片段中有两个视图时,也会发生这种情况


0
投票

我遇到了同样的问题,因为我在将容器布局添加到活动之前尝试添加片段。


58
投票

解决方案是使用getChildFragmentManager()

而不是getFragmentManager()

从片段调用时如果从活动中调用方法,则使用getFragmentManager()

这将解决问题。


28
投票

我有这个问题(在代码中构建我的UI时)它是由我的ViewPager(显示Fragments)没有ID设置引起的,所以我只是使用pager.setID(id)然后它工作。

This page帮我解决了这个问题。


25
投票

我见过的另一个场景。如果您使用嵌套片段,请说片段中的ViewPager,其页面也是片段。

当您在内部片段(ViewPager的页面)中执行Fragment事务时,您将需要

FragmentManager fragmentManager = getActivity().getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

getActivity()是这里的关键。 ...


12
投票

我在另一个类似于这个问题的线程上读到的答案,当我遇到这个问题时,这个问题涉及布局xml。

你的logcat说“找不到id 0x7f080011的视图”。

打开gen->package->R.java->id,然后寻找id 0x7f080011

当我遇到这个问题时,这个id属于我的FrameLayout文件中的activity_main.xml

FrameLayout没有ID(没有声明android:id = "blablabla")。

确保所有布局中的所有组件都具有ID,尤其是logcat中引用的组件。


11
投票

如果您传递给FragmentTransaction.replace(int ID, fragment)的布局ID存在于其他正在膨胀的布局中,也会发生此异常。确保布局ID是唯一的,它应该工作。


11
投票

当我从com.android.support:support-v4:21.0.0升级到com.android.support:support-v4:22.1.1时,我收到了这个错误。

我不得不改变我的布局:

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

对此:

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

    <FrameLayout
        android:id="@+id/container_frame_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>

</FrameLayout> 

所以布局必须有一个子视图。我假设他们在新库中强制执行此操作。


10
投票

在我的情况下,我试图显示包含寻呼机的DialogFragment,当FragmentPagerAdapter尝试将碎片添加到寻呼机时抛出此异常。根据howettl的回答,我猜这是由于Pager父节点不是我的FragmentActivity中的setContentView()中的视图集。

我为解决这个问题所做的唯一改变是创建FragmentPagerAdapter传入一个通过调用getChildFragmentManager()获得的FragmentMager,而不是像往常一样调用getFragmentManager()获得的那个。

    public class PagerDialog extends DialogFragment{

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.pager_dialog, container, false);

        MyPagerAdapter pagerAdapter = new MyPagerAdapter(getChildFragmentManager());
        ViewPager pager = (ViewPager) rootView.findViewById(R.id.pager);
        pager.setAdapter(pagerAdapter);

        return rootView;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.