滚动时如何修复折叠工具栏中的视图?

How to fix a view in collapsing toolbar while scrolling?

我想实现带有两个 EditText 的折叠工具栏,以供用户输入。我正在关注 this 答案。答案给出了将两个 EditText 添加到折叠工具栏的完美解决方案。但行为并不像预期的那样。

我的收获:

预期行为:

我的XML代码

<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">

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

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsing_tool_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:elevation="0dp"
        app:expandedTitleTextAppearance="@style/Widget.AppCompat.ActionBar.TabText"
        app:layout_scrollFlags="scroll|enterAlways"
        app:statusBarScrim="?attr/colorAccent">


        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar_1"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/primary"
            android:minHeight="?attr/actionBarSize"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:layout_collapseMode="none"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
        </android.support.v7.widget.Toolbar>

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

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/primary"
        android:minHeight="?attr/actionBarSize"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:layout_collapseMode="none"
        app:elevation="0dp"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingLeft="32dp"
            android:paddingTop="16dp"
            android:paddingBottom="56dp"
            android:paddingRight="16dp">

            <android.support.design.widget.TextInputLayout
                android:id="@+id/lNameLayout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/fNameLayout"
                android:layout_marginTop="10dp">

                <EditText
                    android:id="@+id/ltitle"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:ems="10"
                    android:hint="Title"/>
            </android.support.design.widget.TextInputLayout>

            <android.support.design.widget.TextInputLayout
                android:id="@+id/lNameLayout2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/fNameLayout"
                android:layout_marginTop="10dp"
                android:layout_marginBottom="10dp">

                <EditText
                    android:id="@+id/ldesc"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:ems="10"
                    android:hint="Description"/>
            </android.support.design.widget.TextInputLayout>


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

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


<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingTop="10dp">

        <!--my widgets here-->

    </LinearLayout>
</android.support.v4.widget.NestedScrollView>

我知道我可以使用 scrollFlag 进行此类样式设置。我已阅读 this post about scroll flags.但无法找到具体的使用方法。
我也想把EditText的字号改成上面的GIF

但第一个问题是如何修复工具栏中的一个视图并在用户向上滚动时隐藏另一个视图。如果有人用合适的例子解释,那就太好了。

我确定 Todoist 正在以另一种方式进行操作,但仍然...

这是xml布局。主要思想是,应该固定的视图应该在 Toolbar 内,而您要隐藏的另一个视图应该在 CollapsingToolbarLayout 内,并且上边距合适,以防止重叠:

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_tool_bar_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:statusBarScrim="?attr/colorAccent">

            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_collapseMode="parallax"
                android:layout_marginLeft="72dp"
                android:layout_marginRight="16dp"
                android:layout_marginBottom="32dp"
                android:layout_marginTop="136dp">

                <android.support.design.widget.TextInputLayout
                    android:id="@+id/lNameLayout2"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

                    <android.support.design.widget.TextInputEditText
                        android:id="@+id/ldesc"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:ems="10"
                        android:hint="Description"/>
                </android.support.design.widget.TextInputLayout>

            </FrameLayout>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/primary"
                android:minHeight="?attr/actionBarSize"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

                <android.support.design.widget.TextInputLayout
                    android:id="@+id/lNameLayout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginRight="16dp"
                    android:layout_marginBottom="16dp"
                    android:layout_marginTop="48dp">

                    <android.support.design.widget.TextInputEditText
                        android:id="@+id/title"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:hint="Title"
                        android:textSize="30sp"
                        android:textColor="@android:color/white"
                        android:ems="10"/>
                </android.support.design.widget.TextInputLayout>

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

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


    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="none"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <!-- your content here -->

    </android.support.v4.widget.NestedScrollView>

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

然后,要实现相同的字体大小和上边距动画,我们可以实现 AppBarLayout.OnOffsetChangedListener 并根据滚动偏移量的变化为我们的属性设置动画。这里是 activity class:

public class MainActivity extends AppCompatActivity
    implements AppBarLayout.OnOffsetChangedListener {

    private static final float COLLAPSED_TEXT_SIZE_SP = 18f;

    private static final float COLLAPSED_TOP_MARGIN_DP = 24f;

    private static final float MARGIN_SCROLLER_MULTIPLIER = 4f;

    private float expandedTextSize;
    private float collapsedTextSize;

    private int expandedTopMargin;
    private int collapsedTopMargin;

    private AppBarLayout mAppBarLayout;
    private Toolbar mToolbar;
    private TextInputEditText editText;
    private TextInputLayout textInputLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        mAppBarLayout = (AppBarLayout) findViewById(R.id.appbar);
        editText = (TextInputEditText) findViewById(R.id.title);
        textInputLayout = (TextInputLayout) findViewById(R.id.lNameLayout);

        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        mAppBarLayout.addOnOffsetChangedListener(this);

        expandedTextSize = editText.getTextSize();
        collapsedTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, COLLAPSED_TEXT_SIZE_SP, getResources().getDisplayMetrics());

        expandedTopMargin = ((ViewGroup.MarginLayoutParams) textInputLayout.getLayoutParams()).topMargin;
        collapsedTopMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, COLLAPSED_TOP_MARGIN_DP, getResources().getDisplayMetrics());
    }

    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int offset) {
        int maxScroll = appBarLayout.getTotalScrollRange();
        float percentage = (float) Math.abs(offset) / maxScroll;
        float textSizeDiff = Math.abs(expandedTextSize - collapsedTextSize);
        int marginDiff = Math.abs(expandedTopMargin - collapsedTopMargin);
        //change text size along with scrolling
        editText.setTextSize(TypedValue.COMPLEX_UNIT_PX, expandedTextSize - textSizeDiff * percentage);
        //change top view margin along with scrolling
        ((ViewGroup.MarginLayoutParams) textInputLayout.getLayoutParams()).topMargin = (int) (expandedTopMargin - marginDiff * Math.min(1, percentage * MARGIN_SCROLLER_MULTIPLIER));
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            finish();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
} 

因此,对于展开状态,我使用了默认值,我们在 xml 中应用了默认值。对于折叠状态,我定义了简单的常量。随意满足您的需求。

注意, 当您向 Toolbar 添加后退按钮或菜单项时,您应该使用 leftright 第二个视图(您要隐藏的那个)的边距,因为第一个 EditTextToolbar 的一部分,因此它的边距将根据你添加了什么。

结果:

编码愉快!