前情提要: 原来的页面为普通的activity,业务已经成熟。但是最新的UI需要修改成BottomSheetDialog半模态样式。而用BottomSheetDialog实现代价较大,所以改用Activity实现。
改造过程: 分析BottomSheetDialog实现方式。
分析主要依赖CoordinatorLayout 及com.google.android.material.bottomsheet.BottomSheetBehavior
实现结果: xml布局
activity_bottom_sheet.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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">
<FrameLayout
android:id="@+id/design_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bottom_sheet_bg"
app:behavior_fitToContents="false"
app:behavior_hideable="true"
app:behavior_skipCollapsed="true"
app:layout_behavior="@string/bottom_sheet_behavior">
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
BottomSheetActivity.java
public class BottomSheetActivity extends AppCompatActivity {
protected FrameLayout mBottomSheet;
protected BottomSheetBehavior mBehavior;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
//改造入场动画
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
//设置状态栏颜色
setStatusBarTransparent();
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
}
private void setStatusBarTransparent() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
);
getWindow().setStatusBarColor(0x00000000);
getWindow().setNavigationBarColor(getColor(R.color.bottom_sheet_bg));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
getWindow().setNavigationBarDividerColor(getColor(R.color.bottom_sheet_bg));
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
@Override
public void setContentView(View view) {
super.setContentView(view);
}
@Override
public void setContentView(int layoutResID) {
View contentView = getLayoutInflater().inflate(layoutResID, null);
View rootView = getLayoutInflater().inflate(R.layout.activity_bottom_sheet, null);
mBottomSheet = rootView.findViewById(R.id.design_bottom_sheet);
mBottomSheet.addView(contentView);
mBehavior = BottomSheetBehavior.from(mBottomSheet);
mBehavior.setExpandedOffset(getStatusBarHeight(this));
mBehavior.setSkipCollapsed(true);
mBottomSheet.setPadding(0, 0, 0, getStatusBarHeight(this));
mBottomSheet.post(new Runnable() {
@Override
public void run() {
BottomSheetUtils.setBottomSheetAnimationDuration(BottomSheetActivity.this,mBehavior,700);
mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
mBehavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
BottomSheetActivity.super.finish();
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
super.setContentView(rootView);
}
public static int getStatusBarHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
@Override
public void finish() {
if (mBehavior != null) {
mBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
}
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
}
}
fade_in.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
fade_out.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
使用方式*
1.直接继承BottomSheetActivity
注意
1.在contentview中滑动的view必须是继承nestscroll,不然会引起滑动冲突,支持recycleview但不支持listview。