根布局上的活动过渡动画在每次 EditText 单击时执行

Posted

技术标签:

【中文标题】根布局上的活动过渡动画在每次 EditText 单击时执行【英文标题】:Activity transition animation on root layout is executing on every EditText click 【发布时间】:2017-05-29 07:10:13 【问题描述】:

我在活动过渡上应用显示效果,当 startActivity 被称为通过显示效果显示的活动时。 Activity是注册Activity,包含3个editText、一个imageView和一个拍照按钮。

问题是每当我选择或单击editText时,就会应用显示效果动画。

动画应用于根布局,动画在 OnCreate 方法中启动,我也尝试通过其他生命周期方法(如 onStart 和 onResume 方法)应用动画,但它正在工作。

很高兴地接受了答案。 这是代码的快照。

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_add_contact);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    Name = (EditText) findViewById(R.id.enter_name_id);
    Mobile = (EditText) findViewById(R.id.enter_mobile_id);
    Email = (EditText) findViewById(R.id.enter_email_id);
    imageView = (ImageView) findViewById(R.id.set_image);

    LinearLayout rootview = (LinearLayout) findViewById(R.id.rootview);

    rootview.addOnLayoutChangeListener(new View.OnLayoutChangeListener() 
    
        @Override
        public void onLayoutChange(View v, int left, int top, int right, 
        int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) 
        

            float finalRadius=
            (float)Math.hypot(v.getWidth(),v.getHeight());
            int cx1 = (v.getLeft() + v.getRight()) / 2;
            int cy1 = (v.getTop() + v.getBottom()) / 2;
            Animator anim = ViewAnimationUtils.createCircularReveal(v, 
            cx1, cy1, 0, finalRadius);
            anim.setDuration(1000);
            anim.setInterpolator(new AccelerateDecelerateInterpolator());
            anim.start();
        
    );

【问题讨论】:

【参考方案1】:

您可以使用 globalLayoutListener 等待:

final LinearLayout rootview = (LinearLayout) findViewById(R.id.rootview);
rootview .getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() 
@Override
public void onGlobalLayout() 
    rootview .getViewTreeObserver().removeOnGlobalLayoutListener(this);
    // remove listener
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) 
        //noinspection deprecation
        imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
     else 
        imageView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    

    float finalRadius=
    (float)Math.hypot(rootview.getWidth(),rootview.getHeight());
    int cx1 = (rootview.getLeft() + rootview.getRight()) / 2;
    int cy1 = (rootview.getTop() + rootview.getBottom()) / 2;
    Animator anim = ViewAnimationUtils.createCircularReveal(v, 
    cx1, cy1, 0, finalRadius);
    anim.setDuration(1000);
    anim.setInterpolator(new AccelerateDecelerateInterpolator());
    anim.start();

);

您可能不需要检查您不支持的旧版本 id 低于 JELLY_BEAN

【讨论】:

我正在为根布局而不是图像视图应用侦听器,或者你的意思是我必须将代码的 imageView 替换为 rootView... ...?????。我没有得到解释请。 监听器可以添加到任何视图中,当布局完成时,它只会被调用一次 嗨,我有一个问题,下面的代码(sarthak Gandhi)也可以正常工作。在这两个答案中,哪一个是高效的......? 这个更好,因为它只在布局完成时被调用,下面的 done 等待任意超时,所以在最好的情况下它等待太久,在最坏的情况下,它不会等待足够长的时间,根本不起作用。 Tx 解释一下。【参考方案2】:

你可以这样试试

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);

    ...
    ...

    final LinearLayout rootview = (LinearLayout) findViewById(R.id.rootview);
    ViewTreeObserver observer = rootview.getViewTreeObserver();

    if (observer.isAlive()) 
        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() 
            @Override
            public void onGlobalLayout() 
                showLayout(rootview)
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) 
                    rootview.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                 else 
                    rootview.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                
            
        );
    

    ...
    ...


private void showLayout(@NonNull View v) 
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) 
        circularReveal(v);
     else 
        v.setVisibility(View.VISIBLE);
    


@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void circularReveal(@NonNull final View v) 
    float finalRadius = (float) Math.hypot(v.getWidth(), v.getHeight());
    int cx1 = (v.getLeft() + v.getRight()) / 2;
    int cy1 = (v.getTop() + v.getBottom()) / 2;
    Animator anim = ViewAnimationUtils.createCircularReveal(v, cx1, cy1, 0, finalRadius);
    anim.setDuration(1000);
    anim.setInterpolator(new AccelerateDecelerateInterpolator());
    v.setVisibility(View.VISIBLE);
    anim.start();

在xml父布局中放这个android:visibility="invisible"

【讨论】:

【参考方案3】:

问题是,每当您单击图像或编辑文本时,都会调用 onLayoutChange 方法。只需在 onCreate 中开始您的动画,而不是将其放入 onLayoutChanged 中。

    root.post(new Runnable() 
        @Override
        public void run() 
            float finalRadius =
                    (float) Math.hypot(root.getWidth(), root.getHeight());
            int cx1 = (root.getLeft() + root.getRight()) / 2;
            int cy1 = (root.getTop() + root.getBottom()) / 2;
            Animator anim = ViewAnimationUtils.createCircularReveal(root,
                    cx1, cy1, 0, finalRadius);
            anim.setDuration(1000);
            anim.setInterpolator(new AccelerateDecelerateInterpolator());
            anim.start();
        
    );

请试试这个。

【讨论】:

我厌倦了它,但它给出了运行时异常。 Caused by: java.lang.IllegalStateException: Cannot start this animator on a detached view! 在这一行 Animator anim = ViewAnimationUtils.createCircularReveal(v, cx1, cy1, 0, finalRadius);

以上是关于根布局上的活动过渡动画在每次 EditText 单击时执行的主要内容,如果未能解决你的问题,请参考以下文章

Vue显示和隐藏的过渡动画

发生布局更改时动画

布局上的动画?

从 Button 到 EditText 的转换

从另一个活动返回时,MapFragment 的地图加载滞后

在 BottomSheetFragment 上重复 ConstraintSet 的过渡动画问题