【发布时间】:2019-07-27 18:37:45
【问题描述】:
我想压缩一个“ViewGroup”,正如您在视频中看到的那样。同时,我想在 ViewGroup 的原始位置淡出内容。即不将内容推到右侧。
知道如何实现吗?
谢谢!
【问题讨论】:
-
查看github.com/hujiaweibujidao/FabDialogMorph。我猜你必须做类似的事情。
我想压缩一个“ViewGroup”,正如您在视频中看到的那样。同时,我想在 ViewGroup 的原始位置淡出内容。即不将内容推到右侧。
知道如何实现吗?
谢谢!
【问题讨论】:
您可以使用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" 参数。这就是为什么它看起来是正确的并且底部边界没有改变。