10

もちろん、いくつかのフラグメントを含むビューページャーがあります。これらの各フラグメントには、親として CoordinatorLayout があります。

何かのスナックバーを見せています。問題は、フラグメント A がスナックバーを表示する場合は問題ありませんが、隣接するフラグメント B もスナックバーを表示する場合、フラグメント A のスナックバーは自動的に非表示になります。

viewpager に隣接するフラグメントがプリロードされているため、これは目に見える問題です。回避策はありますか?それとも私はそれを間違っていますか?

4

2 に答える 2

3

ViewPager の複数の Fragments でのスナックバーにはいくつかの問題があります

1) フラグメント A (表示) とフラグメント B (非表示) にスナックバーが表示されている場合、両方のスナックバーは表示されません。

2) @Override setUserVisibleHint と getUserVisibleHint() の組み合わせを使用して、フラグメントの可視性に応じてスナックバーをスマートに表示および非表示にすると、最初にのみ機能します。その後、snackbar.show() を呼び出すと、スナックバーが表示されなくなります (スナックバーを再作成しない限り)。

以下は私が提案した解決策です(v23.1.1でテスト済み):

public class SnackbarManager {
    private static final String TAG = SnackbarManager.class.getName();

    private Snackbar snackbar;
    private Create instance;
    // private boolean isMultiSnackbar;

    public interface Create {
        Snackbar create();
    }

    public SnackbarManager(Create instance) {
        // why not pass in snackbar? coz snackbar.show will fail after 1st show (it multiple snackbar), thus need to recreate it
        snackbar = instance.create();
        this.instance = instance;
    }

    public void show(Fragment fragment) {
        if (fragment.getUserVisibleHint()) {
            snackbar.show();
        }
    }

    public void onSetUserVisibleHint(boolean isVisible) {
        if (isVisible) {
            if (snackbar == null) {
                snackbar = instance.create();
            }
            snackbar.show();
            Log.d(TAG, "showSnackbar="+snackbar.isShown());
            // if snackbar.isShown()=false, if means multiple snackbar exist (might or might not be in same fragment)
            /*
            boolean isMultiSnackbar = !snackbar.isShown();
            // the following is inaccurate when I manually dismiss one of the snackbar
            // even when isShown()=true, the snackbar is not shown
            if (isMultiSnackbar) {
                snackbar = null;
                snackbar = instance.create();
                snackbar.show();
            }
             */
            }
            else {
                Log.d(TAG, "dismissSnackbar");
                snackbar.dismiss();
                // subsequent show will fail, make sure to recreate next
                snackbar = null;
            }
        }
    }
}

public class TestFragment extends Fragment {
    private SnackbarManager snackbarManager;

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (snackbarManager != null)
            snackbarManager.onSetUserVisibleHint(isVisibleToUser);
    }

    public void showSnackbar() {
        snackbarManager = new SnackbarManager(new SnackbarManager.Create() {
            @Override
            public Snackbar create() {
                Snackbar snackbar = Snackbar.make(snackbarLayout, "Create your first moment ;)", Snackbar.LENGTH_INDEFINITE);
                snackbar.setAction("Create", new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        snackbarManager = null;
                    }
                });
                // enable following if not Snackbar.LENGTH_INDEFINITE
                /*
                snackbar.setCallback(new Snackbar.Callback() {
                    @Override
                    public void onDismissed(Snackbar snackbar, int event) {
                        super.onDismissed(snackbar, event);
                        snackbarManager = null;
                    }
                })
                */
                return snackbar;
            }
        });
        snackbarManager.show(this);
    }
}
于 2016-02-20T07:02:07.337 に答える
2

setUserVisibleHint(boolean isVisible) を使用してフラグメントの可視性を更新し (たとえば、ViewPager onPageSelected で)、フラグメントでgetUserVisibleHint()を使用して、フラグメントが表示されている場合にのみスナックバーを表示できます。

フラグメントA、B、Cがあるとしましょう

フラグメント A が表示され、スナックバーも表示されます。フラグメント B または C がスナックバーを開こうとすると、getUserVisibleHint() は false を返し、フラグメント A のスナックバーを混乱させることはありません。

オブス。FragmentStatePagerAdapter でこれを行う場合は注意してください。NPE が Fragments への参照を保持し、この参照で setUserVisibleHint() を呼び出す可能性があるためです。

編集:システムによってすでに呼び出されているため、 setUserVisibleHint() は必要ありません。

于 2016-01-12T18:11:17.200 に答える