How to fix a view in collapsing toolbar while scrolling?

后端 未结 1 1508
滥情空心
滥情空心 2021-01-01 00:46

I want to implement collapsing toolbar with two EditText in it, for the purpose of user input. I\'m following this answer. The answer gives perfect solution for

相关标签:
1条回答
  • 2021-01-01 01:34

    I'm sure Todoist is doing it another way, but still...

    Here is the xml layout. The main idea is that the view, that supposed to be pinned, should be inside Toolbar, when another view, which you want to hide, should be inside CollapsingToolbarLayout with a decent top margin, to prevent overlapping:

    <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>
    

    Then, to achieve the same font size and top margin animation, we can implement AppBarLayout.OnOffsetChangedListener and animate our properties according to scrolling offset changes. Here is the 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);
        }
    } 
    

    So, here for expanded state I've used default values, that we applied in our xml. For collapsed state I've defined simple constants. Feel free to fit them for your needs.

    Note, when you add a back button or menu items to the Toolbar, you should play around with left and right margins of the second view (the one you want to hide), because the first EditText is a part of Toolbar, therefore its margins will be changed according to what you did add.

    Result:

    Happy coding!

    0 讨论(0)
提交回复
热议问题