关键时刻,第一时间送达!
今天我们的目标简单可以概括为,通过DialogFragment高仿IOS弹框效果并对外公开,让大家可以通过一个地址调用,具体分为以下三部分:
-
玩转DialogFragment;
-
高仿IOS弹框效果;
玩转DialogFragment
在此,不知道的大家可能会说,DialogFragment这是什么鬼?哈哈,主要LZ之前是真心没了解过这个东东,恕我孤陋寡闻~
下面为大家简单介绍下,主要还是LZ自己回顾下~ ^_^
DialogFragment简介
DialogFragment是在Android3.0(API level 11)中引入的,主要是为了替代AlertDialog(重点)。
DialogFragment优势
DialogFragment和Fragment生命周期基本一致,方便管理;
完美兼容横竖屏切换,让你想怎么切,就怎么切~而我们之前使用的AlertDialog就out了~
话说上面说到我们之前玩转的AlertDialog对于横竖屏切换有点弱,有的伙伴说了,光说不练假把式,来个demo瞅瞅~
论:DialogFragment于AlertDialog横竖屏切换对比
首先编写一个AlertDialog例子,如下:
findViewById(R.id.btn_alert_dialog).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {new AlertDialog.Builder(selfActivity).setTitle("测试标题").setMessage("Hello Word~!").setPositiveButton("哈喽", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {dialogInterface.dismiss();}}).show();}});
接着编写一个简单的DialogFragment例子,如下:
定义LoadingDialog类
package cn.hlq.iosdialog.manager;import android.app.DialogFragment;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.Window;import android.widget.TextView;import cn.hlq.iosdialog.R;public class LoadingDialog extends DialogFragment {private boolean onTouchOutside = false;private String hintMsg = "正在加载,请稍后...";public LoadingDialog setOnTouchOutside(boolean onTouchOutside) {this.onTouchOutside = onTouchOutside;return this;}public LoadingDialog setHintMsg(String hintMsg) {if (!hintMsg.isEmpty()) {this.hintMsg = hintMsg;}return this;}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {getDialog().getWindow().setBackgroundDrawableResource(android.R.color.transparent);getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);getDialog().setCanceledOnTouchOutside(onTouchOutside);View loadingView = inflater.inflate(R.layout.hlq_android_dialog_loading, container);TextView hintTextView = loadingView.findViewById(R.id.tv_loading_dialog_hint);hintTextView.setText(hintMsg);return loadingView;}}
代码编写完毕后,下面为大家附上对比图:
错误日志如下:
08-06 13:23:35.774 3403-3403/cn.hlq.iosdialog E/WindowManager: android.view.WindowLeaked: Activity cn.hlq.iosdialog.MainActivity has leaked window com.android.internal.policy.PhoneWindow$DecorView{eca8948 V.E...... R....... 0,0-1368,632} that was originally added hereat android.view.ViewRootImpl.(ViewRootImpl.java:368)at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:299)at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)at android.app.Dialog.show(Dialog.java:319)at android.app.AlertDialog$Builder.show(AlertDialog.java:1112)at cn.hlq.iosdialog.MainActivity$1.onClick(MainActivity.java:40)at android.view.View.performClick(View.java:5198)at android.view.View$PerformClick.run(View.java:21147)at android.os.Handler.handleCallback(Handler.java:739)at android.os.Handler.dispatchMessage(Handler.java:95)at android.os.Looper.loop(Looper.java:148)at android.app.ActivityThread.main(ActivityThread.java:5417)at java.lang.reflect.Method.invoke(Native Method)at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
消失原因为,切换屏幕时,dialog没有被重新创建,从而造成窗口泄露。如果依然要使用AlertDialog而且不想横竖屏切换消失,LZ提供最简单方法去解决: 切换屏幕时候重新创建AlertDilog。(哈哈,不要打我~)
高仿IOS弹框效果
首先还是老规矩,看看效果,不然说不过去哈~
录制的效果不是很好,稍微有点模糊,Sorry~我们将依次为大家介绍,瞧好吧您那~
仿IOS加载框 -> 传说中菊花转~
首先要明确一个实现过程,具体如下:1.继承DialogFragment,重写onCreateView();2.编写布局文件,动画;简单概括如上,下面依次附上源码,比较简单~
定义IOSLoadingDialog菊花转类:
package cn.hlq.iosdialog.manager;import android.app.DialogFragment;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.Window;import android.widget.TextView;import cn.hlq.iosdialog.R;public class IOSLoadingDialog extends DialogFragment {private boolean onTouchOutside = false;private String hintMsg = "正在加载";public IOSLoadingDialog setOnTouchOutside(boolean onTouchOutside) {this.onTouchOutside = onTouchOutside;return this;}public IOSLoadingDialog setHintMsg(String hintMsg) {if (!hintMsg.isEmpty()) {this.hintMsg = hintMsg;}return this;}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {getDialog().getWindow().setBackgroundDrawableResource(android.R.color.transparent);getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);getDialog().setCanceledOnTouchOutside(onTouchOutside);View loadingView = inflater.inflate(R.layout.hlq_ios_dialog_loading, container);TextView hintTextView = loadingView.findViewById(R.id.tv_ios_loading_dialog_hint);hintTextView.setText(hintMsg);return loadingView;}}
定义布局文件:
略
来个动画:
"http://schemas.android.com/apk/res/android"android:drawable="@drawable/ic_ios_loading"android:fromDegrees="0.0"android:pivotX="50.0%"android:pivotY="50.0%"android:toDegrees="-360.0"/>
调用方式:
findViewById(R.id.btn_ios_loading_dialog).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {IOSLoadingDialog iosLoadingDialog = new IOSLoadingDialog().setOnTouchOutside(true);iosLoadingDialog.show(selfActivity.getFragmentManager(), "iosLoadingDialog");}});
回过头,我们来瞅瞅对外提供的方法:
设置是否允许点击外面取消;> 默认为false,可以通过setOnTouchOutside()设置是否允许点击外面取消。设置加载框提示信息;> 默认为“正在加载”,可以通过setHintMsg()传入需要设置加载框提示信息。
仿IOS提示框
关于提示框,常用的一般有俩种类型,如下:
1.提供用户俩个按钮,可确定或取消;2.只提供一个按钮,主要用于相关提示,提醒。而实现流程,相对来说比较简单,今天主要是通过ViewStub去控制不同的显示隐藏,简单概括如下:1.继承DialogFragment,重写onCreateView;2.编写俩个按钮以及单个按钮布局;3.新增按下效果,对外开放相关方法内容。
编写HintDialog类
package cn.hlq.iosdialog.manager;import android.app.DialogFragment;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.ViewStub;import android.view.Window;import android.widget.TextView;import cn.hlq.iosdialog.R;public class HintDialog extends DialogFragment {private TextView tvTitle; private TextView tvContent; private TextView tvCancelTextView; private TextView tvConfirmTextView; private TextView tvSingleTextView; private HintConfirmCallback confirmCallback;private HintCancelCallback cancelCallback;private HintSingleCallback singleCallback;private boolean isSingleButton = false; private boolean onTouchOutside = false;private String title = "提示";private String content;private String confirm, cancel; public HintDialog setOnConfirmBtnText(String confirmMsg) {this.confirm = confirmMsg;return this;}public HintDialog setOnCancelBtnText(String cancelMsg) {this.cancel = cancelMsg;return this;}public HintDialog setIsSingleButton(boolean isSingle) {this.isSingleButton = isSingle;return this;}public HintDialog setOnTouchOutside(boolean onTouchOutside) {this.onTouchOutside = onTouchOutside;return this;}public HintDialog setTitle(String title) {if (!title.isEmpty()) {this.title = title;}return this;}public HintDialog setContent(String content) {this.content = content;return this;}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {getDialog().getWindow().setBackgroundDrawableResource(android.R.color.transparent);getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);getDialog().setCanceledOnTouchOutside(onTouchOutside);View hintView = inflater.inflate(R.layout.hlq_dialog_hint, null);initView(hintView);return hintView;}private void initView(View hintView) {tvTitle = hintView.findViewById(R.id.tv_hint_dialog_title);tvContent = hintView.findViewById(R.id.tv_hint_dialog_content);tvTitle.setText(title);tvContent.setText(content);if (isSingleButton) {ViewStub vsSingleButton = hintView.findViewById(R.id.vs_single_button);vsSingleButton.inflate();tvSingleTextView = hintView.findViewById(R.id.tv_single);tvSingleTextView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {singleCallback.onClick();}});} else {ViewStub vsDoubleButton = hintView.findViewById(R.id.vs_double_button);vsDoubleButton.inflate();tvCancelTextView = hintView.findViewById(R.id.btn_hint_dialog_cancle);tvConfirmTextView = hintView.findViewById(R.id.btn_hint_dialog_confirm);if (!"".equals(confirm) && confirm != null) {tvConfirmTextView.setText(confirm);}if (!"".equals(cancel) && cancel != null) {tvCancelTextView.setText(cancel);}tvConfirmTextView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {confirmCallback.onClick();}});tvCancelTextView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {cancelCallback.onClick();}});}}public HintDialog setOnConfirmClickListener(HintConfirmCallback confirmCallback) {this.confirmCallback = confirmCallback;return this;}