9

I want to have a transition in my android views on view is Button and other is EditText, transitions must be like this animation

Button to EditText Transitions

I tried in this way

Layout xml is

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="app.itc.org.todo.MainActivity">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:weightSum="2">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="vertical"
            android:background="@android:color/white"
            android:gravity="center_horizontal|center_vertical">

            <TextView
                android:id="@+id/title_tv"
                android:text="@string/to_do"
                android:textSize="22sp"
                android:textStyle="bold"
                android:textColor="@android:color/black"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"/>

            <TextView
                android:id="@+id/date_tv"
                android:textSize="16sp"
                android:textColor="@android:color/darker_gray"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />


        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="@color/colorGray"
            android:gravity="center_horizontal|center_vertical"
            android:orientation="vertical">

            <TextView
                android:text="@string/what_do_you_want_to_do_today"
                android:textSize="16sp"
                android:textColor="@android:color/darker_gray"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"/>

            <TextView
                android:text="@string/start_adding_items_to_your_to_do_list"
                android:textSize="16sp"
                android:textColor="@android:color/darker_gray"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>


        </LinearLayout>

    </LinearLayout>

    <FrameLayout
        android:id="@+id/transitions_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="visible">

        <Button
            android:id="@+id/add_btn"
            android:layout_width="200dp"
            android:layout_height="60dp"
            android:text="@string/add_item"
            android:textSize="18sp"
            android:paddingLeft="20dp"
            android:textColor="@android:color/white"
            android:drawableLeft="@drawable/ic_add_24dp"
            android:background="@drawable/rounded_black_bg"
            android:layout_gravity="center"/>

        <EditText
            android:id="@+id/item_input_et"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:visibility="gone"
            android:minHeight="50dp"
            android:layout_marginLeft="@dimen/margin_30dp"
            android:layout_marginRight="@dimen/margin_30dp"
            android:paddingLeft="@dimen/dimen_20dp"
            android:paddingRight="@dimen/dimen_50dp"
            android:textColor="@android:color/black"
            android:inputType="text"
            android:background="@drawable/rounded_edit_text"
            android:layout_gravity="center"/>


    </FrameLayout>

</RelativeLayout>

Preview is

Java code is

public class MainActivity extends AppCompatActivity {

    private EditText mItemInputEditText;

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

        TextView dateTextView = (TextView) findViewById(R.id.date_tv);

        mItemInputEditText = (EditText) findViewById(R.id.item_input_et);
        final Button addButton = (Button) findViewById(R.id.add_btn);

        final ViewGroup transitionsContainer = (ViewGroup) findViewById(R.id.transitions_container);

        mItemInputEditText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {



                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    TransitionSet set = new TransitionSet()
                            .addTransition(new Fade())
                            .setInterpolator(new FastOutLinearInInterpolator());

                    TransitionManager.beginDelayedTransition(transitionsContainer, set);
                }

                addButton.setVisibility(View.VISIBLE);
                mItemInputEditText.setVisibility(View.GONE);
            }
        });

        addButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    TransitionSet set = new TransitionSet()
                            .addTransition(new Fade())
                            .setInterpolator(new FastOutLinearInInterpolator());

                    TransitionManager.beginDelayedTransition(transitionsContainer, set);
                }

                addButton.setVisibility(View.GONE);
                mItemInputEditText.setVisibility(View.VISIBLE);
            }

        });

        SimpleDateFormat dt = new SimpleDateFormat("EEE d MMM yyyy");
        dateTextView.setText(dt.format(new Date()));

    }
}

but with this code the resulting transition is

My Resulting transition

As you can see this is bit weird as compared to expected one, can any one suggest me some changes to get the desired transitions.

azizbekian
  • 60,783
  • 13
  • 169
  • 249
Arshad Ali
  • 3,082
  • 12
  • 56
  • 99

3 Answers3

16

Transitions API is surely nice thing, but it cannot solve each and everything for you. You haven't instructed how to perform that animation to the transition framework, how come it would understand what is the final animation that you want to perform?

I'm not sure this animation can be achieved using solely Transitions API. Instead, you can stick to standard animations APIs, e.g. ValueAnimator.

The animation consists of several stages. When a button is clicked, you want it to become slightly wider, also losing its transparency. And after this is done, you want the EditText to come into the scene and be animated to its final value starting from the width, where the button was landed at.

So, inside button click listener:


    @Override
    public void onClick(View v) {

        final int from = addButton.getWidth();
        final int to = (int) (from * 1.2f); // increase by 20%
        final LinearInterpolator interpolator = new LinearInterpolator();

        ValueAnimator firstAnimator = ValueAnimator.ofInt(from, to);
        firstAnimator.setTarget(addButton);
        firstAnimator.setInterpolator(interpolator);
        firstAnimator.setDuration(DURATION);

        final ViewGroup.LayoutParams params = addButton.getLayoutParams();
        firstAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                params.width = (Integer) animation.getAnimatedValue();
                addButton.setAlpha(1 - animation.getAnimatedFraction());
                addButton.requestLayout();
            }
        });

        firstAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                // reset alpha channel
                addButton.setAlpha(1.0f);
                addButton.setVisibility(View.GONE);

                mItemInputEditText.setVisibility(View.VISIBLE);

                ValueAnimator secondAnimator = ValueAnimator.ofInt(to, editTextWidth);
                secondAnimator.setTarget(mItemInputEditText);
                secondAnimator.setInterpolator(interpolator);
                secondAnimator.setDuration(DURATION);

                final ViewGroup.LayoutParams params = mItemInputEditText.getLayoutParams();
                secondAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        params.width = (Integer) animation.getAnimatedValue();
                        mItemInputEditText.requestLayout();
                    }
                });

                secondAnimator.start();
            }
        });

        firstAnimator.start();
    }

Similar actions are performed when coming back from EditText to button:


    @Override
    public void onClick(View view) {

        final int from = mItemInputEditText.getWidth();
        final int to = (int) (from * 0.8f);
        final LinearInterpolator interpolator = new LinearInterpolator();

        ValueAnimator firstAnimator = ValueAnimator.ofInt(from, to);
        firstAnimator.setTarget(mItemInputEditText);
        firstAnimator.setInterpolator(interpolator);
        firstAnimator.setDuration(DURATION);

        final ViewGroup.LayoutParams params = mItemInputEditText.getLayoutParams();
        firstAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                params.width = (Integer) animation.getAnimatedValue();
                mItemInputEditText.requestLayout();
            }
        });

        firstAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mItemInputEditText.setVisibility(View.GONE);
                addButton.setVisibility(View.VISIBLE);

                ValueAnimator secondAnimator = ValueAnimator.ofInt(to, buttonWidth);
                secondAnimator.setTarget(addButton);
                secondAnimator.setInterpolator(interpolator);
                secondAnimator.setDuration(DURATION);

                final ViewGroup.LayoutParams params = addButton.getLayoutParams();
                secondAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        params.width = (Integer) animation.getAnimatedValue();
                        addButton.setAlpha(animation.getAnimatedFraction());
                        addButton.requestLayout();
                    }
                });

                secondAnimator.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationStart(Animator animation) {
                        addButton.setAlpha(0.0f);
                    }
                });

                secondAnimator.start();
            }
        });

        firstAnimator.start();
    }

editTextWidth and buttonWidth are initial sizes of views:


    private int editTextWidth, buttonWidth;

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

        ...

        // `transitions_container` is the parent of both `EditText` and `Button`
        // Thus, posting on it ensures that both of those views are laid out when this runnable is executed
        findViewById(R.id.transitions_container).post(new Runnable() {
            @Override
            public void run() {
                editTextWidth = mItemInputEditText.getWidth();
                // `mItemInputEditText` should be left visible from XML in order to get measured
                // setting to GONE after we have got actual width
                mItemInputEditText.setVisibility(View.GONE);
                buttonWidth = addButton.getWidth();
            }
        });
    }

Here's the output:

enter image description here

You can have the patch file with changes here.

azizbekian
  • 60,783
  • 13
  • 169
  • 249
0

First, change your Layout XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="app.itc.org.todo.MainActivity">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:weightSum="2">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="vertical"
            android:background="@android:color/white"
            android:gravity="center_horizontal|center_vertical">

            <TextView
                android:id="@+id/title_tv"
                android:text="@string/to_do"
                android:textSize="22sp"
                android:textStyle="bold"
                android:textColor="@android:color/black"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"/>

            <TextView
                android:id="@+id/date_tv"
                android:textSize="16sp"
                android:textColor="@android:color/darker_gray"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />


        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="@color/colorGray"
            android:gravity="center_horizontal|center_vertical"
            android:orientation="vertical">

            <TextView
                android:text="@string/what_do_you_want_to_do_today"
                android:textSize="16sp"
                android:textColor="@android:color/darker_gray"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dp"/>

            <TextView
                android:text="@string/start_adding_items_to_your_to_do_list"
                android:textSize="16sp"
                android:textColor="@android:color/darker_gray"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>


        </LinearLayout>

    </LinearLayout>

    <FrameLayout
        android:id="@+id/transitions_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="visible">
        <include layout="@layout/a_scene" />
    </FrameLayout>

</RelativeLayout>

Then create your first scene for the button. The layout for the first scene is defined as follows:

res/layout/a_scene.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/scene_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button
            android:id="@+id/add_btn"
            android:layout_width="200dp"
            android:layout_height="60dp"
            android:text="@string/add_item"
            android:textSize="18sp"
            android:paddingLeft="20dp"
            android:textColor="@android:color/white"
            android:drawableLeft="@drawable/ic_add_24dp"
            android:background="@drawable/rounded_black_bg"
            android:layout_gravity="center"/>
</RelativeLayout>

The layout for the second scene contains editText (with the same IDs) and is defined as follows:

res/layout/another_scene.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/scene_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <EditText
                android:id="@+id/add_btn"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:visibility="gone"
                android:minHeight="50dp"
                android:layout_marginLeft="@dimen/margin_30dp"
                android:layout_marginRight="@dimen/margin_30dp"
                android:paddingLeft="@dimen/dimen_20dp"
                android:paddingRight="@dimen/dimen_50dp"
                android:textColor="@android:color/black"
                android:inputType="text"
                android:background="@drawable/rounded_edit_text"
                android:layout_gravity="center"/>
    </RelativeLayout>

Java Code:

public class MainActivity extends AppCompatActivity {

    private EditText mItemInputEditText;
    private Scene mAScene;
    private Scene mAnotherScene;

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

        TextView dateTextView = (TextView) findViewById(R.id.date_tv);

        mItemInputEditText = (EditText) findViewById(R.id.item_input_et);
        final Button addButton = (Button) findViewById(R.id.add_btn);

        final ViewGroup transitionsContainer = (ViewGroup) findViewById(R.id.transitions_container);

        // Create the scenes
        mAScene = Scene.getSceneForLayout(mSceneRoot, R.layout.a_scene, this);
        mAnotherScene = Scene.getSceneForLayout(mSceneRoot, R.layout.another_scene, this);

        mItemInputEditText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {



                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    Transition transition = new ChangeBounds();

                    TransitionManager.go(mAScene, transition);
                }

                addButton.setVisibility(View.VISIBLE);
                mItemInputEditText.setVisibility(View.GONE);
            }
        });

        addButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    Transition transition = new ChangeBounds();

                    TransitionManager.go(mAnotherScenetransition);
                }

                addButton.setVisibility(View.GONE);
                mItemInputEditText.setVisibility(View.VISIBLE);
            }

        });

        SimpleDateFormat dt = new SimpleDateFormat("EEE d MMM yyyy");
        dateTextView.setText(dt.format(new Date()));

    }
}
Sourav Bagchi
  • 656
  • 7
  • 13
0

You can use FABReveal Layout for that. Take a reference from that and change Relative layout to button. and modify it as per requirement.

XML

<com.truizlop.fabreveallayout.FABRevealLayout
    android:id="@+id/fab_reveal_layout"
    android:layout_width="match_parent"
    android:layout_height="@dimen/fab_reveal_height"
    >

    <android.support.design.widget.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:backgroundTint="@color/some_color"
        android:src="@drawable/some_drawable"
        />

    <RelativeLayout
        android:id="@+id/main_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        ...
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/secondary_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        ...
    </RelativeLayout>

</com.truizlop.fabreveallayout.FABRevealLayout>

https://github.com/truizlop/FABRevealLayout

https://github.com/saulmm/Curved-Fab-Reveal-Example

Aditya Vyas-Lakhan
  • 13,409
  • 16
  • 61
  • 96