Android:在不同的片段(ViewPager)中使用多个snackbar

10
我有一个viewpager, 当然包含几个fragment。这些fragment的父级视图是CoordinatorLayout。
我正在展示snackbar信息,但问题是如果Fragment A 展示了snackbar,那么没有问题,但是如果相邻的Fragment B 也展示了snackbar,那么Fragment A 中的snackbar会自动隐藏。
由于viewpager预加载相邻的fragment,因此这是一个可见的问题。有什么解决方法吗?或者我的做法不对?

嗨,KalpitJain!你找到答案了吗?我也遇到了同样的问题。 - Vijay
它已经两年了,我不太记得了。我猜想解决方案是在每个片段中维护要显示在 snackbar 中的消息,并在该特定片段对用户可见时(以及其他片段)显示它。 - TheKalpit
2个回答

3
在ViewPager中多个Fragment中使用Snackbar存在一些问题:
1)如果在可见的Fragment A和不可见的Fragment B上显示Snackbar,则两个Snackbar都不可见。
2)如果我使用@ Override setUserVisibleHint和getUserVisibleHint()的组合来智能地根据片段可见性显示和隐藏Snackbar,它只能在第一次工作。之后,调用snackbar.show()无法再显示Snackbar(除非我重新创建Snackbar)。
以下是我的建议解决方案(已在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);
    }
}

2
你可以使用 setUserVisibleHint(boolean isVisible) 方法更新片段的可见性(例如,在您的ViewPager onPageSelected 上),然后在您的片段上使用getUserVisibleHint(),仅当该片段可见时才显示Snackbar。
假设您有A、B和C三个片段。
片段A可见,因此Snackbar也是可见的。如果片段B或C尝试打开Snackbar,则getUserVisibleHint()将返回false,并且它们不会干扰片段A的Snackbar。
注意:在使用FragmentStatePagerAdapter时要小心,因为保持对片段的引用并调用其 setUserVisibleHint() 方法可能会导致NullPointerException。
编辑:不需要使用 setUserVisibleHint(),因为系统已经自动调用了该方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接