BottomSheet:从底部滑出的dialog,解决上一篇中的bug
BottomSheet : Android 5.0的Material Design中的新的设计方案
详解:http://www.google.com/design/spec/components/bottom-sheets.html#/
本次只用来实现退出功能。
在上一篇中,通过设置的dialog的windowEnterAnimation和windowExitAnimation实现的dialog的进入和退出动画。
其中存在一个不足,即在navigation bars(back,home,menu)是虚拟按键的设备上,dialog是从navigation bars的底部滑出,穿过了navigation bars,目标效果是在navigation bars上面滑出。
解决方案
不使用dialog的enter和exit动画,对dialog内部的layout添加动画。
设计模式:创建者设计模式,仿照AlertDialog
示例代码如下:
public class MyBottomSheetDialog extends Dialog implements View.OnClickListener {
@ViewInject(id = R.id.bottom_sheet_dialog_positive_layout, click = true)
LinearLayout positiveClickLayout;
@ViewInject(id = R.id.bottom_sheet_dialog_negative_layout, click = true)
LinearLayout negativeClickLayout;
@ViewInject(id = R.id.bottom_sheet_dialog_title)
TextView titleTextView;
@ViewInject(id = R.id.bottom_sheet_dialog_layout)
LinearLayout dialogLayout;
@ViewInject(id = R.id.positive_textView)
TextView positiveTextView;
@ViewInject(id = R.id.negative_textView)
TextView negativeTextView;
MyDialogClickListener positiveClickListener;
MyDialogClickListener negativeClickListener;
public MyBottomSheetDialog(Context context) {
super(context, R.style.MyDialogStyle);
init();
}
private void init() {
Window window = this.getWindow();
//去掉dialog自己的title
window.requestFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.layout_bottom_sheet_dialog);
//ViewInject框架 不用去写findviewById了
ViewInjectUtils.initInjectedView(this, window.getDecorView());
//去掉dialog默认的padding
window.getDecorView().setPadding(0, 0, 0, 0);
window.getDecorView().setBackgroundColor(getContext().getResources().getColor(R.color.fully_tr ansparent));
WindowManager.LayoutParams lp = window.getAttributes();
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
//位置设置到底部
lp.gravity = Gravity.BOTTOM;
window.setAttributes(lp);
}
public void setTitle(String title) {
titleTextView.setText(title);
}
private void upAnimation() {
TranslateAnimation animUp = new TranslateAnimation(
TranslateAnimation.RELATIVE_TO_SELF, 0,
TranslateAnimation.RELATIVE_TO_SELF, 0,
TranslateAnimation.RELATIVE_TO_SELF, 1,
TranslateAnimation.RELATIVE_TO_SELF, 0);
animUp.setInterpolator(new DecelerateInterpolator());
animUp.setDuration(100);
animUp.setFillAfter(true);
dialogLayout.startAnimation(animUp);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bottom_sheet_dialog_positive_layout:
positiveClick();
break;
case R.id.bottom_sheet_dialog_negative_layout:
negativeClick();
break;
}
}
@Override
public void dismiss() {
negativeClick();
}
private void positiveClick() {
TranslateAnimation animDown = new TranslateAnimation(
TranslateAnimation.RELATIVE_TO_SELF, 0,
TranslateAnimation.RELATIVE_TO_SELF, 0,
TranslateAnimation.RELATIVE_TO_SELF, 0,
TranslateAnimation.RELATIVE_TO_SELF, 1);
animDown.setInterpolator(new AccelerateInterpolator());
animDown.setDuration(100);
animDown.setFillAfter(true);
animDown.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
MyBottomSheetDialog.super.dismiss();
if (positiveClickListener != null) {
positiveClickListener.onClick();
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
dialogLayout.startAnimation(animDown);
}
private void negativeClick() {
TranslateAnimation animDown = new TranslateAnimation(
TranslateAnimation.RELATIVE_TO_SELF, 0,
TranslateAnimation.RELATIVE_TO_SELF, 0,
TranslateAnimation.RELATIVE_TO_SELF, 0,
TranslateAnimation.RELATIVE_TO_SELF, 1);
animDown.setInterpolator(new AccelerateInterpolator());
animDown.setDuration(100);
animDown.setFillAfter(true);
animDown.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
MyBottomSheetDialog.super.dismiss();
if (negativeClickListener != null) {
negativeClickListener.onClick();
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
dialogLayout.startAnimation(animDown);
}
public interface MyDialogClickListener {
void onClick();
}
public void setPositiveClickListener(MyDialogClickListener myDialogClickListener) {
this.positiveClickListener = myDialogClickListener;
}
public void setNegativeClickListener(MyDialogClickListener myDialogClickListener) {
this.negativeClickListener = myDialogClickListener;
}
public void setPositiveTextView(String text) {
positiveTextView.setText(text);
}
public void setNegativeTextView(String text) {
negativeTextView.setText(text);
}
public static class Builder {
private MyBottomSheetDialog bottomSheetDialog;
public Builder(Context context) {
bottomSheetDialog = new MyBottomSheetDialog(context);
}
public MyBottomSheetDialog show() {
bottomSheetDialog.show();
bottomSheetDialog.upAnimation();
return bottomSheetDialog;
}
public Builder setPositiveButton(String positiveText, MyDialogClickListener myDialogClickListener1) {
bottomSheetDialog.setPositiveTextView(positiveText);
bottomSheetDialog.setPositiveClickListener(myDialogClickListener1);
return this;
}
public Builder setNegativeButton(String negativeText, MyDialogClickListener myDialogClickListener) {
bottomSheetDialog.setNegativeTextView(negativeText);
bottomSheetDialog.setNegativeClickListener(myDialogClickListener);
return this;
}
public Builder setTitle(String title) {
bottomSheetDialog.setTitle(title);
return this;
}
}
}
xml布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="@+id/bottom_sheet_dialog_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@null">
<include
layout="@layout/layout_top_shadow_for_alarm_list_item"
android:id="@+id/logout_dialog_top_shadow"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:background="@color/white"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:layout_height="56dp">
<TextView
android:id="@+id/bottom_sheet_dialog_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:textColor="@color/black_54_opacity"
android:textSize="16sp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/bottom_sheet_dialog_positive_layout"
android:layout_width="match_parent"
android:background="@drawable/white_button_click_selector"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:layout_height="48dp">
<ImageView
android:src="@drawable/icon_logout_color_24dp"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/positive_textView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="32dp"
android:gravity="center_vertical"
android:textColor="@color/black_87_opacity"
android:textSize="16sp"/>
</LinearLayout>
<LinearLayout
android:id="@+id/bottom_sheet_dialog_negative_layout"
android:background="@drawable/white_button_click_selector"
android:layout_width="match_parent"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:layout_marginBottom="8dp"
android:layout_height="48dp">
<ImageView
android:src="@drawable/ic_close_black_24dp"
android:layout_width="wrap_content"
android:alpha="0.54"
android:layout_gravity="center_vertical"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/negative_textView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="32dp"
android:gravity="left|center_vertical"
android:textColor="@color/black_87_opacity"
android:textSize="16sp"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
下面是Google对UI的一些标准尺寸:
外部调用,如AlertDialog一样:
new MyBottomSheetDialog.Builder(context)
.setTitle(title)
.setNegativeButton(getString(R.string.cancel), null)
.setPositiveButton(getString(R.string.logout), new MyBottomSheetDialog.MyDialogClickListener() {
@Override
public void onClick() {
mInterface.onLogOut();
}
}).show();