【问题标题】:Nonsibling Constraint for a ViewPager BELOW its Tabs, where TabLayout in AppbarLayout, and ViewPager in a DrawerLayoutViewPager 在其选项卡下方的非兄弟约束,其中 AppbarLayout 中的 TabLayout 和 DrawerLayout 中的 ViewPager
【发布时间】:2019-11-30 16:07:57
【问题描述】:

我有一个主要活动 ConstraintLayout,它需要在顶部 AppbarLayout 下方左侧可见的区域中显示 ViewPager LiveData,该区域包含 ViewPager 的滚动 TabLayout 项目名称。我的困难是 ViewPager 片段文本的顶部被 AppbarLayout 工具栏和选项卡遮住了。我正在尝试将 ViewPager 数据限制为显示在 AppbarLayout 区域下方。

这我可以在 AS 自带的 TabLayout 活动模板中做,当 TabLayout 单独时它可以正常工作。不幸的是,我的 Activity 还迎合了 DrawerLayout NavigationView 菜单,而 Drawer 和 ViewPager 交替响应滑动的唯一方法是当我将 ViewPager 嵌套在 DrawerLayout 中,放置在其 NavigationView 之前。所以我的 ViewPager 已经在 XML 规范底部的 ActivityLayout 中的 DrawerLayout 中关闭了:

<ConstraintLayout
        ...
    <androidx.drawerlayout.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:openDrawer="start"
        app:layout_constraintTop_toBottomOf="@+id/cal_appbar">
    <androidx.viewpager.widget.ViewPager
            android:id="@+id/view_pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:focusableInTouchMode="true"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            android:visibility="visible">
        </androidx.viewpager.widget.ViewPager>

        <com.google.android.material.navigation.NavigationView
            android:id="@+id/nav_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"
            app:headerLayout="@layout/nav_header_refresh"
            app:menu="@menu/activity_calib_drawer" />

    </androidx.drawerlayout.widget.DrawerLayout>
</ConstraintLayout>

在它和我显示省略号的根标记之间,ConstraintLayout 有一个 AppbarLayout,其中包含 Toolbar 和 TabLayout,然后是用于其他 Fragment 的 RelativeLayout。问题不涉及RelativeLayout但AppbarLayout重叠ViewPager的显示

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:fitsSystemWindows="true"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/cal_appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay"
        android:fitsSystemWindows="true"
        tools:context=".Calibsense"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/cal_toolbar"
            android:layout_width="match_parent"
            android:layout_height="?android:attr/actionBarSize"
            android:background="@color/colorPrimary"
            android:visibility="visible"
            app:layout_collapseMode="pin"
            app:popupTheme="@style/AppTheme.PopupOverlay" >

            <TextView
                android:id="@+id/title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:minHeight="?actionBarSize"
                android:padding="@dimen/appbar_padding_top"
                android:text="@string/intro_name"
                android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"/>
        </androidx.appcompat.widget.Toolbar>

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            android:visibility="visible"
            app:layout_constraintTop_toBottomOf="@id/cal_appbar">
        </com.google.android.material.tabs.TabLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/overlap">
        ...

    </RelativeLayout>
    ...
</ConstraintLayout>

ConstraintLayout 坚持约束同级,所以我上面的约束指定包含视图 DrawerLayout 约束 AppbarLayout 而不是最终目标:ViewPager 与 TabLayout。

是否有约束启发式可用于指定片段(ViewPager)显示在 AppbarLayout-TabLayout 下方?

作为一种可能的解决方法,有没有办法为 ViewPager 指定一个顶部填充,其高度为 AppbarLayout 以将其内容推送到可视区域?

我也曾考虑尝试使用 CollapsingToolbarLayout,但设法显示整个 ViewPager 完全没有 AppBarLayout。

附录:

进一步查看在 Activity 的 onCreate() 方法调用 setGuide() 期间对上述内容的编程调用,我在下面公开了 AppbarLayout 参数,并且调试器向我显示了与 XML 设置相同的值:高度 -1 (match_parent)和宽度 -2 (wrap_content),并且在 setGuide() 末尾使用子视图展开后,该值保持不变。测量高度始终显示为零。我不知道这些值的意义;我希望看到几何值,例如非零 px / dp 数量。任何人都可以解释一下吗?零测量高度是否也意味着 ViewPager 被锚定在 px (0,0),如果是这样,如何将锚 y 值更改为低于 AppbarLayout 的可见底部?但我需要首先以编程方式提取该值。如何实现?

DrawerLayout drwLyt;
SectionsPagerAdapter sectionsPagerAdapter;
ViewPager viewPager;
AppBarLayout aBL;
CollapsingToolbarLayout cTBL;
TabLayout tabs;
TextView title;
ConstraintLayout mainGuideView;
Calibsense guideParent;

void setGuide(Calibsense guideModule){
    guideParent = guideModule;
    // AppbarLayout
    aBL = guideParent.findViewById(R.id.cal_appbar);
    ViewGroup.LayoutParams aBLParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    aBL.setLayoutParams(aBLParams);
    aBL.setExpanded(true);
    // measure AppbarLayout using params copy of internal value
    ViewGroup.LayoutParams appBarLayoutParams = aBL.getLayoutParams();
    int aBLHeight = appBarLayoutParams.height;
    int aBLmHeight =  aBL.getMeasuredHeight();

    drwLyt =  findViewById(R.id.drawer_layout);
    ViewGroup.LayoutParams drawerLayoutParams = drwLyt.getLayoutParams();
    int drwLytHeight = drawerLayoutParams.height;

    // setting-up of viewPager
    sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
    viewPager = findViewById(R.id.view_pager);
    // this could be redundant,
    // somewhere it was suggested a new LayoutParams() is required
    ViewGroup.LayoutParams viewPagerParams = viewPager.getLayoutParams();
    viewPager.setAdapter(sectionsPagerAdapter);
    int viewPagerHeight = viewPager.getHeight();

    View spacerView = findViewById(R.id.pager_spacer);
    int spacerHeight = spacerView.getHeight();
    spacerView.setMinimumHeight(aBLHeight);
    // Start set-up of tabs
    TabLayout tabs = findViewById(R.id.tabs);

    // complete set-up of tabs by insertion of viewPager
    tabs.setupWithViewPager(viewPager);
    int tabsHeight = tabs.getHeight();
    relL.setVisibility(View.INVISIBLE);
    // measure AppbarLayout using params copy of internal value
    appBarLayoutParams = aBL.getLayoutParams();
    aBLHeight = appBarLayoutParams.height;
    aBLmHeight =  aBL.getMeasuredHeight();
}

【问题讨论】:

    标签: android-viewpager drawerlayout android-appbarlayout


    【解决方案1】:

    好像是规范:

    android:fitsSystemWindows="true"

    覆盖其他约束并将可查看项目锚定在 (0,0),但该覆盖的范围和范围对我来说并不清楚,所以我暂时避免它。

    此外,经过多次试验和错误(包括隐藏/显示 SystemUI 和 decorView Insets 等的一些错误),这个微妙问题的解决方案就在这个微妙之处:

    要在内容顶部显示工具栏,请最后声明它,而要让 ViewPager 内容不被 systemDecor 遮挡,请先声明它。 所以当前xml标签宏代码的解决方案是:

    <CoordinatorLayout>
       <DrawerLayout>
       <ViewPager>...</ViewPager>
       <RelativeLayout>...</RelativeLayout>
       <AppBarLayout>
          <TabLayout>...</TabLayout>
       </AppBarLayout>
       <ToolBar/>
       <NavigationView/>
       </DrawerLayout>
    </CoordinatorLayout>
    

    然后所有组件的行为都与宣传的一样(除了 TabLayout 不暴露其最后一个页面标题)。 简单的问题需要简单的解决方案,而不是深入研究 API 内部!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-22
      • 1970-01-01
      • 2013-09-26
      • 1970-01-01
      • 2011-12-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多