android仿ios弹框 带动画效果,通过DialogFragment玩转高仿IOS弹框~

原标题:通过DialogFragment玩转高仿IOS弹框~

前言

LZ虽说是搞Android的,但是对IOS的风格样式甚是酷爱,感觉简约大方,而今天,我们通过DialogFragment一起开启高仿之路~篇幅所限,文章有删减,可以点击左下角“阅读原文”查看全部内容。

本文目标

今天我们的目标简单可以概括为,通过DialogFragment高仿IOS弹框效果并对外公开,让大家可以通过一个地址调用,具体分为以下三部分:

玩转DialogFragment;

高仿IOS弹框效果;

上传jcenter,方便有需要的人直接compile。

玩转DialogFragment

在此,不知道的大家可能会说,DialogFragment这是什么鬼?哈哈,主要LZ之前是真心没了解过这个东东,恕我孤陋寡闻~

下面为大家简单介绍下,主要还是LZ自己回顾下~ ^_^

DialogFragment简介

DialogFragment是在Android3.0(API level 11)中引入的,主要是为了替代AlertDialog(重点)。

DialogFragment优势

DialogFragment和Fragment生命周期基本一致,方便管理;

完美兼容横竖屏切换,让你想怎么切,就怎么切~而我们之前使用的AlertDialog就out了~

话说上面说到我们之前玩转的AlertDialog对于横竖屏切换有点弱,有的伙伴说了,光说不练假把式,来个demo瞅瞅~

论:DialogFragment于AlertDialog横竖屏切换对比

首先编写一个AlertDialog例子,如下:

// AlertDialog findViewById(R.id.btn_alert_dialog).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { new AlertDialog.Builder(selfActivity).setTitle("测试标题").setMessage("Hello Word~!").setPositiveButton("哈喽", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { dialogInterface.dismiss(); } }).show(); } });

接着编写一个简单的DialogFragment例子,如下:

1. 定义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; } @Override public 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 outside 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; }}

代码编写完毕后,下面为大家附上对比图:

2e3406416483a19fa56c3accd821d3db.gif

错误日志如下:

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 here at 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弹框效果

首先还是老规矩,看看效果,不然说不过去哈~

e8aa6e8157e2fdb9c15f58b4835e8a8a.gif

录制的效果不是很好,稍微有点模糊,Sorry~我们将依次为大家介绍,瞧好吧您那~

仿IOS加载框 -> 传说中菊花转~

首先要明确一个实现过程,具体如下:

1.继承DialogFragment,重写onCreateView();

2.编写布局文件,动画;

简单概括如上,下面依次附上源码,比较简单~

1. 定义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; } @Override public 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 outside 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; }}

2. 定义布局文件:

3. 来个动画:

4. 调用方式:

// 高仿IOS加载框 findViewById(R.id.btn_ios_loading_dialog).setOnClickListener(new View.OnClickListener() { @Override public 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.新增按下效果,对外开放相关方法内容。

1. 编写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; } @Override public 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 outside getDialog().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() { @Override public 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() { @Override public void onClick(View v) { confirmCallback.onClick(); } }); tvCancelTextView.setOnClickListener(new View.OnClickListener() { @Override public 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(); }}

2. 编写布局文件

主布局;

单个按钮布局;

对应的按下样式文件;

俩个按钮布局;

对应按下样式;

左侧;

右侧。

3. 调用方式

// 提示框 findViewById(R.id.btn_ios_hint_dialog).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { hintDialog.setContent("确定要离开吗?"); hintDialog.setOnConfirmClickListener(new HintDialog.HintConfirmCallback() { @Override public void onClick() { hintDialog.dismiss(); Toast.makeText(selfActivity, "点击确定", Toast.LENGTH_SHORT).show(); } }); hintDialog.setOnCancelClickListener(new HintDialog.HintCancelCallback() { @Override public 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() { @Override public void onClick(View view) { singleHintDialog.setContent("请认真填写相关信息,谢谢合作~").setIsSingleButton(true); singleHintDialog.setOnSingleClickListener(new HintDialog.HintSingleCallback() { @Override public void onClick() { singleHintDialog.dismiss(); Toast.makeText(selfActivity, "点击确认~", Toast.LENGTH_SHORT).show(); } }); singleHintDialog.show(selfActivity.getFragmentManager(), "singleHintDialog"); } });

对外提供方法如下:

setTitle() 设置标题 ,默认为“提示”;

setContent() 设置内容;

setIsSingleButton() 是否启用单个按钮模式;

setOnTouchOutside() 是否允许点击外面消失 默认不允许

仿IOS选择照片 选取相册

首先明确实现过程,如下:

继承DialogFragment,重写onCreateView,并设置底部显示;

设置布局文件以及按下效果;

对外提供监听回调~

仿IOS选择照片选取相册与

项目Github地址:

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

责任编辑:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值