您的位置:首页 > 移动开发 > IOS开发

通过DialogFragment玩转高仿IOS弹框~

2017-10-01 00:00 399 查看
新媒体管家点击上方“程序员大咖”,选择“置顶公众号”关键时刻,第一时间送达!




今天我们的目标简单可以概括为,通过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例子,如下:
// AlertDialogfindViewById(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;/*** create by heliquan at 2017年7月30日* Android 普通加载框*/public class LoadingDialog extends DialogFragment {/*** 默认点击外面无效*/private boolean onTouchOutside = false;/*** 加载框提示信息 设置默认*/private String hintMsg = "正在加载,请稍后...";/*** 设置是否允许点击外面取消** @param onTouchOutside* @return*/public LoadingDialog setOnTouchOutside(boolean onTouchOutside) {this.onTouchOutside = onTouchOutside;return this;}/*** 设置加载框提示信息** @param hintMsg*/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);// set cancel on touch outsidegetDialog().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;/*** Created by HLQ on 2017/7/31*/public class IOSLoadingDialog extends DialogFragment {/*** 默认点击外面无效*/private boolean onTouchOutside = false;/*** 加载框提示信息 设置默认*/private String hintMsg = "正在加载";/*** 设置是否允许点击外面取消** @param onTouchOutside* @return*/public IOSLoadingDialog setOnTouchOutside(boolean onTouchOutside) {this.onTouchOutside = onTouchOutside;return this;}/*** 设置加载框提示信息** @param hintMsg*/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);// set cancel on touch outsidegetDialog().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;}}
定义布局文件:
来个动画:
<animated-rotate xmlns:android="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"/>
调用方式:
// 高仿IOS加载框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;/*** 提示框 Created by HLQ on 2017/6/15*/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; // 确定 取消 可单独定制/*** 设置确定按钮内容** @param confirmMsg* @return*/public HintDialog setOnConfirmBtnText(String confirmMsg) {this.confirm = confirmMsg;return this;}/*** 设置取消按钮内容** @param cancelMsg* @return*/public HintDialog setOnCancelBtnText(String cancelMsg) {this.cancel = cancelMsg;return this;}/*** 设置是否启用单个按钮** @param isSingle* @return*/public HintDialog setIsSingleButton(boolean isSingle) {this.isSingleButton = isSingle;return this;}/*** 设置是否允许点击外面** @param onTouchOutside* @return*/public HintDialog setOnTouchOutside(boolean onTouchOutside) {this.onTouchOutside = onTouchOutside;return this;}/*** 设置标题** @param title* @return*/public HintDialog setTitle(String title) {if (!title.isEmpty()) {this.title = title;}return this;}/*** 设置内容** @param content* @return*/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);// set cancel on touch outsidegetDialog().setCanceledOnTouchOutside(onTouchOutside);View hintView = inflater.inflate(R.layout.hlq_dialog_hint, null);initView(hintView);return hintView;}/*** 初始化View** @param 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();}});}}/*** 确定点击事件** @param confirmCallback* @return*/public HintDialog setOnConfirmClickListener(HintConfirmCallback confirmCallback) {this.confirmCallback = confirmCallback;return this;}/*** 取消点击事件** @param cancelCallback* @return*/public HintDialog setOnCancelClickListener(HintCancelCallback cancelCallback) {this.cancelCallback = cancelCallback;return this;}/*** 单个按钮点击事件** @param singleCallback* @return*/public HintDialog setOnSingleClickListener(HintSingleCallback singleCallback) {this.singleCallback = singleCallback;return this;}/*** 确认回调*/public interface HintConfirmCallback {void onClick();}/*** 取消回调*/public interface HintCancelCallback {void onClick();}/*** 单个按钮回调*/public interface HintSingleCallback {void onClick();}}
编写布局文件
主布局;
单个按钮布局;
对应的按下样式文件;
俩个按钮布局;
对应按下样式;
左侧;
右侧。

调用方式
// 提示框findViewById(R.id.btn_ios_hint_dialog).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {hintDialog.setContent("确定要离开吗?");hintDialog.setOnConfirmClickListener(new HintDialog.HintConfirmCallback() {@Overridepublic void onClick() {hintDialog.dismiss();Toast.makeText(selfActivity, "点击确定", Toast.LENGTH_SHORT).show();}});hintDialog.setOnCancelClickListener(new HintDialog.HintCancelCallback() {@Overridepublic void onClick() {hintDialog.dismiss();Toast.makeText(selfActivity, "点击取消", Toast.LENGTH_SHORT).show();}});hintDialog.show(selfActivity.getFragmentManager(), "hintDialog");}});// 单个提示框findViewById(R.id.btn_ios_single_hint_dialog).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {singleHintDialog.setContent("请认真填写相关信息,谢谢合作~").setIsSingleButton(true);singleHintDialog.setOnSingleClickListener(new HintDialog.HintSingleCallback() {@Overridepublic void onClick() {singleHintDialog.dismiss();Toast.makeText(selfActivity, "点击确认~", Toast.LENGTH_SHORT).show();}});singleHintDialog.show(selfActivity.getFragmentManager(), "singleHintDialog");}});
对外提供方法如下:setTitle() 设置标题 ,默认为“提示”;setContent() 设置内容;setIsSingleButton() 是否启用单个按钮模式;setOnTouchOutside() 是否允许点击外面消失 默认不允许仿IOS选择照片 选取相册首先明确实现过程,如下:继承DialogFragment,重写onCreateView,并设置底部显示;设置布局文件以及按下效果;对外提供监听回调~

来自:https://github.com/HLQ-Struggle/IOSDialog

程序员大咖整理发布,转载请联系作者获得授权


[b]

【点击成为安卓大神】
[/b]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: