Жизненный цикл фрагментов - какой метод вызывается show/hide?
Я использую следующий метод для переключения между фрагментами (в моем NavigationDrawer), показывая/скрывая их.
protected void showFragment(int container, Fragment fragment, String tag, String lastTag, boolean addToBackStack ) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
if ( lastTag != null && !lastTag.equals("")) {
Fragment lastFragment = fragmentManager.findFragmentByTag( lastTag );
if ( lastFragment != null ) {
transaction.hide( lastFragment );
}
}
if ( fragment.isAdded() ) {
transaction.show( fragment );
}
else {
transaction.add( container, fragment, tag );
}
if ( addToBackStack ) {
transaction.addToBackStack( tag );
}
transaction.commit();
// set the active tag
activeFragTag = tag;
}
Я не понимаю, какой метод жизненного цикла фрагментов вызывается, когда я показываю или скрываю его? (поскольку нет метода, такого как onShow() или onHide() im, не совсем уверен что использовать). Я хочу выполнить определенные действия при показе и скрытии определенного фрагмента.
Ответы
Ответ 1
Подобно жизненному циклу активности, Android вызывает onStart(), когда фрагмент становится видимым. onStop()
обычно вызывается, когда фрагмент становится невидимым, но его также можно вызвать позже.
В зависимости от вашего макета Android может вызывать onStart()
даже, когда ваш фрагмент еще не виден, но он принадлежит видимому родительскому контейнеру. Например, это справедливо для android.support.v4.view.ViewPager
, для чего требуется переопределить метод Fragment.setUserVisibleHint()
. В любом случае, если вам необходимо зарегистрировать/отменить регистрацию BroadcastReceivers или других слушателей, вы можете безопасно использовать методы onStart()
и onStop()
, потому что они будут вызываться всегда.
Примечание. Некоторые фрагментированные контейнеры могут содержать невидимые фрагменты. Чтобы справиться с этой ситуацией, вы можете переопределить Fragment.onHiddenChanged(boolean hidden)
. Согласно документации фрагмент должен быть как запущенным, так и видимым (не скрытым), чтобы быть видимым пользователю.
Обновление: Если вы используете android.support.v4.widget.DrawerLayout
, то фрагмент под ящиком остается включенным и видимым, даже когда ящик открыт. В этом случае вам нужно использовать DrawerLayout.setDrawerListener()
и прослушать обратные вызовы onDrawerClosed()
и onDrawerOpened()
.
Ответ 2
I @Переопределите этот метод и устраните мою проблему:
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (hidden) {
//do when hidden
} else {
//do when show
}
}
Ответ 3
вне курса вы можете @Overriede использовать следующий метод:
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
// Do your Work
} else {
// Do your Work
}
}
Ответ 4
Попробуйте этот код:
@Override
public void setUserVisibleHint(boolean visible)
{
super.setUserVisibleHint(visible);
if (visible && isResumed())
{
onResume();
}
}
@Override
public void onResume()
{
super.onResume();
if (!getUserVisibleHint())
{
return;
}
//Add your code this section
}
Ответ 5
Просто попробуйте это в setUserVisibleHint()
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser && getView() != null){
isActive = true;
init();
}else if(isVisibleToUser && getView() == null){
isActive = false;
}else{
isActive = true;
}
}
И создайте этот код в onCreateView():
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if(!isActive){
init();
}
}
Ответ 6
setUserVisibleHint
вызов до onCreateView
. и вы не можете обновить любой вид внутри setUserVisibleHint Я использую
public void setMenuVisibility(final boolean visible)
для видимости и onHiddenChanged() не вызывал в первый раз. он вызывает, когда скрытое состояние изменяется. потому что a fragment is visible by default
. Чтобы получить этот метод в первый раз, вам нужно позвонить mFragmentTransaction.hide(oldFragment)
, тогда он будет работать
Примечание
если вы хотите использовать подсказку и обновление setUserVisible View Использовать этот метод
Ответ 7
Другой способ вызова метода фрагмента, когда фрагмент видим, и вы используете viewpager в действии.
//прежде всего вы создаете интерфейс
public interface ShowFragmentVisible{
public void showFragment();}
//После этого этот интерфейс реализует внутри Fragment, подобный этому
public class MyFragment extends Fragment implements
ShowFragmentVisible {
@Override
public void showFragment() {
}
//Теперь ваша деятельность затем создает объект интерфейса и вызывает внутри, когда addOnViewpagerListener
ShowFragmentVisible showFragmentVisible;
@Override
public void onAttachFragment(Fragment fragment) {
super.onAttachFragment(fragment);
if (fragment instanceof ShowFragmentVisible) {
showFragmentVisible = (ShowFragmentVisible) fragment;
}
}
//your viewpager method
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
if (position==0){
showFragmentVisible.showFragment();
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
this is another alternative,but its work for me successfully
Ответ 8
Конечно, вы можете переопределить setUserVisibleHint
или setMenuVisibility
но если вам нужен доступ к Context
или Activity
, они там будут нулевыми! Существует другой метод onStart
который всегда имеет доступный контекст, но он будет вызываться только один раз при создании фрагмента, и если вы начнете перемещаться между фрагментами в пейджере, вы увидите, что он не будет вызван во втором представлении и после этого.
Итак... что теперь делать?
Обходной путь довольно прост, используйте onStart
для первого посещения и setMenuVisibility
для последующих. Ваш код, вероятно, будет выглядеть так:
Фрагмент класса:
public class MyFragmentClass{
private boolean isCurrentVisible = false;
...
@Override
public void onStart() {
super.onStart();
if (isCurrentVisible)
doSth();
}
@Override
public void setMenuVisibility(boolean menuVisible){
super.setMenuVisibility(menuVisible);
this.isCurrentVisible = menuVisible;
if(menuVisible && getContext() != null)
doSth();
}
Таким образом, Context
всегда будет доступен для doSth()
.
Ответ 9
Вы можете использовать onCreateView (или onActivityCreated) и onHiddenChanged. Используйте "onCreateView" для первого показа и "onHiddenChanged" для последующего показа. setMenuVisibility не вызывается при управлении транзакциями.
@Override
public View OnCreateView() {
// fragment will show first
}
@Override
public void onHiddenChanged(boolean hidden) {
if (!hidden) {
// fragment will show
}
else {
// fragment will hide
}
}
Ответ 10
Поведение пейджера в представлении фрагментов отличается от обычного контейнера фрагментов.
Попробуйте этот код:
boolean mIsVisibleToUser;
/**
* is visible to user
*/
public void show() {
//do when show
}
/**
* is invisible to user
*/
public void hide() {
//do when gone
}
@Override
public void onResume() {
super.onResume();
if (!mIsVisibleToUser && getUserVisibleHint()) {
mIsVisibleToUser = true;
show();
}
}
@Override
public void onPause() {
super.onPause();
if (mIsVisibleToUser && getUserVisibleHint()) {
mIsVisibleToUser = false;
hide();
}
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isResumed()) {
if (mIsVisibleToUser != isVisibleToUser) {
mIsVisibleToUser = isVisibleToUser;
if (isVisibleToUser) show();
else hide();
}
}
}
public boolean isVisibleToUser() {
return mIsVisibleToUser;
}