底部弹出式菜单, 可以使用PopupWindow来做,也可以用自定义View来做。当然这里采用DialogFragment来做。

DialogFragment是3.0之后引入的,使用DialogFragment,我们不用管理其生命周期,并且可以作为组件重用。比如当屏幕旋转的时候,如果PopupWindow没有dismiss掉,会抛出异常。AlertDialog则会消失,DialogFragment创建的对话框则不受影响。

概述

使用DialogFragment,需要重写onCreateView或者onCreateDialog方法,前者是通过layout下的自定义布局来创建对话框,后者则是用AlertDialog或者Dialog创建出Dialog,适用于创建简单的对话框。

如果同时复写onCreateViewonCreateDialog会报如下异常,

AndroidRuntimeException: requestFeature() must be called before adding content

通过查看DialogFragment的源码,我们发现会有下面的注释

     * This method will be called after {@link #onCreate(Bundle)} and* before {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.  The* default implementation simply instantiates and returns a {@link Dialog}* class.

那这句异常的意思是什么呢?具体可以参见stackoverflow:
http://stackoverflow.com/questions/13257038/custom-layout-for-dialogfragment-oncreateview-vs-oncreatedialog/15602648#15602648
http://stackoverflow.com/questions/27045451/dialog-fragment-is-crashing

You can override both (in fact the DialogFragment says so), the problem comes when you try to inflate the view after having already creating the dialog view. You can still do other things in onCreateView, like use the savedInstanceState, without causing the exception.

可以看出onCreateDialog优先于onCreateView执行,如果我们复写了这两个方法,那么对话框是在onCreateDialog中创建的,但是我们依然可以在onCreateView中做状态保存等操作。

onCreateDialog

这个回调方法是DialogFragment独有的,通过它返回的是一个Dialog对象,这个对象就会被显示到屏幕上。

AlertDialog.Builder builder = new AlertDialog.Builder(this);builder.setView(R.layout.dialog_fragment_item);builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();}});builder.show();

Activity中我们可以通过如下两种方式将对话框展示出来

 BottomDialogFragment bottomDialogFragment = (BottomDialogFragment) Fragment.instantiate(this, BottomDialogFragment.class.getName());getSupportFragmentManager().beginTransaction().add(bottomDialogFragment, "bottomDialogFragment").commitAllowingStateLoss();break;

或者:

BottomDialogFragment dialog = new BottomDialogFragment();  dialog.show(getSupportFragmentManager(), "bottomDialogFragment");

onCreateView

通过onCreateView自定义布局展示对话框。生命周期同Fragment,同时,支持FragmentManager 事务

  • 布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="30dp"android:orientation="horizontal"><ImageView
        android:id="@android:id/icon"android:layout_width="50dp"android:layout_height="match_parent"android:adjustViewBounds="true"android:padding="5dp"android:src="@mipmap/ic_launcher" /><TextView
        android:id="@android:id/text1"android:layout_width="match_parent"android:layout_height="wrap_content"android:ellipsize="marquee"android:padding="10dp"android:singleLine="true"android:text="@string/image_content"android:textSize="15sp" />
</LinearLayout>
  • java代码,
    继承DialogFragment,重写onCreateView方法
@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {if (null == fragmentRoot) {fragmentRoot = inflater.inflate(R.layout.dialog_fragment_item, container, false);}if (null != fragmentRoot) {ViewGroup parent = (ViewGroup) fragmentRoot.getParent();if (null != parent)parent.removeAllViews();}return fragmentRoot;}

去标题

去标题有两种方式,通过 代码 或者 通过 theme

  • 代码设置,需要用到DialogFragment.STYLE_NO_TITLE

  • 主题设置,需要在style.xml中使用NoActionBar属性。

 <item name="windowNoTitle">true</item>

注意

一. 如果使用onCreateDialog 创建对话框时,可以通过如下方式设置style

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.BottomDialog);

同时,可以在onCreateDialog 通过Dialog 对象获取Window 对象,并设置相关属性

dialog = builder.create();
Window window = dialog.getWindow();

二. 如果使用 onCreateView 创建对话框,则设置 style 的方式将有所变化.

  • 必须在onCreateView 中获取window 对象,并设置Window 的相关属性,在onCreate 中设置无效
 getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
  • 必须在onCreate 中设置Style ,而在OnCreateView 中设置无效,因为此时对话框已经init
 setStyle(DialogFragment.STYLE_NO_TITLE, R.style.BottomDialog);

位置控制

像很多UI都采用底部弹出的效果,比如展示菜单,分享等操作,我们都知道Dialog是展示在屏幕中央,而且宽度是没有填充屏幕的,其实我们只要给dialog设置一个LayoutParams即可。

ps:

 @NonNull@Overridepublic Dialog onCreateDialog(Bundle savedInstanceState) {AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.BottomDialog);LayoutInflater inflater = getActivity().getLayoutInflater();View view = inflater.inflate(R.layout.dialog_fragment_layout, null);initView(view);builder.setView(view);dialog = builder.create();dialog.setCanceledOnTouchOutside(true);// 设置宽度为屏宽、靠近屏幕底部。Window window = dialog.getWindow();WindowManager.LayoutParams wlp = window.getAttributes();wlp.gravity = Gravity.BOTTOM;window.setAttributes(wlp);return dialog;}

上面是通过设置了Gravity.BOTTOM来实现在屏幕下方显示。默认情况下DialogFragment是现实在屏幕中间的,我们如果想要改变其现实位置,同理,也可以用此方法。

比如,在屏幕中间靠上显示,可以这样设置。

        Window window = dialog.getWindow();WindowManager.LayoutParams wlp = window.getAttributes();wlp.gravity = Gravity.TOP;// 这里是坐标值,即离屏幕上方距离是100wlp.y = 100;window.setAttributes(wlp);

我们发现在DialogFragment 弹出的时候,左右两边会留白,这是所有Dialog
都有的,本来试过通过LayoutParams控制,当时失败,之后找到了解决办法
相关代码

@Override public void onStart() {super.onStart();Dialog dialog = getDialog();if (null != dialog) {dialog.getWindow().setLayout(-1, -2);}}

DialogFragment动画

这里涉及到了一个theme,主要是设置动画的,dialog自下而上的弹出来

<!--屏幕底部的dialog--><style name="BottomDialog" parent="AppTheme"><item name="android:windowNoTitle">true</item><item name="android:windowIsFloating">true</item><!-- Dialog进入及退出动画 --><item name="android:windowAnimationStyle">@style/BottomToTopAnim</item></style>
<style name="BottomToTopAnim" parent="android:Animation"><item name="@android:windowEnterAnimation">@anim/bottomview_anim_enter</item><item name="@android:windowExitAnimation">@anim/bottomview_anim_exit</item></style>

enter动画:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><translate
        android:duration="@android:integer/config_mediumAnimTime"android:fromYDelta="100%p"android:toYDelta="0%p" /><alpha
        android:duration="@android:integer/config_mediumAnimTime"android:fromAlpha="0.0"android:toAlpha="1.0" />
</set>

exit动画:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"><translate
        android:duration="@android:integer/config_mediumAnimTime"android:fromYDelta="0%p"android:toYDelta="100%p" /><alpha
        android:duration="@android:integer/config_mediumAnimTime"android:fromAlpha="1.0"android:toAlpha="0.3" />
</set>

防止重复弹出

我们都知道,如果我们点击一个按钮弹出一个对话框,如果每次都是新建Dialog ,则会出现重叠现象,在FragmentManager中有一个方法isAdded()可以用来判断此 Dialog是否被添加,同时,为了减少相同Dialog 的创建,我们并不需要每次都new 一个出来,并通过isAdded()来判断是否添加,减少不必要的消耗

 public static BottomDialogFragment showDialog(AppCompatActivity appCompatActivity) {FragmentManager fragmentManager = appCompatActivity.getSupportFragmentManager();BottomDialogFragment bottomDialogFragment =(BottomDialogFragment) fragmentManager.findFragmentByTag(TAG);if (null == bottomDialogFragment) {bottomDialogFragment = newInstance();}if (!appCompatActivity.isFinishing()&& null != bottomDialogFragment&& !bottomDialogFragment.isAdded()) {fragmentManager.beginTransaction().add(bottomDialogFragment, TAG).commitAllowingStateLoss();}return bottomDialogFragment;}

实例demo:
BottomDialogFragment @[Github]

Android DialogFragment实现底部弹出菜单效果相关推荐

  1. android+底部评论框,Android 之BottomsheetDialogFragment仿抖音评论底部弹出对话框效果(实例代码)...

    实现的效果图: 自定义Fragment继承BottomSheetDialogFragment 重写它的三个方法: onCreateDialog() onCreateView() onStart() 他 ...

  2. jquery底部弹出菜单_带有jQuery的新鲜底部滑出菜单

    jquery底部弹出菜单 View demo 查看演示Download Source 下载源 In this tutorial we will create a unique bottom slide ...

  3. Android编程:底部弹出输入框

    Android编程:底部弹出的对话框 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境: 主机:WIN10 开发环境:Android Studio ...

  4. Android——完全自定义 底部弹出支付页面

    近期博主在网上随便搜了一番,发现很多实现 底部弹出支付页面的大多数都用的,自定义PopupWindow 去实现的,里面复杂的逻辑看得我不想看,很多对自定义不熟悉伙伴们,看到 自定义 这三个字就有种血脉 ...

  5. Axure RP实例教程:组合弹出菜单效果

    Axure RP 9 Mac这款原型设计软件能让设计者快速创建应用软件,或者在web网站的线框图.流程图.原型和规格的设计制作,从低到高的视觉和交互保真度的全方位构建,是目前业界首屈一指的交互式产品原 ...

  6. android 底部弹窗失效,Android实现从底部弹出Dialog(和PopWindow实现的效果同样)

    布局文件:dialog_custom_layout.xmlandroid android:orientation="vertical" android:layout_width=& ...

  7. android 仿ios 底部弹出,项目需求讨论-仿ios底部弹框实现及分析

    hi,在项目开发中,有时候需要仿照ios的底部弹框做效果,比如我们在iPhone上面关闭定位的时候,就会弹出ios特有的底部弹框: 屏幕快照 2017-10-09 08.20.30 PM.png 弹框 ...

  8. 简单利用Dialog实现Ios从底部弹出的效果,合QQ空间里面的发表说说弹出拍照的效果类似

    前面项目赶得紧,有个从底部往上弹出的效果,我想都没想就用PopWindow去实现了,但是实现后发现效果不太理想.没办法了,只能用Dialog来做的.现在主要就是实现下面这个效果: 在实现这个效果前,我 ...

  9. flutter向上动画弹出菜单效果

    题记 -- 执剑天涯,从你的点滴积累开始,所及之处,必精益求精. 重要消息[视频教程 感兴趣的伙伴可以瞅瞅] 本文章最后的效果如下: 如上图的效果,当点击菜单按钮时,子菜单向上动画弹出,然后当点击弹出 ...

最新文章

  1. Python垂直翻转图像(Vertically Flip Image)
  2. 零基础学python这本书怎么样-看了这本基础教程的书籍你还担心你的python学不好吗?...
  3. 基于HTML5 WebGL实现 json工控风机叶轮旋转
  4. VC++ 限制窗口的大小范围的方法
  5. C/C++中指针和引用之相关问题研究
  6. [19/06/07-星期五] CSS基础_布局定位背景样式
  7. 【目标识别】SIFT算法理论部分
  8. android 约束 布局_Android约束布局动画
  9. sap供应商主数据表_SAP供应商统驭科目调整操作说明
  10. ios6.x 插件介绍及常用源
  11. 【SQL基础-4】SQL语句练习实例—在SQLzoo平台练习
  12. 【量子机器学习】HHL算法: Quantum algorithm for solving linear systems of equations
  13. 商城APP开发关键板块
  14. 未知USB设备(设备描述符请求失败)解决方法
  15. DOCTYPE声明——标准模式与怪异模式的区别
  16. btrfs管理及应用
  17. c语言的实验题答案,大一C语言上机实验试题及答案
  18. org.springframework.boot.actuate.endpoint.EndpointId cannot be cast to java.lang.String 异常处理
  19. 平安科技寿险金服面试
  20. Kafka入门和使用

热门文章

  1. ni visa pci_希捷酷玩固态520系列1TB评测:PCI-E 4.0让游戏进一步加速
  2. 考拉海购技术支持的前世今生
  3. 高斯消元法求解方程组(要有python基础和线性代数的基础)
  4. 2022新东方考研英语百度云全程
  5. 怎么做食品安全教育培训主题班会PPT课件?
  6. C++打造传奇游戏修改器!(源码+文档)附带教学
  7. 喜事一桩|派盾科技荣获2020年杭州高新区“5050计划”政策扶持
  8. c语言x21是什么意思,vivo X21是什么接口_vivo X21充电接口是什么-太平洋IT百科手机版...
  9. 树形导航栏,由树形数据生成导航栏。
  10. 光纤耦合透镜的参数优化