Android - FAB在viewpager中的不同片段之间导航时隐藏

Sim*_*mon 12 android android-viewpager floating-action-button

我正在尝试做一些非常简单的事情.

我希望FAB只显示在我的TabLayout中的一个选项卡上,并在导航到另一个选项卡时隐藏.因此,例如,一个选项卡允许您在FAB中添加新项目,但下一个选项卡不允许您添加项目.

我遵循了"典型的"XML设计布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    xmlns:tools="http://schemas.android.com/tools"
    >

<android.support.design.widget.AppBarLayout
    android:id="@+id/appBarLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_scrollFlags="scroll|enterAlways">

        <LinearLayout
            android:id="@+id/search_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <EditText
                android:id="@+id/search_view"
                android:layout_width="0dp"
                android:layout_height="?attr/actionBarSize"
                android:layout_weight="1"
                android:background="@android:color/transparent"
                android:gravity="center_vertical"
                android:hint="Search"
                android:imeOptions="actionSearch"
                android:inputType="text"
                android:maxLines="1"
                android:paddingLeft="2dp"
                android:singleLine="true"
                android:textColor="#ffffff"
                android:textColorHint="#b3ffffff" />

            <ImageView
                android:id="@+id/search_clear"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:paddingLeft="16dp"
                android:paddingRight="16dp"
                android:src="@drawable/ic_action_cancel" />

        </LinearLayout>

    </android.support.v7.widget.Toolbar>

    <android.support.design.widget.TabLayout
        android:id="@+id/sliding_tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        app:tabMode="scrollable"
        />


</android.support.design.widget.AppBarLayout>

<android.support.v4.view.ViewPager
    android:id="@+id/viewPager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="com.example.simon.behaviours.PatchedScrollingViewBehavior"/>

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"
    app:borderWidth="0dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_action_new"
    android:layout_margin="16dp"
    android:layout_gravity="bottom|right"
    app:layout_anchor="@+id/viewPager"
    app:layout_anchorGravity="bottom|right|end"
    app:layout_behavior="com.example.simon.behaviours.ScrollingFABBehavior"
    android:visibility="gone"
    app:fabSize="normal">
</android.support.design.widget.FloatingActionButton>

</android.support.design.widget.CoordinatorLayout>
Run Code Online (Sandbox Code Playgroud)

我对FAB使用了以下行为.这导致任何upscrolls导致FAB消失,并将在缩减滚动时返回到屏幕上:

public class ScrollingFABBehavior extends FloatingActionButton.Behavior {
    private int toolbarHeight;

    public ScrollingFABBehavior(Context context, AttributeSet attrs) {
        super();
        this.toolbarHeight = getToolbarHeight(context);
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
        return super.layoutDependsOn(parent, fab, dependency) || (dependency instanceof AppBarLayout);
    }

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton fab, View dependency) {
        boolean returnValue = super.onDependentViewChanged(parent, fab, dependency);
        if (dependency instanceof AppBarLayout) {
            CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
            int fabBottomMargin = lp.bottomMargin;
            int distanceToScroll = fab.getHeight() + fabBottomMargin;
            float ratio = (float)dependency.getY()/(float)toolbarHeight;
            fab.setTranslationY(-distanceToScroll * ratio);
        }
        return returnValue;
    }

    public static int getToolbarHeight(Context context) {
        final TypedArray styledAttributes = context.getTheme().obtainStyledAttributes(
                new int[]{R.attr.actionBarSize});
        int toolbarHeight = (int) styledAttributes.getDimension(0, 0);
        styledAttributes.recycle();

        return toolbarHeight;
    }
}
Run Code Online (Sandbox Code Playgroud)

我添加了一个viewpager addOnPageChangeListener:

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        if (position == 0) {
            FloatingActionButton floatingActionButton = (FloatingActionButton) findViewById(R.id.fab);
            floatingActionButton.setVisibility(View.VISIBLE);
        }
        else
        {
            FloatingActionButton floatingActionButton = (FloatingActionButton) findViewById(R.id.fab);
            floatingActionButton.setVisibility(View.GONE);
        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
});
Run Code Online (Sandbox Code Playgroud)

我只希望FAB出现在第一页上,并在所有其他页面上消失.

代码可以工作但是当我向下滑动下一页时,即使可见性设置为消失,FAB也会出现.我认为它与FAB的行为设置有关.有没有人知道为什么如果能见度设定消失,FAB仍然会在向下滑动时变得可见?

Sim*_*mon 7

这并不是我想在我的应用程序中实现的东西,但我确实设法找到答案,最后通过查看他们如何在wordpress应用程序上实现相同的东西得到一些帮助.

在wordpress应用程序中,我们在应用程序的第一页上看到一个浮动操作按钮,如果您滑动到viewpager上的任何其他页面,它会消失:

WordPress的

他们通过以下代码执行此操作 - 这是包含viewpager的Activity的代码.您可以在onPageScrolled方法下查看代码的相关部分,该方法包含每次滚动页面时发布事件的事件总线.该事件只包含一个名为positionOffset的变量,它是一个从0到1的整数值.如果滚动并且页面位于两个视图之间的中间位置,则positionOffset为0.5,您会明白:

WPMainActivity.java

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                AppPrefs.setMainTabIndex(position);

                switch (position) {
                    case WPMainTabAdapter.TAB_NOTIFS:
                        new UpdateLastSeenTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                        break;
                }
                trackLastVisibleTab(position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                // noop
            }

            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                // fire event if the "My Site" page is being scrolled so the fragment can
                // animate its fab to match
                if (position == WPMainTabAdapter.TAB_MY_SITE) {
                    EventBus.getDefault().post(new MainViewPagerScrolled(positionOffset));
                }
            }
        });
Run Code Online (Sandbox Code Playgroud)

在包含以下代码的片段中拾取事件.该事件将触发translateY方法,该方法在页面滚动时根据positionOffset确定的页面滚动视图的距离垂直地动画FAB:

MySiteFragment

/*
 * animate the fab as the users scrolls the "My Site" page in the main activity's ViewPager
 */
@SuppressWarnings("unused")
public void onEventMainThread(CoreEvents.MainViewPagerScrolled event) {
    mFabView.setTranslationY(mFabTargetYTranslation * event.mXOffset);
}
Run Code Online (Sandbox Code Playgroud)

最后,my_site_fragment.xml中的布局显示FAB实际上放在片段xml而不是活动xml中.

<!-- this coordinator is only here due to https://code.google.com/p/android/issues/detail?id=175330 -->
<android.support.design.widget.CoordinatorLayout
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_marginBottom="@dimen/fab_margin"
        android:layout_marginRight="@dimen/fab_margin"
        android:src="@drawable/gridicon_create_light"
        app:borderWidth="0dp"
        app:rippleColor="@color/fab_pressed" />
</android.support.design.widget.CoordinatorLayout>
Run Code Online (Sandbox Code Playgroud)


Ant*_*eef 5

嘿,我遇到了和你完全一样的问题。

我找到了两种对我有用的方法。

方法一:

在 MainActivity: 中添加一个静态标志 public static boolean fabVisible;

我注意到您有一个侦听器viewPager可以检测当前片段页面,因此您可以添加以下内容:

    public void onPageSelected(int position) {
        switch (position) {
            case 0:
                fabVisible = true;
                mFloatingActionButton.show();
                break;
            default:
                fabVisible = false;
                mFloatingActionButton.hide();
                break;
        }
    }
Run Code Online (Sandbox Code Playgroud)

在您的自定义 fab 行为中,添加以下代码:

    if (dyConsunmed > 0 && child.getVisibility() == View.VISIBLE ) {
            child.hide();
        } else if (dyConsunmed < 0 && child.getVisibility() != View.VISIBLE && MainActivity.fabVisible) {
            child.show();
        }
Run Code Online (Sandbox Code Playgroud)

此方法的重点是确保在实现隐藏和显示方法之前 fab 应该是可见的。

方法二:

您不再需要添加任何标志,例如“fabVisible” MainActivity。尽管此方法确实需要您在 中将 设置viewPager为静态MainActivity,因为我们需要能够在我们的自定义 fab 行为类中访问它。

在您的ScrollAwareFABBehavior类中,添加以下代码:

    if (MainActivity.viewPager.getCurrentItem() == 0) {
        if (dyConsunmed > 0 && child.getVisibility() == View.VISIBLE ) {
            child.hide();
        } else if (dyConsunmed < 0 && child.getVisibility() != View.VISIBLE) {
            child.show();
        }

    }
Run Code Online (Sandbox Code Playgroud)

这个方法的关键点是,当你在你想要的片段中时,只执行显示和隐藏方法(在我的例子中它是片段一,所以当前项 == 0)。当然,为了删除第二个片段中的 fab,您仍然需要将它隐藏在您的 viewPager 侦听器中。

如果您仍然对实现感到困惑,请随时查看我在 GitHub 上的存储库并使用代码。地址为:https : //github.com/Anthonyeef/FanfouDaily

虽然提要内容全是中文,但代码全是英文。