Android:你能嵌套 Fragments 吗?

Posted

技术标签:

【中文标题】Android:你能嵌套 Fragments 吗?【英文标题】:Android: Can you nest Fragments? 【发布时间】:2011-09-07 11:36:39 【问题描述】:

是否可以将Fragment 粘贴到另一个Fragment 的布局中?有人试过吗?

【问题讨论】:

你试过了吗?发生了什么? 我没试过。我希望别人有。 我和米奇在一起。也许我变老了,但在我那个时代,人们尝试了一些事情来看看发生了什么。如果你有一个想法,那就付诸实践 - 100% 纯金从经验中学习。 我想我会成为豚鼠。我会让你知道结果。 Fragment Inside Fragment的可能重复 【参考方案1】:

终于! android 4.2 更新默认支持嵌套片段,也兼容: Official NestedFragments。更重要的是,在v4 support library的最新第11版中宣布了对嵌套Fragments的支持!

【讨论】:

这是现在正式的正确答案。感谢分享,我不知道这个更新。 在片段中只需调用 getChildFragmentManager() 而不是 getFragmentManager。使用旧版本的兼容性库解决了我在嵌套片段时遇到的问题【参考方案2】:

不,片段当前不在层次结构中。试图将一个片段嵌入到另一个片段中可能会导致问题,而且往往很微妙。

【讨论】:

与视图在屏幕上的显示方式有关的问题?还是和fragment的生命周期有关? 我将其指定为答案,因为似乎不建议这样做。这样做时我确实遇到了问题,即使这样做是“可能的”。 我不会把它作为答案,因为它在技术上是错误的,你可以。仅仅因为它不被推荐并不意味着你不能。我让它可靠地工作。 我们不保证您的应用将来会继续正常运行。 @hackbod 您能否为我们提供一些关于片段不在层次结构中的详细信息,以及为什么嵌套片段可能会导致问题?【参考方案3】:

编辑:从 ACLv11 开始,仅当您动态地 replace(...) ViewPagers 时才需要这样做。

是的,你可以,但有些方法很痛苦,但我什至嵌入了 FragmentViewPagers。

如果您嵌入 XML,那么当布局膨胀时,您将没有问题。

如果您将片段动态嵌入到另一个片段中,那么您会遇到问题!虽然有可能。

通常涉及发布到一个处理程序,该处理程序在当前片段转换之后执行,然后开始另一个,这样您可以很容易地嵌入片段。但这会导致其他问题,因此您必须小心如何实施。

FoodTestFeast 已嵌入 ViewPager,可动态移除和添加。

My Base FragmentViewPager - 包含视图分页器的片段(具有 FragmentPagerAdapter)

我还没有看到任何使用它的崩溃,但如果其他人这样做,请告诉我。

/**
 * @project FoodFeast
 * @author chris.jenkins
 * @created Dec 28, 2011
 */
package couk.jenxsolution.food.ui.fragments;

import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.viewpagerindicator.TabPageIndicator;

import couk.jenxsolution.food.R;
import couk.jenxsolution.food.app.FoodApplication;

/**
 * @author chris.jenkins
 */
public class QuizPagerBaseFragment extends QuizBaseFragment


    // Data
    private FragmentStatePagerAdapter mAdapter = null;

    // Views
    private int layoutRes;
    private View mRootView;
    private ViewPager mPager;
    private TabPageIndicator mIndicator;

    // Handlers
    private final Handler handler = new Handler();
    private Runnable runPager;
    private boolean mCreated = false;

    /**
     * @see android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater,
     *      android.view.ViewGroup, android.os.Bundle)
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        mRootView = inflater.inflate(layoutRes, container, false);
        mPager = (ViewPager) mRootView.findViewById(R.id.pager);
        mPager.setOffscreenPageLimit(2);
        mIndicator = (TabPageIndicator) mRootView.findViewById(R.id.indicator);
        mIndicator.setTypeface(FoodApplication.getInstance().getTFs().getTypeFaceBold());

        return mRootView;
    

    /**
     * @see android.support.v4.app.Fragment#onActivityCreated(android.os.Bundle)
     */
    @Override
    public void onActivityCreated(Bundle savedInstanceState)
    
        super.onActivityCreated(savedInstanceState);
        if (runPager != null) handler.post(runPager);
        mCreated = true;
    

    /**
     * @see android.support.v4.app.Fragment#onPause()
     */
    @Override
    public void onPause()
    
        super.onPause();
        handler.removeCallbacks(runPager);
    

    /**
     * Set the ViewPager adapter from this or from a subclass.
     * 
     * @author chris.jenkins
     * @param adapter
     */
    protected void setAdapter(FragmentStatePagerAdapter adapter)
    
        mAdapter = adapter;
        // mAdapter.notifyDataSetChanged();
        runPager = new Runnable() 

            @Override
            public void run()
            
                mPager.setAdapter(mAdapter);
                mIndicator.setViewPager(mPager);
                // mAdapter.notifyDataSetChanged();
                mIndicator.setVisibility(View.VISIBLE);
            
        ;
        if (mCreated)
        
            handler.post(runPager);
        
    

    /**
     * Has to be set before onCreateView
     * 
     * @author chris.jenkins
     * @param layoutRes
     */
    protected void setLayoutRes(int layoutRes)
    
        this.layoutRes = layoutRes;
    


仅供参考,您的布局需要如下所示(或类似): 注意指标 = 消失!

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

    <com.viewpagerindicator.TabPageIndicator
        android:id="@+id/indicator"
        android:layout_
        android:layout_ 
        android:visibility="gone"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_
        android:layout_
        android:layout_weight="1" />

</LinearLayout>

【讨论】:

当然,我会从我的项目中为您挖掘一个。我会更新答案。 @Chris.Jenkins 我在 FragmentPageviewer 中有一个片段。片段包含 4 个值。我想当我点击该值时它会添加或替换另一个片段。这可能吗? @parag 用更多的经验打开另一个问题,我会尝试回答这个问题:) @Chris.Jenkins 感谢您的支持。终于找到解决方案了..我采取了另一个 Viewpager 并创建它的可见性可见,不可见。 @Chris.Jenkins,您是否看到与数据库游标一起使用的类似内容(片段内的视图分页器片段)?我希望找到一些带有数据库游标的 ViewPager 的像样的例子,但找不到,也没有在另一个片段中找到很多关于片段的信息 - 所以将它们结合起来似乎是一项艰巨的任务......【参考方案4】:

解决无法使用嵌套片段的一种聪明方法是同时使用 v4 和原生片段。 它有效(我在许多应用程序中使用它),在某些情况下,我们需要绕过这个限制。

显然,在activity中你可以使用getFragmentManager()或者getSupportFragmentManager()来区分2组fragment。

可能是不推荐使用它,但它解决了我很多情况。

【讨论】:

以上是关于Android:你能嵌套 Fragments 吗?的主要内容,如果未能解决你的问题,请参考以下文章

Android Fragment使用 嵌套Fragments (Nested Fragments) 的使用及常见错误

使用 Fragments 进行 Android 搜索

你能嵌套html表单吗?

你能嵌套html表单吗?

你能避免使用 Promises 完全嵌套吗? [复制]

iOS 中深度嵌套的视图层次结构可以吗?