简体   繁体   中英

Custom Collapsing Toolbar smooth title resizing

I'm using a custom Collapsing Toolbar Layout, which has a Title and a Subtitle.
I got the title to collapse and animate on a curved path, but the part of the title becoming smaller as collapsing isn't smooth. It resizes in a jagged sort of way.
This is my behavior that is responsible for moving and resizing the title:

public class ViewBehavior : CoordinatorLayout.Behavior
{
    private Context mContext;

    private int mStartMarginRight;
    private int mEndMargintRight;
    private int mMarginLeft;
    private int mStartMarginBottom;
    private bool isHide;
    private static float SCALE_MINIMUM = 0.5f;
    public ViewBehavior(Context context, IAttributeSet attrs)
    {
        mContext = context;
    }

    public override bool LayoutDependsOn(CoordinatorLayout parent, Java.Lang.Object child, View dependency)
    {
        return dependency is AppBarLayout;
    }

    public override bool OnDependentViewChanged(CoordinatorLayout parent, Java.Lang.Object child, View dependency)
    {
        ShouldInitProperties((child as HeaderView), dependency);

        int maxScroll = ((AppBarLayout)dependency).TotalScrollRange;
        float percentage = System.Math.Abs(dependency.GetY()) / (float)maxScroll;

        float childPosition = dependency.Height
                + dependency.GetY()
                - (child as View).Height
                - (getToolbarHeight() - (child as View).Height) * percentage / 2;


        childPosition = childPosition - mStartMarginBottom * (1f - percentage);

        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)(child as View).LayoutParameters;
        lp.RightMargin = (int)(100 * System.Math.Sin(percentage * System.Math.PI)) + mStartMarginRight / 2 + mEndMargintRight / 2;
        lp.LeftMargin = mMarginLeft;
        (child as View).LayoutParameters = lp;

        (child as View).SetY(childPosition);
        float x = (child as HeaderView).Title.TextSize;
        //Here is the algorithm for setting the text size
        (child as HeaderView).Title.SetTextSize(ComplexUnitType.Sp, 36 * (1 - percentage / 2));
        (child as HeaderView).SubTitle.SetTextSize(ComplexUnitType.Sp, 26 * (1 - percentage / 2));

        var toolbarTitleSize = (int)TypedValue.ApplyDimension(ComplexUnitType.Sp, 18, Application.Context.Resources.DisplayMetrics);
        var toolbarSubTitleSize = (int)TypedValue.ApplyDimension(ComplexUnitType.Sp, 16, Application.Context.Resources.DisplayMetrics);
        if ((child as HeaderView).Title.TextSize < toolbarTitleSize)
            (child as HeaderView).Title.SetTextSize(ComplexUnitType.Sp, 18);
        if ((child as HeaderView).SubTitle.TextSize < toolbarSubTitleSize)
            (child as HeaderView).SubTitle.SetTextSize(ComplexUnitType.Sp, 14);
        if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop)
        {
            if (isHide && percentage < 1)
            {
                (child as View).Visibility = ViewStates.Visible;
                isHide = false;
            }
            else if (!isHide && percentage == 1)
            {
                (child as View).Visibility = ViewStates.Gone;
                isHide = true;
            }
        }
        return true;
    }


    public void ShouldInitProperties(HeaderView child, View dependency)
    {

        if (mStartMarginRight == 0)
            mStartMarginRight = mContext.Resources.GetDimensionPixelOffset(Resource.Dimension.header_view_start_margin_right);

        if (mEndMargintRight == 0)
            mEndMargintRight = mContext.Resources.GetDimensionPixelOffset(Resource.Dimension.header_view_end_margin_right);

        if (mStartMarginBottom == 0)
            mStartMarginBottom = mContext.Resources.GetDimensionPixelOffset(Resource.Dimension.header_view_start_margin_bottom);

        if (mMarginLeft == 0)
            mMarginLeft = mContext.Resources.GetDimensionPixelOffset(Resource.Dimension.header_view_end_margin_left);

    }


    public int getToolbarHeight()
    {
        int result = 0;
        TypedValue tv = new TypedValue();
        if (mContext.Theme.ResolveAttribute(Android.Resource.Attribute.ActionBarSize, tv, true))
        {
            result = TypedValue.ComplexToDimensionPixelSize(tv.Data, mContext.Resources.DisplayMetrics);
        }
        return result;
    }
}

How can I change the algorithm so it should resize in a smoother fashion?

Edit - Video:
https://youtu.be/j6LseSW6h1s

As mentioned by others scaling via textSize doesn't work well on Android within animations since it isn't accurate enough (it rounds up the decimal values to integers).

If it fulfills your need you should perform your animation with the scaleX / scaleY attributes, eg:

float scale = 1 - percentage * SCALE_MINIMUM;
(child as HeaderView).Title.SetScaleX(scale);
(child as HeaderView).Title.SetScaleY(scale);
(child as HeaderView).SubTitle.SetScaleX(scale);
(child as HeaderView).SubTitle.SetScaleY(scale);

The problem you have is that the even if you calculate scales as demical values, they become integer values in the TextView. You should enable both LINEAR_TEXT_FLAG and SUBPIXEL_TEXT_FLAG flags in your TextView's Paint class to achieve smooth scaling and positioning.

Something like this:

yourTextView.Paint.SubpixelText = true;
yourTextView.Paint.LinearText = true;

I have use this layout format for collapsing toolbar and it works smoothly.

  <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="@dimen/height_300dp"
        android:background="?colorPrimary">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsible_Toolbar_Layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:collapsedTitleTextAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse"
            app:contentScrim="@color/colorDarkBlue"
            app:expandedTitleMarginEnd="@dimen/margin_64dp"
            app:expandedTitleMarginStart="@dimen/margin_20dp"
            app:expandedTitleTextAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <ImageView
                android:id="@+id/image"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:clickable="true"
                android:fitsSystemWindows="true"
                android:focusableInTouchMode="true"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax" />

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/colorTransparent" />

            <ImageButton
                android:id="@+id/ib"
                android:layout_width="@dimen/margin_35dp"
                android:layout_height="@dimen/margin_35dp"
                android:layout_gravity="right"
                android:layout_marginRight="@dimen/margin_10dp"
                android:layout_marginTop="@dimen/height_245dp"
                android:background="@null"
                android:src="@drawable/ic_launcher" />


            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?actionBarSize"
                android:background="@android:color/transparent"
                android:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:contentInsetStart="@dimen/margin_50dp"
                app:layout_collapseMode="pin">

                <ImageButton
                    android:id="@+id/ib2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="right"
                    android:layout_marginRight="@dimen/margin_10dp"
                    android:background="@null"
                    android:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                    android:src="@drawable/ic_launcher"
                    android:visibility="invisible" />

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

After that in Fragment in IntializeComponents I am intialize this layout only and set Text

     appBarLayout = (AppBarLayout)view.findViewById(R.id.app_bar_layout);

        CollapsingToolbarLayout toolbarLayout = (CollapsingToolbarLayout) view.findViewById(R.id.collapsible_Toolbar_Layout);
        toolbarLayout.setTitle(yourTitle);
        toolbarLayout.setCollapsedTitleTextColor(Color.WHITE);
        toolbarLayout.setExpandedTitleColor(Color.WHITE);
        appBarLayout.addOnOffsetChangedListener(this);

Add this method for Handle the toolbar

    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int offset) {
        int maxScroll = appBarLayout.getTotalScrollRange();
        float percentage = (float) Math.abs(offset) / (float) maxScroll;
        handleToolbarTitleVisibility(percentage);
    }

    private void handleToolbarTitleVisibility(float percentage) {
        if (percentage >= PERCENTAGE_TO_SHOW_TITLE_AT_TOOLBAR) {
            if(!mIsTheTitleVisible) {
                imageButton.setVisibility(View.VISIBLE);
                ib.setVisibility(View.INVISIBLE);
                mIsTheTitleVisible = true;
            }

        } else  {

            if (mIsTheTitleVisible) {
                imageButton.setVisibility(View.INVISIBLE);
                ibMap.setVisibility(View.VISIBLE);
                mIsTheTitleVisible = false;
            }
        }
    }

I hope it will helps you :)

No if you are using customTextview then also it will work because I am also using customTextView only.

Will you post the customtextview code here? So all can see the problem in your customTextview.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM