在android中显示隐藏片段

Posted

技术标签:

【中文标题】在android中显示隐藏片段【英文标题】:Show hide fragment in android 【发布时间】:2012-12-30 03:11:47 【问题描述】:

我正在开发包含 2 个片段的应用程序,我想根据需要显示隐藏。以下代码有我的问题的简单示例。 这个简单的 Fragmentactivity 包含 1 个按钮和一个 listfragment。

这个简单的例子完美无缺。但我对显示隐藏片段不满意。如果你删除 layout.setVisibility(View.GONE);从代码然后 ft.hide(f);不会隐藏片段。事实上,我们不是在隐藏片段,而是在隐藏容器。

我的问题是,这是一种显示隐藏片段的方式吗?如果没有,请用经过测试的示例解释如何隐藏和显示片段,因为很多人都面临这个问题。

 public class MainActivity extends FragmentActivity implements OnClickListener 

        Fragment1 f;
        Button b;
        LinearLayout layout;
        Fragment myf;
        @Override
        public void onCreate(Bundle savedInstanceState)
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            b = (Button) findViewById(R.id.button1);
            layout = (LinearLayout) findViewById(R.id.ll);
            f = new Fragment1();
        

        @Override
        public void onClick(View v) 

            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);

            if (f.isHidden()) 
                ft.show(f);
                layout.setVisibility(View.VISIBLE);
                b.setText("Hide");
             else 
                ft.hide(f);
                b.setText("Show");
                layout.setVisibility(View.GONE);
            
            ft.commit();
            // TODO Auto-generated method stub
        

【问题讨论】:

为什么需要设置容器的可见性?它应该可以在不设置可见性的情况下工作。 确切地说,它应该在没有容器可见性的情况下工作,但它不起作用。请与我分享简单的工作示例。然后我就会知道我在哪里失踪了。 我的猜测是您每次都试图显示/隐藏不同的片段实例。当您添加片段时(顺便说一下,我没有看到这段代码)将其添加到标签中,然后通过该标签检索它(而不是尝试存储对它的引用)。这可能就是你所缺少的。 【参考方案1】:

不要弄乱容器的可见性标志 - FragmentTransaction.hide/show 会在内部为您做到这一点。

所以正确的做法是:

FragmentManager fm = getFragmentManager();
fm.beginTransaction()
          .setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
          .show(somefrag)
          .commit();

或者如果您使用的是 android.support.v4.app.Fragment

 FragmentManager fm = getSupportFragmentManager();
 fm.beginTransaction()
          .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out)
          .show(somefrag)
          .commit();

【讨论】:

为什么不建议直接弄乱标志? (我不是反对你的建议,只是想理解它。) 是的,我在您的原始邮件中看到了这一点。我希望您可以为额外的开销添加理由。与此同时,我发现了一些,比如添加到后台堆栈的选项。 这很容易出错,因为您可以在低级 api 和高级 api 上更改标志,如果您不小心(即标志不同步),您可能会遇到奇怪的错误。这就是为什么它推荐使用片段管理器来隐藏和显示你的片段。 @numansalati 嗨,android.R.animator.fade_inandroid.R.animator.fade_out 是否有任何兼容(来自支持库)版本? 使用容器,您可以将其设置为 SHOW、HIDE 或 GONE。隐藏片段时没有 GONE 选项。【参考方案2】:

另外,你可以在 Fragment 中做(例如当获取服务器数据失败时):

 getView().setVisibility(View.GONE);

【讨论】:

Fragment 是 Object 而不是 View 的子对象,因此无法调用:fragment.setVisibility(View.INVISIBLE); Arià 提出了一些不同的建议,建议从该片段中获取视图并将其可见性设置为消失。 小心getView() 可能是null 尚未初始化。 这会隐藏片段的视图,而不是片段本身【参考方案3】:

您好,您使用这种方法进行操作,一旦最初添加,所有片段都将保留在容器中,然后我们只是显示所需的片段并将其他片段隐藏在容器中。

// Within an activity
private FragmentA fragmentA;
private FragmentB fragmentB;
private FragmentC fragmentC;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (savedInstanceState == null) 
        fragmentA = FragmentA.newInstance("foo");
        fragmentB = FragmentB.newInstance("bar");
        fragmentC = FragmentC.newInstance("baz");
    



// Replace the switch method
protected void displayFragmentA() 
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    if (fragmentA.isAdded())  // if the fragment is already in container
        ft.show(fragmentA);
     else  // fragment needs to be added to frame container
        ft.add(R.id.flContainer, fragmentA, "A");
    
    // Hide fragment B
    if (fragmentB.isAdded())  ft.hide(fragmentB); 
    // Hide fragment C
    if (fragmentC.isAdded())  ft.hide(fragmentC); 
    // Commit changes
    ft.commit();

请参阅https://github.com/codepath/android_guides/wiki/Creating-and-Using-Fragments 了解更多信息。我希望我能帮助任何人。即使这是一个老问题。

【讨论】:

所以你必须有另外两个方法,比如 displayFragmentB() 和 displayFragmentC()? 是的@temirbek,您可以按照 displayFragmentA() 方法的实现方式。 如果您在一个活动中有很多片段(2个或更多)并且您正在使用上述方法,请使用this。它会更容易书写和阅读。【参考方案4】:
public void showHideFragment(final Fragment fragment)

    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.setCustomAnimations(android.R.animator.fade_in,
                    android.R.animator.fade_out);

    if (fragment.isHidden()) 
        ft.show(fragment);
        Log.d("hidden","Show");
     else 
        ft.hide(fragment);
        Log.d("Shown","Hide");                        
    

    ft.commit();

【讨论】:

正确的是 ft.setCustomAnimations(android.R.anim.fade_in,android.R.anim.fade_out);【参考方案5】:

试试这个:

MapFragment mapFragment = (MapFragment)getFragmentManager().findFragmentById(R.id.mapview);
mapFragment.getView().setVisibility(View.GONE);

【讨论】:

【参考方案6】:

我可能为时已晚,但它可以帮助将来的人。 这个答案是对mangu23answer的修改 我只添加了一个 for 循环以避免重复并在没有样板代码的情况下轻松添加更多片段。

我们首先需要一个应该显示的片段列表

public class MainActivity extends AppCompatActivity
    //...
    List<Fragment> fragmentList = new ArrayList<>();

然后我们需要用我们的片段填充它

@Override
protected void onCreate(Bundle savedInstanceState) 
    //...
    HomeFragment homeFragment = new HomeFragment();
    MessagesFragment messagesFragment = new MessagesFragment();
    UserFragment userFragment = new UserFragment();
    FavoriteFragment favoriteFragment = new FavoriteFragment();
    MapFragment mapFragment = new MapFragment();

    fragmentList.add(homeFragment);
    fragmentList.add(messagesFragment);
    fragmentList.add(userFragment);
    fragmentList.add(favoriteFragment);
    fragmentList.add(mapFragment);

而且我们需要一种方法来知道从列表中选择了哪个片段,所以我们需要getFragmentIndex函数

private int getFragmentIndex(Fragment fragment) 
    int index = -1;
    for (int i = 0; i < fragmentList.size(); i++) 
        if (fragment.hashCode() == fragmentList.get(i).hashCode())
            return i;
        
    
    return index;

最后,displayFragment 方法将如下所示:

private void displayFragment(Fragment fragment) 
        int index = getFragmentIndex(fragment);
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (fragment.isAdded())  // if the fragment is already in container
            transaction.show(fragment);
         else  // fragment needs to be added to frame container
            transaction.add(R.id.placeholder, fragment);
        
        // hiding the other fragments
        for (int i = 0; i < fragmentList.size(); i++) 
            if (fragmentList.get(i).isAdded() && i != index) 
                transaction.hide(fragmentList.get(i));
            
        
        transaction.commit();
    

这样,我们就可以调用displayFragment(homeFragment),例如 这将自动显示HomeFragment 并隐藏列表中的任何其他片段。 此解决方案允许您将更多片段附加到fragmentList,而无需在旧的displayFragment 版本中重复if 语句。 我希望有人会觉得这很有用。

【讨论】:

【参考方案7】:

从我的代码来看,与上面的解决方案相比,最简单的方法是定义一个包含片段的布局,然后您可以通过控制与一般视图对齐的布局属性来隐藏或取消隐藏片段。在这种情况下不需要额外的代码,并且片段的额外部署属性可以移动到外部布局。

<LinearLayout style="@style/StHorizontalLinearView"
    >

    <fragment
        android:layout_
        android:layout_
        android:layout_alignParentTop="true"
        />

</LinearLayout>

【讨论】:

【参考方案8】:
final Fragment fragment1 = new fragment1();
final Fragment fragment2 = new fragment2();
final FragmentManager fm = getSupportFragmentManager();
Fragment active = fragment1;

在 onCreate 中,在 setContentView 之后,我隐藏了两个片段并将它们提交给片段管理器,但我没有隐藏将作为 home 的第一个片段。

fm.beginTransaction().add(R.id.main_container, fragment2, "2").hide(fragment2).commit();
fm.beginTransaction().add(R.id.main_container,fragment1, "1").commit();
 @Override
    public void onClick(View v) 
        Fragment another = fragment1;
         if(active==fragment1)
          another = fragment2;
         
            fm.beginTransaction().hide(active).show(another).commit();
            active = another;

参考:https://medium.com/@oluwabukunmi.aluko/bottom-navigation-view-with-fragments-a074bfd08711

【讨论】:

【参考方案9】:

这对我有用

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        if(tag.equalsIgnoreCase("dashboard"))

            DashboardFragment dashboardFragment = (DashboardFragment)
                    fragmentManager.findFragmentByTag("dashboard");
            if(dashboardFragment!=null) ft.show(dashboardFragment);

            ShowcaseFragment showcaseFragment = (ShowcaseFragment)
                    fragmentManager.findFragmentByTag("showcase");
            if(showcaseFragment!=null) ft.hide(showcaseFragment);

         else if(tag.equalsIgnoreCase("showcase"))
            DashboardFragment dashboardFragment = (DashboardFragment)
                    fragmentManager.findFragmentByTag("dashboard");
            if(dashboardFragment!=null) ft.hide(dashboardFragment);

            ShowcaseFragment showcaseFragment = (ShowcaseFragment)
                    fragmentManager.findFragmentByTag("showcase");
            if(showcaseFragment!=null) ft.show(showcaseFragment);
        

        ft.commit();

【讨论】:

【参考方案10】:

这里的答案是正确的,我喜欢 @Jyo Whiff 的显示和隐藏片段实现的想法,除了他目前拥有的方式会在第一次运行时隐藏片段,所以我添加了一个轻微的变化,我添加了 isAdded检查并显示片段(如果还没有)

public void showHideCardPreview(int id) 
    FragmentManager fm = getSupportFragmentManager();
    Bundle b = new Bundle();
    b.putInt(Constants.CARD, id);
    cardPreviewFragment.setArguments(b);
    FragmentTransaction ft = fm.beginTransaction()
        .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
    if (!cardPreviewFragment.isAdded())
        ft.add(R.id.full_screen_container, cardPreviewFragment);
        ft.show(cardPreviewFragment);
     else 
        if (cardPreviewFragment.isHidden()) 
            Log.d(TAG,"++++++++++++++++++++ show");
            ft.show(cardPreviewFragment);
         else 
            Log.d(TAG,"++++++++++++++++++++ hide");
            ft.hide(cardPreviewFragment);
        
    

    ft.commit();
 

【讨论】:

以上是关于在android中显示隐藏片段的主要内容,如果未能解决你的问题,请参考以下文章

片段隐藏在Android中不起作用

在片段替换上显示/隐藏 Android 软键盘

如何在 Android 中显示和隐藏菜单项?

片段设计:通过在单个 Activity 中显示/隐藏片段来适应多种屏幕布局?

在Android Studio片段之间切换时地图片段不隐藏

仅在一个片段中隐藏状态栏并在其他片段中显示