Pankaj Negi
Pankaj Negi

Reputation: 1618

Collapsing Toolbar Layout using ConstraintLayout

I am trying to implement Collapsing Toolbar By Using ConstraintLayout. After Trying a lot, I couldn't able to get the desire effects.I have follow this link in youtube (https://www.youtube.com/watch?v=8lAXJ5NFXTM at the 21 min). My Source code is:-

activity.main.xml:-

    <android.support.design.widget.CoordinatorLayout xmlns: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:context=".activities.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/app_bar_height"
        android:theme="@style/AppTheme.AppBarOverlay"
        android:fitsSystemWindows="false">

        <com.example.study.helpers.NoAnimCollapsibleConstraintLayout
            xmlns: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:id="@+id/root"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            android:minHeight="40dp"
            app:layout_scrollFlags="scroll|enterAlways|snap|exitUntilCollapsed"/>

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

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@drawable/ic_border_color_white_24dp"/>

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

content_main.xml:-

    <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns: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"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".activities.MainActivity"
    tools:showIn="@layout/activity_main">


    <TextView
        android:id="@+id/textView3"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="@string/some_long_text"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

NoAnimCollapsibleConstraintLayout.java:-

import android.content.Context;
import android.support.constraint.ConstraintLayout;
import android.support.constraint.ConstraintSet;
import android.support.design.widget.AppBarLayout;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.Toast;
import com.example.study.R;

public class NoAnimCollapsibleConstraintLayout extends ConstraintLayout implements AppBarLayout.OnOffsetChangedListener {

    private static final String TAG = NoAnimCollapsibleConstraintLayout.class.getSimpleName();
    private float mTransitionThreshold = 0.35f;
    private int mLastPosition = 0;
    private boolean mToolbarOpen = true;

    private ConstraintSet mOpenToolbarSet = new ConstraintSet();
    private ConstraintSet mCloseToolbarSet = new ConstraintSet();

    public NoAnimCollapsibleConstraintLayout(Context context) { super(context, null); }

    public NoAnimCollapsibleConstraintLayout(Context context, AttributeSet attrs) { super(context, attrs, 0); }

    public NoAnimCollapsibleConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (getParent() instanceof AppBarLayout){
            Log.d(TAG, "Instance AppBarLayout");
            AppBarLayout appBarLayout = (AppBarLayout)getParent();
            appBarLayout.addOnOffsetChangedListener(this);
            mOpenToolbarSet.clone(getContext(), R.layout.open);
            mCloseToolbarSet.clone(getContext(), R.layout.close);

        }else {
            Log.d(TAG, "Instance if Not Parent");
        }
    }

    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
        Log.d(TAG, "onOffsetChanged");
        if (mLastPosition == verticalOffset){
            return;
        }

        mLastPosition = verticalOffset;
        Float progress =  ( Math.abs(verticalOffset / (float) (appBarLayout.getHeight()))) ;

        AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) getLayoutParams();
        params.topMargin = -verticalOffset;
        setLayoutParams(params);

        if ( mToolbarOpen && progress > mTransitionThreshold) {
            Log.d(TAG, "Apply close.xml");
            mCloseToolbarSet.applyTo(this);
            mToolbarOpen = false;
        }else if ( !mToolbarOpen && progress < mTransitionThreshold){
            Log.d(TAG, "Apply open.xml");
            mOpenToolbarSet.applyTo(this);
            mToolbarOpen = true;

        }
    }
}

open.xml:-

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns: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:id="@+id/open"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:contentDescription="@string/app_name"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/study" />

</android.support.constraint.ConstraintLayout>

close.xml:-

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns: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:id="@+id/close"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <TextView
        android:id="@+id/textView4"
        android:layout_width="0dp"
        android:layout_height="30dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="@string/app_name"
        android:textColor="@android:color/white"
        android:textSize="@dimen/text_size_16"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

After Applying this code open.xml and close.xml design not shown when I am trying to collapse Toolbar. This is the screenshot which I am getting in output:-

Without Collapse (open.xml design missing) :- https://www.dropbox.com/s/c0rh126rinmopd4/Screen_Shot1.png?dl=0)

With Collpase (close.xml design missing):- https://www.dropbox.com/s/cdlbg84lmht3gv0/Screen_Shot2.png?dl=0

Upvotes: 1

Views: 2541

Answers (1)

RuAware
RuAware

Reputation: 969

I've been trying to do the same thing after watching the video.

Add the id "constraint" to both root ConstraintLayout

You did inflate your view in NoAnimCollapsibleConstraintLayout, so inflate and then find constraint view

import android.content.Context;
import android.support.constraint.ConstraintLayout;
import android.support.constraint.ConstraintSet;
import android.support.design.widget.AppBarLayout;
import android.support.transition.TransitionManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;

public class NoAnimCollapsibleConstraintLayout extends ConstraintLayout
    implements AppBarLayout.OnOffsetChangedListener {

  private static final String TAG = NoAnimCollapsibleConstraintLayout.class.getSimpleName();
  private float mTransitionThreshold = 0.35f;
  private int mLastPosition = 0;
  private boolean mToolbarOpen = true;

  private ConstraintSet mOpenToolbarSet = new ConstraintSet();
  private ConstraintSet mCloseToolbarSet = new ConstraintSet();
  private ConstraintLayout constraint;

  public NoAnimCollapsibleConstraintLayout(Context context) {
    this(context, null);
  }

  public NoAnimCollapsibleConstraintLayout(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public NoAnimCollapsibleConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    LayoutInflater.from(getContext()).inflate(R.layout.open, this, true);
    constraint = findViewById(R.id.constraint);
  }

  @Override
  protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    if (getParent() instanceof AppBarLayout) {
      Log.d(TAG, "Instance AppBarLayout");
      AppBarLayout appBarLayout = (AppBarLayout) getParent();
      appBarLayout.addOnOffsetChangedListener(this);
      mOpenToolbarSet.clone(constraint);
      mCloseToolbarSet.clone(getContext(), R.layout.close);
    } else {
      Log.d(TAG, "Instance if Not Parent");
    }
  }

  @Override
  public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
    Log.d(TAG, "onOffsetChanged");
    if (mLastPosition == verticalOffset) {
      return;
    }

    mLastPosition = verticalOffset;
    Float progress = (Math.abs(verticalOffset / (float) (appBarLayout.getHeight())));

    AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) getLayoutParams();
    params.topMargin = -verticalOffset;
    setLayoutParams(params);
    TransitionManager.beginDelayedTransition(constraint);
    if (mToolbarOpen && progress > mTransitionThreshold) {
      Log.d(TAG, "Apply close.xml");
      mCloseToolbarSet.applyTo(constraint);
      mToolbarOpen = false;
    } else if (!mToolbarOpen && progress < mTransitionThreshold) {
      Log.d(TAG, "Apply open.xml");
      mOpenToolbarSet.applyTo(constraint);
      mToolbarOpen = true;
    }
  }
}

This has an animation in and it seems to work for me. try and make sure the same view is in both, even if it is just to move it or visibility gone

EDIT: https://github.com/BigFishStudios/ConstraintToolbar here is a code example of this working

Hope this helps :D

Upvotes: 3

Related Questions