📅  最后修改于: 2023-12-03 15:00:41.313000             🧑  作者: Mango
本示例演示如何使用 FloatingActionButton (Fab) 将一个菜单展开到 CircularRevealFrameLayout 中。
在开始本示例之前,您应该已经熟悉以下内容:
将以下依赖项添加到您的 build.gradle
文件中:
implementation 'com.android.support:design:28.0.0'
在布局文件中添加以下代码:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/content_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:padding="24dp">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/fab_margin_bottom"
android:layout_marginEnd="@dimen/fab_margin_end"
android:src="@drawable/ic_add_white_24dp"
app:backgroundTint="@color/colorPrimary"
app:fabSize="normal" />
<android.support.constraint.ConstraintLayout
android:id="@+id/hidden_content_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible">
<!-- 折叠的菜单内容在这里添加 -->
</android.support.constraint.ConstraintLayout>
<View
android:id="@+id/overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:alpha="0"
android:onClick="@{() -> viewModel.hideMenu()}"
android:visibility="@{viewModel.showMenu ? View.VISIBLE : View.GONE}" />
</android.support.constraint.ConstraintLayout>
在此布局中:
fab
是 FloatingActionButton ,表示要展开菜单项的按钮。hidden_content_container
是展开的菜单项的容器,初始时设置为 invisible
。overlay
是一个黑色的 View,用于在展开菜单时遮盖其背后的内容。创建新的 Java 文件并添加以下代码:
public class CircularRevealHelper {
public static void showMenu(View menuContainer, View anchorView) {
AnimatorSet showAnimations = new AnimatorSet();
int cx = (anchorView.getLeft() + anchorView.getRight()) / 2;
int cy = (anchorView.getTop() + anchorView.getBottom()) / 2;
int finalRadius = Math.max(menuContainer.getWidth(), menuContainer.getHeight());
Animator anim = ViewAnimationUtils.createCircularReveal(menuContainer, cx, cy, 0, finalRadius);
anim.setInterpolator(new AccelerateInterpolator());
anim.setDuration(300);
ObjectAnimator overlayAnimator = ObjectAnimator.ofFloat(anchorView.getRootView().findViewById(R.id.overlay), View.ALPHA, 0, 0.5f);
overlayAnimator.setDuration(300);
overlayAnimator.setStartDelay(300);
menuContainer.setVisibility(View.VISIBLE);
showAnimations.playTogether(anim, overlayAnimator);
showAnimations.start();
}
public static void hideMenu(View menuContainer, View anchorView) {
AnimatorSet hideAnimations = new AnimatorSet();
int cx = (anchorView.getLeft() + anchorView.getRight()) / 2;
int cy = (anchorView.getTop() + anchorView.getBottom()) / 2;
int initialRadius = menuContainer.getWidth() / 2;
Animator anim = ViewAnimationUtils.createCircularReveal(menuContainer, cx, cy, initialRadius, 0);
anim.setInterpolator(new AccelerateInterpolator());
anim.setDuration(300);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
menuContainer.setVisibility(View.INVISIBLE);
}
});
ObjectAnimator overlayAnimator = ObjectAnimator.ofFloat(anchorView.getRootView().findViewById(R.id.overlay), View.ALPHA, 0.5f, 0);
overlayAnimator.setDuration(300);
hideAnimations.playTogether(anim, overlayAnimator);
hideAnimations.start();
}
}
这个类提供两个静态方法:
showMenu()
在给定的 anchorView 处展开菜单。hideMenu()
关闭菜单并将其折叠回 anchorView 处。创建一个新的 ViewModel 文件并添加以下代码:
public class MainViewModel extends ViewModel {
private MutableLiveData<Boolean> showMenu = new MutableLiveData<>();
private MutableLiveData<View.OnClickListener> fabClickListener = new MutableLiveData<>();
public MainViewModel() {
showMenu.setValue(false);
fabClickListener.setValue(v -> showMenu());
}
public LiveData<Boolean> getShowMenu() {
return showMenu;
}
public LiveData<View.OnClickListener> getFabClickListener() {
return fabClickListener;
}
public void showMenu() {
showMenu.setValue(true);
}
public void hideMenu() {
showMenu.setValue(false);
}
}
这里创建了一个 MainViewModel
类,其中包含两个 LiveData: showMenu
和 fabClickListener
。这个类的构造函数将 showMenu
的初始值设置为 false
。
接下来,在您的 Activity 或 Fragment 中初始化该 ViewModel:
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private MainViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
binding.setViewModel(viewModel);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(v -> viewModel.getFabClickListener().getValue().onClick(v));
}
}
在这里,使用 DataBindingUtil
来设置 Activity 的布局,并获取 MainViewModel
实例。接下来,您将视图绑定到该 ViewModel,并将 ViewModel 中的 fabClickListener
属性添加到实际的悬浮按钮上。
最后,在您的 Activity 或 Fragment 中,将 showMenu
属性观察到,并根据其值展开或折叠菜单:
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private MainViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
binding.setViewModel(viewModel);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(v -> viewModel.getFabClickListener().getValue().onClick(v));
viewModel.getShowMenu().observe(this, show -> {
View menuContainer = findViewById(R.id.hidden_content_container);
if (show) {
CircularRevealHelper.showMenu(menuContainer, fab);
} else {
CircularRevealHelper.hideMenu(menuContainer, fab);
}
});
}
}
在这里,您可以使用 CircularRevealHelper
类来实现展开和折叠菜单的动画。此代码块将观察到 showMenu
属性的更改,并相应地调用 showMenu()
或 hideMenu()
方法。
使用本示例,您可以将一个菜单展开到 CircularRevealFrameLayout 中。此示例演示了如何使用 FloatingActionButton、CircularReveal 动画和 ConstraintLayout 来实现该效果。