Skip to content Skip to sidebar Skip to footer

Collapsingtoolbarlayout With A Customised Behavior

I am following this popular link for cordinator behaviour, following this post .I wanted a desired behavior that image should be floated to right side instead of left and for this,

Solution 1:

So, the first thing you should do is to tweak the layout file - make Toolbar fixed at top by removing its layout_anchor attribute.

<android.support.design.widget.CoordinatorLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:ignore="RtlHardcoded"
    ><android.support.design.widget.AppBarLayoutandroid:id="@+id/main.appbar"android:layout_width="match_parent"android:layout_height="wrap_content"android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        ><android.support.design.widget.CollapsingToolbarLayoutandroid:id="@+id/main.collapsing"android:layout_width="match_parent"android:layout_height="wrap_content"app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
            ><ImageViewandroid:id="@+id/main.imageview.placeholder"android:layout_width="match_parent"android:layout_height="300dp"android:scaleType="centerCrop"android:src="@drawable/quila2"android:tint="#11000000"app:layout_collapseMode="parallax"app:layout_collapseParallaxMultiplier="0.9"
                /></android.support.design.widget.CollapsingToolbarLayout></android.support.design.widget.AppBarLayout><android.support.v4.widget.NestedScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:scrollbars="none"app:behavior_overlapTop="24dp"app:layout_behavior="@string/appbar_scrolling_view_behavior"
        ><android.support.v7.widget.CardViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="8dp"app:cardElevation="8dp"app:contentPadding="16dp"
            ><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:lineSpacingExtra="8dp"android:text="@string/lorem"android:textSize="18sp"
                /></android.support.v7.widget.CardView></android.support.v4.widget.NestedScrollView><android.support.v7.widget.Toolbarandroid:id="@+id/main.toolbar"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"android:background="@color/primary"app:theme="@style/ThemeOverlay.AppCompat.Dark"app:title=""><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="match_parent"android:orientation="horizontal"><TextViewandroid:id="@+id/main.textview.title"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_marginLeft="8dp"android:gravity="center_vertical"android:text="@string/quila_name2"android:textColor="@android:color/white"android:textSize="20sp"/></LinearLayout></android.support.v7.widget.Toolbar><de.hdodenhof.circleimageview.CircleImageViewandroid:layout_width="@dimen/image_width"android:layout_height="@dimen/image_width"android:layout_gravity="center_horizontal"android:src="@drawable/quila"app:border_color="@android:color/white"app:border_width="2dp"app:finalHeight="@dimen/image_final_width"app:layout_behavior="saulmm.myapplication.AvatarImageBehavior"
        /></android.support.design.widget.CoordinatorLayout>

Note, I've also removed main.framelayout.title section, as I consider it as a part of a Toolbar as well. And I've also removed onOffsetChanged() and all relative to it methods in MainActivity, and made our title of Toolbar always visible.

Secondly, of course, you should make changes in the AvatarImageBehavior class. The main thing here is that now your ImageView is dependent on NestedScrollView instead of Toolbar. But since we're not dependent on Toolbar anymore, we still need it to define the mFinalYPosition, so I've added the method to find the Toolbar as well. Here is the behavior:

publicclassAvatarImageBehaviorextendsCoordinatorLayout.Behavior<CircleImageView> {

    privatefinalstaticfloatMIN_AVATAR_PERCENTAGE_SIZE=0.3f;
    privatefinalstaticintEXTRA_FINAL_AVATAR_PADDING=80;

    privatefinalstaticStringTAG="behavior";
    private Context mContext;

    privatefloat mCustomFinalYPosition;
    privatefloat mCustomStartXPosition;
    privatefloat mCustomStartToolbarPosition;
    privatefloat mCustomStartHeight;
    privatefloat mCustomFinalHeight;

    privatefloat mAvatarMaxSize;
    privatefloat mStartPosition;
    privateint mStartXPosition;
    privatefloat mStartToolbarPosition;
    privateint mStartYPosition;
    privateint mFinalYPosition;
    privateint mStartHeight;
    privateint mFinalXPosition;
    privatefloat mChangeBehaviorPoint;

    publicAvatarImageBehavior(Context context, AttributeSet attrs) {
        mContext = context;

        if (attrs != null) {
            TypedArraya= context.obtainStyledAttributes(attrs, R.styleable.AvatarImageBehavior);
            mCustomFinalYPosition = a.getDimension(R.styleable.AvatarImageBehavior_finalYPosition, 0);
            mCustomStartXPosition = a.getDimension(R.styleable.AvatarImageBehavior_startXPosition, 0);
            mCustomStartToolbarPosition = a.getDimension(R.styleable.AvatarImageBehavior_startToolbarPosition, 0);
            mCustomStartHeight = a.getDimension(R.styleable.AvatarImageBehavior_startHeight, 0);
            mCustomFinalHeight = a.getDimension(R.styleable.AvatarImageBehavior_finalHeight, 0);

            a.recycle();
        }

        init();
    }

    privatevoidinit() {
        bindDimensions();
    }

    privatevoidbindDimensions() {
        mAvatarMaxSize = mContext.getResources().getDimension(R.dimen.image_width);
    }

    @OverridepublicbooleanlayoutDependsOn(CoordinatorLayout parent, CircleImageView child, View dependency) {
        return dependency instanceof NestedScrollView;
    }

    @OverridepublicbooleanonDependentViewChanged(CoordinatorLayout parent, CircleImageView child, View dependency) {
        maybeInitProperties(parent, child, dependency);

        finalintmaxScrollDistance= (int) (mStartToolbarPosition);
        floatexpandedPercentageFactor= dependency.getY() / maxScrollDistance;

        if (expandedPercentageFactor < mChangeBehaviorPoint) {
            floatheightFactor= (mChangeBehaviorPoint - expandedPercentageFactor) / mChangeBehaviorPoint;

            floatdistanceXToSubtract= ((mStartXPosition - mFinalXPosition)
                    * heightFactor) + (child.getHeight()/2);
            floatdistanceYToSubtract= ((mStartYPosition - mFinalYPosition)
                    * (1f - expandedPercentageFactor)) + (child.getHeight()/2);

            child.setX(mStartXPosition - distanceXToSubtract);
            child.setY(mStartYPosition - distanceYToSubtract);

            floatheightToSubtract= ((mStartHeight - mCustomFinalHeight) * heightFactor);

            CoordinatorLayout.LayoutParamslp= (CoordinatorLayout.LayoutParams) child.getLayoutParams();
            lp.width = (int) (mStartHeight - heightToSubtract);
            lp.height = (int) (mStartHeight - heightToSubtract);
            child.setLayoutParams(lp);
        } else {
            floatdistanceYToSubtract= ((mStartYPosition - mFinalYPosition)
                    * (1f - expandedPercentageFactor)) + (mStartHeight/2);

            child.setX(mStartXPosition - child.getWidth()/2);
            child.setY(mStartYPosition - distanceYToSubtract);

            CoordinatorLayout.LayoutParamslp= (CoordinatorLayout.LayoutParams) child.getLayoutParams();
            lp.width = (int) (mStartHeight);
            lp.height = (int) (mStartHeight);
            child.setLayoutParams(lp);
        }
        returntrue;
    }

    privatevoidmaybeInitProperties(CoordinatorLayout parent, CircleImageView child, View dependency) {
        if (mStartYPosition == 0)
            mStartYPosition = (int) (dependency.getY());

        Viewtoolbar= tryFindToolbarInLayout(parent);

        if (mFinalYPosition == 0 && toolbar != null) {
            mFinalYPosition = (toolbar.getHeight() / 2);
        }

        if (mStartHeight == 0)
            mStartHeight = child.getHeight();

        if (mStartXPosition == 0)
            mStartXPosition = (int) (child.getX() + (child.getWidth() / 2));

        if (mFinalXPosition == 0)
            mFinalXPosition = dependency.getContext().getResources().getDisplayMetrics().widthPixels - mContext.getResources().getDimensionPixelOffset(R.dimen.abc_action_bar_content_inset_material)
                    - ((int) mCustomFinalHeight / 2);

        if (mStartToolbarPosition == 0)
            mStartToolbarPosition = dependency.getY();

        if (mChangeBehaviorPoint == 0 && toolbar != null) {
            mChangeBehaviorPoint = (child.getHeight() - mCustomFinalHeight) / (mStartYPosition - mFinalYPosition - toolbar.getHeight());
        }
    }

    private View tryFindToolbarInLayout(CoordinatorLayout parent) {
        for (inti=0; i < parent.getChildCount(); i++) {
            Viewchild= parent.getChildAt(i);
            if (child instanceof Toolbar)
                return child;
        }
        returnnull;
    }

    publicintgetStatusBarHeight() {
        intresult=0;
        intresourceId= mContext.getResources().getIdentifier("status_bar_height", "dimen", "android");

        if (resourceId > 0) {
            result = mContext.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }
} 

This is what I managed to do:

Post a Comment for "Collapsingtoolbarlayout With A Customised Behavior"