在Android中显示隐藏片段


98

我正在开发包含2个片段的应用程序,我想根据需要显示hide。以下代码提供了我的问题的简单示例。这个简单的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
        }

为什么需要设置容器的可见性?它应该在不设置可见性的情况下工作。
Andrii Chernenko 2013年

确切地说,它应该在没有容器可见性的情况下工作,但不能工作。请与我分享简单的工作示例。然后我会知道我在哪里。
abidkhan303

1
我的猜测是,您每次尝试显示/隐藏片段的不同实例。当您添加片段时(顺便说一下,我看不到这段代码),将其与标签一起添加,然后由该标签进行检索(而不是尝试存储对其的引用)。那可能就是您所缺少的。
Andrii Chernenko

Answers:


158

不要搞乱容器的可见性标志-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();

5
为什么建议您不要直接弄乱这些标志?(我并不是在反对您的建议,只是想了解它。)
Ellen Spertus 2014年

1
是的,我在您的原始邮件中看到了。我希望您可以为额外的开销添加理由。同时,我发现了一些东西,例如添加到后堆栈的选项。
Ellen Spertus

2
这很容易出错,因为您可以在低级api和高级api上更改标志,并且如果不小心(即标志不同步),则可能是在追寻奇怪的错误。因此,建议使用片段管理器隐藏和显示片段。
努曼萨拉蒂2014年

@numansalati嗨,有什么了兼容性(从支持库)的版本android.R.animator.fade_in,和android.R.animator.fade_out
安慰

1
使用容器,您可以将其设置为SHOW,HIDE或GONE。隐藏片段时没有GONE选项。
Stealth Rabbi

57

此外,您可以在一个片段中执行操作(例如,在获取服务器数据失败时):

 getView().setVisibility(View.GONE);

11
Fragment是Object的子级,而不是View的子级,因此无法调用:fragment.setVisibility(View.INVISIBLE);
AndroidGeek

8
Arià提出了一些不同的建议,建议从该片段中获取视图并将其可见性设置为消失。
2014年

10
细心的getView()可能是null当它尚未初始化。
TWiStErRob

22

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

// 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了解更多信息。我希望我能帮助任何人。即使这是一个古老的问题。


1
所以您还必须拥有另外两个方法,例如displayFragmentB()和displayFragmentC()吗?
temirbek

是的@temirbek,您可以仅遵循displayFragmentA()方法的实现方式。
mangu23

1
如果一个活动中有很多片段(两个或更多),并且您正在使用上述方法,请使用this。编写和阅读起来会更容易。
马克西姆·克劳德

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

1
正确的是ft.setCustomAnimations(android.R.anim.fade_in,android.R.anim.fade_out);
Webserveis

8

试试这个:

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

2

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

<LinearLayout style="@style/StHorizontalLinearView"
    >

    <fragment
        android:layout_width="match_parent"
        android:layout_height="390dp"
        android:layout_alignParentTop="true"
        />

</LinearLayout>

0

这对我有用

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();

0

这里的答案是正确的,我喜欢@Jyo的“显示和隐藏片段实现”的想法,除了他目前拥有的方式会在第一次运行时隐藏片段,因此我添加了一个细微的变化,即添加了我的“检查并显示”片段(如果尚未存在)

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

0
final Fragment fragment1 = new fragment1();
final Fragment fragment2 = new fragment2();
final FragmentManager fm = getSupportFragmentManager();
Fragment active = fragment1;

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

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


0

我可能为时已晚,但将来可能对某人有所帮助。
这个答案是对mangu23 答案的修改,
我只添加了一个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而不必重复ifdisplayFragment版本中的语句。
我希望有人会觉得有用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.