【问题标题】:Animating the parent view without animating the child view动画父视图而不动画子视图
【发布时间】:2019-07-27 18:37:45
【问题描述】:

我想做这样的事情: https://storage.googleapis.com/spec-host/mio-staging%2Fmio-design%2F1563837804615%2Fassets%2F1XlKhaQFU9aS84ACmF-EDjVKDgI4pPldv%2F02-overflowmenu.mp4

我想压缩一个“ViewGroup”,正如您在视频中看到的那样。同时,我想在 ViewGroup 的原始位置淡出内容。即不将内容推到右侧。

知道如何实现吗?

谢谢!

【问题讨论】:

标签: android android-animation


【解决方案1】:

您可以使用Transition API 制作此类动画。声明两个ViewGroups:第一个是水平的,带有剪切/复制按钮,第二个是垂直的,带有搜索/共享按钮。然后用TransitionManager 切换这些ViewGroups。然后只需提供Transition,它描述了第一个和第二个ViewGroups 上的视图如何出现和消失。

import androidx.appcompat.app.AppCompatActivity;
import androidx.transition.ChangeBounds;
import androidx.transition.Fade;
import androidx.transition.Scene;
import androidx.transition.Slide;
import androidx.transition.Transition;
import androidx.transition.TransitionManager;
import androidx.transition.TransitionSet;

public class MainActivity extends AppCompatActivity {

    private ViewGroup mSceneRoot;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_layout);
        mSceneRoot = findViewById(R.id.sceneRoot);

        showPopup1();
    }

    private void showPopup1() {
        ViewGroup popup1 = (ViewGroup) getLayoutInflater().inflate(R.layout.popup_1, mSceneRoot, false);
        popup1.findViewById(R.id.btnGo).setOnClickListener(v -> {
            showPopup2();
        });

        Scene scene = new Scene(mSceneRoot, popup1);
        TransitionManager.go(scene, getTransition(false));
    }

    private void showPopup2() {
        ViewGroup popup2 = (ViewGroup) getLayoutInflater().inflate(R.layout.popup_2, mSceneRoot, false);
        popup2.findViewById(R.id.btnBack).setOnClickListener(v -> {
            showPopup1();
        });

        Scene scene = new Scene(mSceneRoot, popup2);
        TransitionManager.go(scene, getTransition(true));
    }
}

activity_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/sceneRoot"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="bottom|right"
    android:orientation="vertical"
    android:paddingBottom="150dp"
    android:paddingRight="50dp"
    android:clipToPadding="false"
    android:clipChildren="false"/>

popup_1.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/popup1"
    android:layout_width="250dp"
    android:layout_height="wrap_content"
    android:transitionName="bg"
    app:cardElevation="10dp">

    <Button
        android:id="@+id/btnGo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:text="go"
        android:transitionName="btn_go"/>
</androidx.cardview.widget.CardView>

popup_2.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/popup2"
    android:layout_width="wrap_content"
    android:layout_height="250dp"
    android:transitionName="bg"
    app:cardElevation="10dp">

    <Button
        android:id="@+id/btnBack"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="back"
        android:transitionName="btn_back"/>
</androidx.cardview.widget.CardView>

这里的最后一件事是getTransition 方法。您可以使用AutoTransition,它可以轻松处理布局更改。

private Transition getTransition(boolean open) {
      return new AutoTransition();
}

结果:

也只是为了演示,我编写了更复杂的过渡,其中第一个视图组上的按钮出现/消失,Slide 动画。

 private Transition getTransition(boolean open) {
        Slide btnGo = new Slide(Gravity.RIGHT);
        btnGo.addTarget("btn_go");

        ChangeBounds bgBounds = new ChangeBounds();
        bgBounds.addTarget("bg");

        Fade btnBack = new Fade();
        btnBack.addTarget("btn_back");

        TransitionSet set = new TransitionSet();
        set.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
        if (open) {
            set.addTransition(btnGo);
            set.addTransition(bgBounds);
            set.addTransition(btnBack);
        } else {
            set.addTransition(btnBack);
            set.addTransition(bgBounds);
            set.addTransition(btnGo);
        }
        return set;
    }

结果:

注意transitionName 的背景在两种布局中应该相同。 这里的所有转换类都来自androix 包,因此代码是向后兼容的。但是如果你需要支持棒棒糖之前的设备,你应该通过ViewCompat.setTransitionName 方法设置transitionName

您可以检查my another answer 更难/自定义的过渡。

【讨论】:

  • 感谢您的详细回答。我有一个后续问题。因此,在您的示例中,右侧和底部边界保持不变,而我们更改了顶部和左侧边界。这是默认的吗?如果我们愿意,有没有办法改变它?谢谢。
  • ChangeBounds 转换将视图边界从第一个视图组中的边界更改为第二个视图组中的边界。在这个例子中,我将两个视图组的右下角放在同一个位置。检查activity_layout.xmlandroid:gravity="bottom|right" 参数。这就是为什么它看起来是正确的并且底部边界没有改变。
猜你喜欢
  • 1970-01-01
  • 2019-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多