java - 从按钮过渡到 EditText

标签 java android animation android-animation android-transitions

我想在我的 android views 中有一个 transition view 是 Button 而另一个是 EditText,过渡必须像这个动画

Button to EditText Transitions

我试过这种方式

布局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">

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

预览是

Java代码是

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()));

    }
}

但是使用这段代码,结果转换是

My Resulting transition

如您所见,与预期相比这有点奇怪,任何人都可以建议我进行一些更改以获得所需的过渡。

最佳答案

Transitions API 确实是个好东西,但它不能为您解决所有问题。您还没有指示过渡框架如何执行该动画,它怎么会知道您要执行的最终动画是什么?

我不确定仅使用 Transitions API 可以实现此动画。相反,您可以坚持使用标准动画 API,例如ValueAnimator.

动画由几个阶段组成。单击按钮时,您希望它变得稍微宽一些,同时也失去其透明度。完成此操作后,您希望 EditText 进入场景并从按钮所在的宽度开始动画到其最终值。

因此,在按钮内部点击监听器:


    @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();
    }

EditText 返回到按钮时会执行类似的操作:


    @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();
    }

editTextWidthbuttonWidth 是 View 的初始大小:


    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();
            }
        });
    }

这是输出:

enter image description here

你可以得到修改后的补丁文件here .

关于java - 从按钮过渡到 EditText,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46616821/

相关文章:

java - Spring 中的改造自动配置

java - 如何在不覆盖默认 spring-cache 的情况下创建辅助 CacheManager

php - 使用 csrf token 从 android 应用程序访问 laravel 应用程序

android - 启动 Android 设备监视器时找不到 hprof-conv

java - 斯坦福 CoreNLP 仅在 Windows 上失败

java - 如何将应用程序图标应用到 Theme.DeviceDefault.Light.DarkActionBar?

android - PolarSSl bignum.c 在 Android 5.0 及以上版本使用 JNI 时会导致崩溃

javascript - 你能用Javascript控制GIF动画吗?

android - Android ProgressBar 上的背景动画图像?

javascript - jQuery animate() 与 addClass() 移动元素