Показати приховати фрагмент в android


99

Я розробляю додаток, яке містить 2 фрагменти, і я хочу показати сховати відповідно до своїх потреб. Наступний код має простий приклад моєї проблеми. Ця проста фрагментаційність містить 1 кнопку та один фрагмент списку.

Цей простий приклад працює бездоганно. але я не задоволений фрагментом show hide. Якщо видалити 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
Я припускаю, що ви намагаєтеся щоразу показувати / приховувати різні екземпляри фрагментів. Коли ви додаєте свій фрагмент (до речі, я не бачу цей фрагмент коду), додайте його за допомогою тегу, а потім отримайте за цим тегом (замість того, щоб намагатися зберегти посилання на нього). Це може бути те, чого вам не вистачає.
Андрій Черненко

Відповіді:


159

Не возитися з прапорцями видимості контейнера - 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 високого рівня, і якщо ви не будете обережні (тобто прапори не синхронізуються), ви можете переслідувати дивні помилки. Ось чому рекомендується використовувати менеджер фрагментів, щоб приховати та показати ваші фрагменти.
numan salati

@numansalati Привіт, чи існує версія сумісності (з бібліотеки підтримки) android.R.animator.fade_inта android.R.animator.fade_out?
Заспокоєння

1
За допомогою контейнера ви можете встановити для нього ПОКАЗАТИ, ПРИКРИТИ або ВІДХОДИТИ. Немає опції GONE при приховуванні фрагмента.
Stealth Rabbi

57

Крім того, ви можете зробити у фрагменті (наприклад, коли не вдалося отримати дані сервера):

 getView().setVisibility(View.GONE);

11
Фрагмент є дочірнім об'єктом, а не перегляду, тому не можна викликати: fragment.setVisibility (View.INVISIBLE);
AndroidGeek

8
Аріа пропонує щось інше, пропонує отримати вигляд з цього фрагмента і зменшити його видимість.
AlvaroSantisteban

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
Якщо у вас багато фрагментів в одній діяльності (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 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.