2015-04-06 2 views
9

Как могла часть моего кода знать об экземпляре фрагмента, видимого на экране?Как определить, когда на экране появляется фрагмент?

Следующий фрагмент объяснит мой вопрос.

public class MyApp extends Application { 
public static final String TAG = MyApp.class.getSimpleName(); 

@Override 
public void onCreate() { 
    super.onCreate(); 
    registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { 
     ... 

     @Override 
     public void onActivityResumed(Activity activity) { 
      Log.d(TAG, activity.getClass().getSimpleName() + " is on screen"); 
     } 

     @Override 
     public void onActivityStopped(Activity activity) { 
      Log.d(TAG, activity.getClass().getSimpleName() + " is NOT on screen"); 
     } 

     ... 
    }); 
} 

Здесь я могу отслеживать, когда на экране появляется какое-либо действие в моем приложении. Есть ли способ расширить этот подход на фрагментах?

Что-то вроде Activity.getFragmentManager().registerFragmentLifecycleCallbacks();

UPD. Я ничего не знаю о реализации действий, они вообще используют фрагменты и как они их используют (инъекция через xml, ViewPager и т. Д.) Единственное, что у меня есть в моем классе, - это контекст приложения. Предположим, что реализация Activity и Fragment - это черные ящики, и я не могу вносить никаких изменений.

+0

Если вызван метод onResume вашего фрагмента, это означает, что ваш фрагмент виден для пользователя. – Toppers

+0

Ну ... Скажем, реализация Фрагмента - это черный ящик, и у меня нет возможности добавлять несколько строк кода. –

+0

Итак, ваш те, кто подталкивает невосприимчивый дизайн приложения. – danny117

ответ

0

Перехват onWindowFocusChanged() в своей деятельности и распространение этого интересующего фрагмента.

+0

Пожалуйста, загляните в раздел UPD моего вопроса. –

+0

Я считаю, что единственный надежный механизм, который должен сделать это, опирается на метод onWindowFocusChanged() активности, таким образом разоблачая это событие через созданный вами интерфейс. Однако вам все равно нужно подключить интерфейс к самим действиям. –

0

Попробуйте

private Boolean isFragmentVisible() 
    { 
     if(getFragmentManager().findFragmentByTag("TAG") != null && getFragmentManager().findFragmentByTag("TAG").isVisible()) 
     { 
     //The fragment is visible 
     return true; 
     } 
     return false; 
    } 

Альтернативный способ

private Boolean isFragmentVisible() 
    { 
     return getFragmentManager().findFragmentByTag("TAG") != null && getFragmentManager().findFragmentByTag("TAG").isVisible(); 
    } 
+0

К сожалению, я ничего не знаю о тегах или идентификаторах, которые использовались во время транзакций фрагментов. Я смотрю что-то вроде «Observer» жизненного цикла фрагмента. Насколько я понял эту проблему, я ничего не нашел. Во всяком случае, это не значит, что решение не существует :) –

0

Вы можете знать следующее со встроенным методом, который называется «onActivityCreated (Bundle)» этот метод говорит, что фрагмент был создан таким образом, вам узнайте, что фрагмент появляется на экране Click here for reference Надеюсь, он поможет

5

В вашем фрагменте переопределить onHiddenChanged(...)

@Override 
public void onHiddenChanged(boolean hidden) { 
    super.onHiddenChanged(hidden); 
    if (hidden) { 
     Log.d(TAG, ((Object) this).getClass().getSimpleName() + " is NOT on screen");   
    } 
    else 
    { 
     Log.d(TAG, ((Object) this).getClass().getSimpleName() + " is on screen"); 
    } 
} 

Надеюсь, что эта работа для вас!

+0

Он работает. Great –

0

Я просмотрел все, что доступно, без использования базы Fragment или Activity класс, но не смог найти. Я сделал реализацию, которая обеспечивает базовую (onAdded/onRemoved) функциональность для всех фрагментов в вашем приложении. Конечно, можно продлить его, чтобы сообщить текущее состояние фрагмента (onAttach, onResume, onPause, onDetach, ...).

Вы можете найти код вместе с образцом здесь: https://github.com/Nillerr/FragmentLifecycleCallbacks

Он работает как для не-поддержки библиотеки фрагментов и библиотеки поддержки фрагментов с помощью различных реализаций. Класс библиотеки поддержки более безопасен в использовании и должен работать лучше, потому что не поддерживающий использует Reflection для доступа к фрагментам, в то время как библиотека поддержки FragmentManager включает в себя метод getFragments().

0

Если вы устанавливаете фрагмент в свой вид, у вас, вероятно, есть контейнер, где он будет показан. Учитывая, что этот контейнер является, скажем, FrameLayout с id R.id.контейнер, вы можете сделать это:

Fragment f = fragmentManager.findFragmentById(R.id.container); 
if (f instanceof YourFragment) { 
    // TODO something when YourFragment is ready 
} 
0

Используйте так же, как деятельность

установлен флаг в классе приложения для проверки visiblity фрагмента, используйте ниже код в фрагменте

@Override 
     public void onStart() { 
      super.onStart(); 
      Log.e("Fragment is visible", "Fragment is visible"); 
Application Class.isFragmentShow = true; 
     } 

    @Override 
     public void onPause() { 
      super.onPause(); 
      Log.e("Fragment is not visible", "Fragment is not visible"); 

Application Class.isFragmentShow = false; 
     } 

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

MainFragment fragment = (MainFragment) fragmentManager.findFragmentByTag("MainFragment"); 
        fragment.setFilter(); 
+0

К сожалению, я не могу выполнять никаких модификаций фрагментов :(Более того, я знаю, что они представляют, их имена, теги транзакций и т. Д. Единственное решение, которое я вижу на данный момент, - создать кучу ' TrackableFragment' и обязывать разработчиков расширять их. Это самый простой и очевидный способ, но не самый изящный. –

5

Не касаясь кода Activity или Fragment и предполагая, что вы не знаете тег или макет, в который он помещен, очень мало того, что вы можете сделать. Лучшее, что я вижу, это то, что вы можете получить FragmentManager в обработчиках ActivityResumed и ActivityStopped (потому что здесь у вас есть ссылка на Activity) и примените BackstackChangedListener. Это предполагает, что вы используете стоп-кадр при смене фрагментов.

Проблема с тем, что вы просите, заключается в том, что вы хотите, чтобы обратные вызовы жизненного цикла для фрагментов на уровне приложения, когда у вас нет контроля над средними людьми, действия, которые уже голодают для обратных вызовов фрагментов. Они делают больше всего через свой FragmentManager и распространяют свои собственные обратные вызовы жизненного цикла вплоть до фрагментов, чтобы фрагменты работали надлежащим образом. Обратные вызовы onResume и onPause во фрагментах возникают только тогда, когда они сначала создаются или когда Activity испытывает эти обратные вызовы. Существует только один обратный вызов жизненного цикла для фрагментов в действиях, onAttachFragment, который, если вы можете переопределить, даст вам ссылки на фрагменты, прикрепленные к Activity. Но вы сказали, что не можете изменить действие или фрагмент, и вы хотите знать, когда отображаются фрагменты.

Итак, если вы не используете заднюю часть, я не думаю, что есть способ сделать то, что вы хотите.

+0

Я боюсь, что это так. Грустно, но это правда. Пока я не найду какое-то решение) –

0

Предоставляет ли этот интерфейс что-нибудь полезное для вас?

https://github.com/soarcn/AndroidLifecyle/blob/master/lifecycle/src/main/java/com/cocosw/lifecycle/FragmentLifecycleCallbacks.java

Это звучит как ваш лучший выбор, если вы не можете изменить собственный onResume() метод фрагмента является создать свой собственный интерфейс, который расширяет ActivityLifecycleCallbacks, затем поместить свой код протоколирования в методе onFragmentResumed(Fragment yourFragment).

Вы можете получить указатель на фрагмент, делая что-то вроде этого:

int yourFragmentId = 0; //assign your fragment's ID to this variable; Fragment yourFragment.getId(); 
     FragmentManager fm = activity.getFragmentManager(); 
     Fragment f = fm.findFragmentById(yourFragmentId); 
2

Для ввода фрагментов внутри деятельности я использую SlidingTabLayout, который использует Google. Внутри у вас есть ViewPager и некоторые Adapter для заполнения многих фрагментов. Прежде всего, вы должны положить this и this файлов в свой проект. Тогда here есть хороший учебник, как вы можете реализовать SlidingTabLayout.

1) После реализации SlidingTabLayout в вашей деятельности, вы можете определить, когда и который становится видимым Фрагмент деятельности:

mSlidingTabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 
     @Override 
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
      //Do nothing 
     } 
     @Override 
     public void onPageSelected(int position) { 
      if (position == 0) { 
       //Whenever first fragment is visible, do something 
      } else if (position == 1) { 
       //Whenever second fragment is visible, do something 
      } else if (position == 2) { 
       //Whenever third fragment is visible, do something 
      } else if (position == 3) { 
       //Whenever fourth fragment is visible, do something 
      } 
     } 
     @Override 
     public void onPageScrollStateChanged(int state) { 
      //Do nothing 
     } 
    }); 

2) Вы можете обнаружить, если фрагмент виден из самого фрагмента как я ответил here, однако это может дозвонились до того onCreateView() фрагмента, поэтому проверьте ответ в ссылке:

@Override 
public void setUserVisibleHint(boolean visible){ 
    super.setUserVisibleHint(visible); 
    if (visible){ 
     //when this Fragment is active, do something 
    } 
} 

3) Вы можете изменить также изменить цвет индикаторов каждой вкладки, как это от деятельности:

mSlidingTabLayout.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() { 
     @Override 
     public int getIndicatorColor(int position) { 
      if (position == 0) { 
       return getResources().getColor(R.color.orange); 
      } else if (position == 1) { 
       return getResources().getColor(R.color.redDimmed); 
      } else if (position == 2) { 
       return getResources().getColor(R.color.yellow); 
      } else if (position == 3) { 
       return getResources().getColor(R.color.green); 
      } else { 
       return getResources().getColor(R.color.redLight); 
      } 
     } 

     @Override 
     public int getDividerColor(int position) { 
      return getResources().getColor(R.color.defaultActionBarBg); 
     } 

    }); 
0

везде, где и хотят, чтобы проверить, если фрагмент виден или нет .. просто проверить isMenuVisible() значение. это метод фрагмента, который я использовал для проверки видимого фрагмента, когда мне нужно запустить некоторый HTTP-запрос из выбранного элемента Viewpager. надеюсь, что это поможет.

в моем случае я использовал этот метод в onActivityCreated().

+1

'isMenuVisible()' является частной (@hide), по крайней мере, с v25. – ypresto

0

В вашем методе переопределения фрагмента setMenuVisibility Если вы используете ViewPager и прокручиваете влево и вправо, этот метод вызывается, когда изменчивость фрагмента изменяется.

Вот пример из моего проекта

public abstract class DemosCommonFragment extends Fragment { 

    protected boolean isVisible; 

    public DemosCommonFragment() { 
    } 


    @Override 
    public void setMenuVisibility(boolean menuVisible) { 
     super.setMenuVisibility(menuVisible); 
     isVisible = menuVisible; 
     // !!! Do Something Here !!! 
    } 

} 
0

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

public class BaseFragment extends Fragment { 

private String fragmentName; 
private FragmentLifecycleCallbacks listener; 

public void registerCallBacks(String fragmentName){ 
    // handle the listener that implement 'MyApp' class 
try{ 
    listener = (FragmentLifecycleCallbacks) getActivity().getApplication(); 
    } catch (ClassCastException e) { 
     throw new ClassCastException("Application class must implement FragmentLifecycleCallbacks"); 
    } 
    // set the current fragment Name for the log 
    this.fragmentName = fragmentName; 
} 

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 
    if(listener!=null) { 
     listener.onAttachFragment(fragmentName); 
    } 
} 

@Override 
public void onResume() { 
    super.onResume(); 
    if(listener!=null) { 
     listener.onResumeFragment(fragmentName); 
    } 
} 

@Override 
public void onStop() { 
    super.onStop(); 
    if(listener!=null) { 
     listener.onStopFragment(fragmentName); 
    } 
} 

// 'MyApp' class needs implement this interface to handle all the fragments events 
public interface FragmentLifecycleCallbacks{ 
    void onStopFragment(String fragmentName); 
    void onResumeFragment(String fragmentName); 
    void onAttachFragment(String fragmentName); 
}} 

В классе 'MYAPP' реализовать интерфейс BaseFragment

public class MyApp extends Application implements BaseFragment.FragmentLifecycleCallbacks{ 

public static final String TAG = MyApp.class.getSimpleName(); 

@Override 
public void onCreate() { 
    super.onCreate(); 
} 


@Override 
public void onStopFragment(String fragmentName) { 
    Log.d(TAG, fragmentName + " is NOT on screen"); 
} 

@Override 
public void onResumeFragment(String fragmentName) { 
    Log.d(TAG, fragmentName + " is on screen"); 
} 

@Override 
public void onAttachFragment(String fragmentName) { 
    Log.d(TAG, fragmentName + " is attached to screen"); 
}} 

и теперь каждый осколок, что у вас есть необходимость распространяется 'BaseFragment' и зарегистрировать в глобальном слушателю

public class FragmentA extends BaseFragment { 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 

    View rootView = inflater.inflate(R.layout.fragment_simple, container, false); 
    // here register to the global listener 
    registerCallBacks(FragmentA.class.getName()); 

    return rootView; 
}} 

Надежда это помогает!

Смежные вопросы