Android自定义Dialog带Dialog的显示消失动画(一)
来源:互联网 发布:中华书局 知乎 编辑:程序博客网 时间:2024/05/01 20:51
效果图
博客绝大时候还是为了记录自己的一些想法,跟心得,我也不指望有什么人看我的博客,我抽空回来往往能提醒自己要学的还有很多,在自定义一个组件之前,最好得先明白这个组件的工作原理,在之前曾发了一个自定义Toast的文章
这里对于Toast就不赘述了,当一个Dialog弹出的时候,处于下面的Activity会失去焦点, 负责显示Dialog的布局接受所有的用户交互.Dialog的官方API
在看Dialog源码之前先说下Android的UI视图层
当我们调用Dialog的show方法的时候系统会做哪些事情,我们点开源码看一下
public void show() { if (mShowing) { if (mDecor != null) { if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) { mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR); } mDecor.setVisibility(View.VISIBLE); } return; } mCanceled = false; if (!mCreated) { dispatchOnCreate(null); } onStart(); mDecor = mWindow.getDecorView(); if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) { final ApplicationInfo info = mContext.getApplicationInfo(); mWindow.setDefaultIcon(info.icon); mWindow.setDefaultLogo(info.logo); mActionBar = new WindowDecorActionBar(this); } WindowManager.LayoutParams l = mWindow.getAttributes(); if ((l.softInputMode & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) { WindowManager.LayoutParams nl = new WindowManager.LayoutParams(); nl.copyFrom(l); nl.softInputMode |= WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION; l = nl; } try { mWindowManager.addView(mDecor, l); mShowing = true; sendShowMessage(); } finally { } }
我们可以直接参考系统的AlertDialog来自定义自己的Dialog,系统的AlertDialog采用了Builder模式来构造,我们也参考系统的这种方式来定义我们的Dialog,上我们的代码,要调用的几个比较核心的方法
1,将我们想要让Dialog显示的View添加到phonewindow中,addContentView只是一个view的叠加,不会删除之前的View /** * Add an additional content view to the screen. Added after any existing * ones in the screen -- existing views are NOT removed. * * @param view The desired content to display. * @param params Layout parameters for the view. */ public void addContentView(View view, ViewGroup.LayoutParams params) { mWindow.addContentView(view, params); }
2,"预显示"我们添加到phoneWindow的View,setContentView会将之前的View给移除掉,显示当前的View /** * Set the screen content to an explicit view. This view is placed * directly into the screen's view hierarchy. It can itself be a complex * view hierarchy. * * @param view The desired content to display. */ public void setContentView(View view) { mWindow.setContentView(view); }
"我们的Dialog"public class CustomDialog extends Dialog { public CustomDialog(Context context) { super(context); } public CustomDialog(Context context, int themeResId) { super(context, themeResId); } protected CustomDialog(Context context, boolean cancelable, OnCancelListener cancelListener) { super(context, cancelable, cancelListener); } //用Builder模式来构造Dialog public static class Builder { private Context mContext; private View contentView; private String title; private String message; private String positiveText; private String negativeText; private DialogInterface.OnClickListener positiviOnclickListener; private DialogInterface.OnClickListener negativeOnclickListener; public Builder(Context mContext) { this.mContext = mContext; } public Builder setContentView(View contentView) {//设置dialog的主view this.contentView = contentView; return this; } public Builder setTitle(String title) {//设置dialog的标题 this.title = title; return this; } public Builder setMessage(String msg) {//设置dialig的内容 this.message = msg; return this; } public Builder setPositiveButton(String text, DialogInterface.OnClickListener positiviOnclickListener) {//dialog的确认按钮 this.positiveText = text; this.positiviOnclickListener = positiviOnclickListener; return this; } public Builder setNegativeButton(String text, DialogInterface.OnClickListener negativeOnclickListener) {//dialog的取消按钮 this.negativeText = text; this.negativeOnclickListener = negativeOnclickListener; return this; } /** * 1,加载要显示的布局 * 2,通过dialog的addContentView将布局添加到window中 * 3,基本逻辑处理 * 4,显示dialog的布局 */ public CustomDialog build() { LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); final CustomDialog mCustomDialog = new CustomDialog(mContext, R.style.CustomDialog);//默认调用带style的构造 mCustomDialog.setCanceledOnTouchOutside(false);//默认点击布局外不能取消dialog View view = mInflater.inflate(R.layout.custom_dialog, null); mCustomDialog.addContentView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));//将我们的View添加到phonewindow里,这句话最后调用的是window.addContentView(view); if (!TextUtils.isEmpty(title)) { TextView titleView = (TextView) view.findViewById(R.id.tv_title); titleView.setText(title); } if (!TextUtils.isEmpty(positiveText)) {//这是确认按钮 Button btn_cofirm = (Button) view.findViewById(R.id.btn_confirm); btn_cofirm.setText(positiveText); if (positiviOnclickListener != null) { btn_cofirm.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { positiviOnclickListener.onClick(mCustomDialog, BUTTON_POSITIVE); } }); } } else { view.findViewById(R.id.btn_confirm).setVisibility(View.GONE); } if (!TextUtils.isEmpty(negativeText)) {//这是取消按钮逻辑处理 Button btn_cancle = (Button) view.findViewById(R.id.btn_cancle); btn_cancle.setText(negativeText); if (negativeOnclickListener != null) { btn_cancle.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { negativeOnclickListener.onClick(mCustomDialog, BUTTON_NEGATIVE); } }); } } else { view.findViewById(R.id.btn_cancle).setVisibility(View.GONE); } if (!TextUtils.isEmpty(message)) { TextView messageView = (TextView) view.findViewById(R.id.tv_message); messageView.setText(message);//显示的内容 } else if (contentView != null) {//如果内容区域要显示其他的View的话 LinearLayout mContentLayout = (LinearLayout) view.findViewById(R.id.content); mContentLayout.removeAllViews(); mContentLayout.addView(contentView); } mCustomDialog.setContentView(view); return mCustomDialog; } }}
"Dialog的布局文件"<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:background="@drawable/dialog_shape" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:orientation="vertical" > <TextView android:id="@+id/tv_title" android:layout_width="fill_parent" android:layout_height="40dp" android:gravity="center" android:text="title" android:visibility="visible" /> <LinearLayout android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/dialog_shape" android:gravity="center" > <TextView android:id="@+id/tv_message" android:text="message" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="left|center" android:minHeight="120dp" android:paddingBottom="20dp" android:paddingLeft="20dp" android:paddingRight="20dp" android:paddingTop="15dp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="60dp" android:layout_gravity="bottom" android:gravity="center" android:orientation="horizontal" > <Button android:id="@+id/btn_confirm" android:layout_width="114dp" android:layout_height="40dp" android:gravity="center" android:text="确认" /> <Button android:id="@+id/btn_cancle" android:layout_width="120dp" android:layout_height="40dp" android:layout_marginLeft="20dp" android:gravity="center" android:text="取消" /> </LinearLayout> </LinearLayout></FrameLayout>
另外是Dialog的动画跟shape
"进入动画,从左进"<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromXDelta="-100%p" android:toXDelta="0" android:fromYDelta="0" android:toYDelta="0" android:duration="1000" /></set>"从右出"<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromXDelta="0" android:toXDelta="100%p" android:fromYDelta="0" android:toYDelta="0" android:duration="1000" /></set> <style name="Dialog_Anim_Style" parent="android:Animation" > <item name="@android:windowEnterAnimation">@anim/left_in</item> //进入时的动画 <item name="@android:windowExitAnimation">@anim/left_out</item> //退出时的动画 </style>
"Dialog的shape及Style""shape"<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <stroke android:width="1px" android:color="@android:color/black" /> <solid android:color="@android:color/background_light" /></shape>"style" <style name="CustomDialog" parent="android:style/Theme.Dialog"> <item name="android:background">#00000000</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowNoTitle">true</item> <item name="android:windowIsFloating">true</item> </style>
调用我们的Dialog
public class MainActivity extends AppCompatActivity { private CustomDialog mDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); setContentView(R.layout.activity_main); mDialog = new CustomDialog.Builder(this).setTitle("标题").setMessage("这是内容") .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (mDialog != null && mDialog.isShowing()) mDialog.dismiss(); } }).setPositiveButton("确认", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "确认", Toast.LENGTH_SHORT).show(); } }).build(); mDialog.getWindow().setWindowAnimations(R.style.Dialog_Anim_Style); } public void showDialog(View view) { if (mDialog != null && !mDialog.isShowing()) mDialog.show(); }}
最后把源码献上吧,源码在这
4 1
- Android自定义Dialog带Dialog的显示消失动画(一)
- android 自定义dialog 带动画的
- Android 自定义带动画的dialog
- Android Dialog使用、自定义带动画的Dialog使用
- android 自定义dialog弹出和消失动画
- android 自定义dialog弹出和消失动画
- android 自定义dialog弹出和消失动画
- android 自定义dialog弹出和消失动画
- android 自定义dialog弹出和消失缩放动画
- android 自定义带关闭按钮的dialog
- Android自定义底部带有动画的Dialog
- Android 自定义dialog 和 相应的动画
- 自定义Android中Dialog的弹出动画
- 设置dialog显示,自定义时间到后dialog消失
- android dialog和activity 改变出现消失的 动画样式
- 自定义dialog和弹出dialog的动画
- 10.自定义Dialog--dialog的动画
- android开发设置Dialog出现消失动画
- jquery validate自定义扩展实例,以及一些常用验证
- 批处理
- spark中RDD的transformation&action
- Light OJ 1354 IP Checking
- Spark三种属性配置方式详细说明
- Android自定义Dialog带Dialog的显示消失动画(一)
- spark shell的学习
- 委托开发合同与合作开发合同的区别
- Spark Shell各种操作及详细说明
- spark rdd 转换过程
- 机器学习实战--kMeans
- jvm最终配置
- Spark 启动脚本——启动总结
- Spark 启动脚本——sbin/slaves.sh