Показать скрытый фрагмент в android


100

Я разрабатываю приложение, которое содержит 2 фрагмента, и я хочу показать скрытие в соответствии с моими потребностями. В следующем коде есть простой пример моей проблемы. Это простое действие Fragmentactivity содержит 1 кнопку и один фрагмент списка.

Этот простой пример работает безупречно. но меня не устраивает фрагмент показать скрыть. Если вы удалите 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
        }

Зачем нужно настраивать видимость контейнера? Он должен работать без настройки видимости.
— Андрей Черненко

Собственно, он должен работать без видимости контейнера, но не работает. Пожалуйста, поделитесь со мной простым рабочим примером. Тогда я бы знал, где мне не хватает.
— abidkhan303

1
Я предполагаю, что вы каждый раз пытаетесь показать / скрыть разные экземпляры фрагмента. Когда вы добавляете свой фрагмент (кстати, я не вижу этот фрагмент кода), добавьте его с помощью тега, а затем извлеките его с помощью этого тега (вместо попытки сохранить ссылку на него). Это может быть то, что вам не хватает.
— Андрей Черненко

Ответы:


160

Не связывайтесь с флагами видимости контейнера - 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
Почему вы не рекомендуете напрямую связываться с флагами? (Я не оспариваю вашу рекомендацию, просто пытаюсь ее понять.)
— Эллен Спертус

1
Да, я прочитал это в вашем исходном сообщении. Я надеялся, что вы сможете оправдать дополнительные накладные расходы. Тем временем я обнаружил некоторые, например, возможность добавления в задний стек.
— Эллен Спертус

2
Это подвержено ошибкам, потому что вы можете изменить свои флаги на низком уровне api и высоком уровне api, и если вы не будете осторожны (т.е. флаги не синхронизируются), вы можете преследовать странные ошибки. Вот почему рекомендуется использовать диспетчер фрагментов, чтобы скрыть и показать ваши фрагменты.
— Нуман Салати

@numansalati Привет, есть ли совместимая (из библиотеки поддержки) версия android.R.animator.fade_inи android.R.animator.fade_out?
— Solace

1
С помощью контейнера вы можете установить его на ПОКАЗАТЬ, СКРЫТЬ или УДАЛИТЬ. При скрытии фрагмента нет опции GONE.
— Стелс раввин,

58

Кроме того, вы можете сделать во фрагменте (например, при сбое получения данных сервера):

 getView().setVisibility(View.GONE);

11
Фрагмент является дочерним элементом объекта, а не представления, поэтому нельзя вызывать: fragment.setVisibility (View.INVISIBLE);
— AndroidGeek

8
Ария предлагает нечто иное, предлагает получить вид из этого фрагмента и отключить его видимость.
— AlvaroSantisteban

10
Тщательное getView()может быть , nullкогда он еще не инициализирован.
— TWiStErRob 01

23

Привет, вы делаете это, используя этот подход, все фрагменты останутся в контейнере после первоначального добавления, а затем мы просто открываем нужный фрагмент и скрываем другие внутри контейнера.

// 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
Если у вас много фрагментов в одном действии (2 или более) и вы используете описанный выше метод, воспользуйтесь этим . Будет легче писать и читать.
— Максим Клод

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

Из моего кода, по сравнению с приведенным выше решением, самый простой способ - определить макет, содержащий фрагмент, затем вы можете скрыть или отобразить фрагмент, контролируя атрибут макета, который соответствует общему способу просмотра. В этом случае дополнительный код не требуется, и дополнительные атрибуты развертывания фрагмента могут быть перемещены во внешний макет.

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

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без повторения ifоператоров в старой displayFragmentверсии.
Надеюсь, кому-то это пригодится.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.