Dialog总结


title: Dialog官方文档总结
date: 2016-03-14 21:38:14
tags: Dialog
categories: android


Dialog官方文档总结

file:///C:/MyProgram/androidprogram/adt-bundle-windows-x86_64-20140702/sdk/docs/guide/topics/ui/dialogs.html

使用 DialogFragment 来管理Dialog

  1. 创建一个类继承DialogFragment

  2. 重写onCreateDialog()方法,这个方法内创建Dialog,并将创建好的Dialog返回

     public Dialog onCreateDialog(Bundle savedInstanceState)
    
  3. 在需要的地方(activity)创建这个类的实例,调用show()方法就可以让DialogFragment出现。

创建Dialog的方法

AlertDialog.Builder

  1. Dialog分三个区域

    1. Title
    2. Content area:不能同时放message和list
    3. Action buttons:最多三个
  2. 创建AlertDialog.Builder对象

     AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    
  3. AlertDialog.Builder里面的方法

    1. setTitle()
    2. setMessage()
    3. setPositiveButton()
    4. setNegativeButton()
    5. setNeutralButton()
    6. create()
  4. 添加Button

    1. setPositiveButton()
    2. setNegativeButton()
    3. setNeutralButton()
  5. 添加List

    1. A traditional single-choice list 单选
      1. setItems()

        .setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
        // The 'which' argument contains the index position
        // of the selected item
        }

      2. setAdapter(),可能还需要Loader异步加载数据

         public Builder setAdapter(final ListAdapter adapter, final OnClickListener listener)
        
    2. A persistent single-choice list (radio buttons) 单选
      1. setSingleChoiceItems()
    3. A persistent multiple-choice list (checkboxes) 多选
      1. setMultiChoiceItems()
      2. 这里需要创建一个属性,存储点击的项目
            private ArrayList mSelectedItems;

            .setMultiChoiceItems(R.array.toppings, null,
                                      new DialogInterface.OnMultiChoiceClickListener() {
                               @Override
                               public void onClick(DialogInterface dialog, int which,
                                       boolean isChecked) {
                                   if (isChecked) {
                                       // If the user checked the item, add it to the selected items
                                       mSelectedItems.add(which);
                                   } else if (mSelectedItems.contains(which)) {
                                       // Else, if the item is already in the array, remove it 
                                       mSelectedItems.remove(Integer.valueOf(which));
                                   }
                               }
                           })

创建自定义布局

方法一:

  1. 创建xml布局文件

  2. 使用LayoutInflater创建布局文件的View

  3. setView(..)

     LayoutInflater inflater = getActivity().getLayoutInflater();
     builder.setView(inflater.inflate(R.layout.dialog_signin, null))
    

方法二:将activity作为dialog

  1. 创建一个activity

  2. 设置activity的xml属性

    <activity android:theme="@android:style/Theme.Holo.Dialog" >

Passing Events Back to the Dialog's Host, Fragment的接口回调

  1. 创建的DialogFragment子类要创建一个内部接口

     public interface NoticeDialogListener {
         public void onDialogPositiveClick(DialogFragment dialog);
         public void onDialogNegativeClick(DialogFragment dialog);
     }
    
  2. DialogFragment子类的成员属性

     NoticeDialogListener mListener;
    
  3. 重写onAttach()方法(注意选择正确的方法),这里的接口回调没有用构造方法的形式,而是将activity作为实现类利用DialogFragment的特点传入。

     // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
     @Override
     public void onAttach(Activity activity) {
         super.onAttach(activity);
         // Verify that the host activity implements the callback interface
         try {
             // Instantiate the NoticeDialogListener so we can send events to the host
             mListener = (NoticeDialogListener) activity;
         } catch (ClassCastException e) {
             // The activity doesn't implement the interface, throw exception
             throw new ClassCastException(activity.toString()
                     + " must implement NoticeDialogListener");
         }
     }
    
  4. 使用这个DialogFragment的activity需要写的代码

    接口方法重写

     @Override
     public void onDialogPositiveClick(DialogFragment dialog) {
         // User touched the dialog's positive button
         ...
     }
    
     @Override
     public void onDialogNegativeClick(DialogFragment dialog) {
         // User touched the dialog's negative button
         ...
     }
    

    不必要的方法

     public void showNoticeDialog() {
         // Create an instance of the dialog fragment and show it
         DialogFragment dialog = new NoticeDialogFragment();
         dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
     }
    
  5. 在DialogFragment子类中分配接口的方法

     mListener.onDialogPositiveClick(NoticeDialogFragment.this);
    

Showing a Dialog 显示Dialog

  1. 在需要调用的地方创建DialogFragment的子类实例
  2. 调用show(FragmentManager,Tag)方法

FragmentManager:getFragmentManager()

Tag:string 类型

作用:

  1. findFragmentByTag(),在fragment中获取fragmentManager,通过FragmentManagerfindFragmentByTag(“。。。”)获取另一个fragment实例达到两个fragment通信的功能。
  2. 在activity中启动dialog的时候调用这个方法,tag设置后可以在DialogFragment中通过getTag()方法获取tag从而知道是谁启动了这个dialogfragment。通过判断不同的tag,DialogFragment可以在onCreateDialog()方法中初始化不同界面的Dialog

Showing a Dialog Fullscreen or as an Embedded Fragment 全屏显示Dialog,内嵌Dialog

public void showDialog() {
    FragmentManager fragmentManager = getSupportFragmentManager();
    CustomDialogFragment newFragment = new CustomDialogFragment();
    
    if (mIsLargeLayout) {
        // The device is using a large layout, so show the fragment as a dialog
        newFragment.show(fragmentManager, "dialog");
    } else {
        // The device is smaller, so show the fragment fullscreen
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        // For a little polish, specify a transition animation
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        // To make it fullscreen, use the 'content' root view as the container
        // for the fragment, which is always the root view for the activity
        transaction.add(android.R.id.content, newFragment)
                   .addToBackStack(null).commit();
    }
}
  1. 注意里面android.R.id.content
  2. 屏幕大小问题
    1. 在values下创建xml

               <!-- Default boolean values -->
       <resources>
           <bool name="large_layout">false</bool>
       </resources>
      
    2. 在values-w820dp下创建xml

               <!-- Large screen boolean values -->
       <resources>
           <bool name="large_layout">true</bool>
       </resources>
      
    3. java代码

       boolean mIsLargeLayout;
       
       @Override
       public void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
       
           mIsLargeLayout = getResources().getBoolean(R.bool.large_layout);
       }
      

Showing an activity as a dialog on large screens

在大屏幕手机上把一个activity作为对话框形式出现的方法

设置清单文件:

<activity android:theme="@android:style/Theme.Holo.DialogWhenLarge" >

Dismissing a Dialog Dialog消失

  1. 正常消失

    1. 点击了对话框中的button
    2. 单选的时候点击了List
  2. 调用DialogFragment的dismiss()方法

    1. 会执行回调方法onDismiss()
  3. 调用DialogFragment的cancel()方法

    1. 会执行回调方法onCancel()
  4. 当我们要在DialogFragment消失的时候做一些操作的时候

    1. 重写onDissmiss()方法
  5. onCancel()方法调用时机

    1. 点击Dialog外面
    2. 点击手机back键

    注意:点击PositiveButton的时候不会调用onCancel()方法

Fragment和Activity交互

比较好的方式是:接口回调

  1. 定义一个接口

     public interface DataCallback {
    
         public void getData(String data);
     }
    
  2. 让使用这个fragment的activity实现这个接口

  3. 在fragment中使用接口方法

     @Override
     public void onAttach(Activity activity) {
     // onAttach()是合适的早期阶段进行检查MyActivity是否真的实现了接口。
     // 采用接口的方式,dialog无需详细了解MyActivity,只需了解其所需的接口函数,这是真正项目中应采用的方式。
     if (!(activity instanceof DataCallback)) {
         throw new IllegalStateException("fragment所在的Activity必须实现Callbacks接口");
     }
     super.onAttach(activity);
     }
    
     @Override
     public void onClick(DialogInterface dialog, int which) {
     DataCallback callback = (DataCallback) getActivity();
     callback.getData("test");
     }
    

用DialogFragment实现二次弹窗

FragmentTransaction ft = getFragmentManager().beginTransaction();

    /*
     * 如果不执行remove(),对话框即不会进入onDismiss()状态。会被显示在新的对话框下方,是可见的。
     * 主要考虑美观的问题,如果下面的对话框大于上面的对话框就很难看了。 对于Dialog,container为0或者null。
     */
    ft.remove(this);
    /*
     * 将当前的PromptDialogFragment加入到回退堆栈,当用户按返回键,或者通过按帮助框的Close按钮dismiss帮助框是,
     * 重新显示提示框。 对于back stack的处理,系统具有一定的智能。例如:执行两次addToStackStack(),实际不会重复压栈。
     * 有例如:注释掉remove()语句,即提示框不消失,而是在帮助框的下面。
     * 但是在实验中发现是否有addToBackStack()都不会结果有影响,系统能够分析到对象存在,不需要压栈。没有去查源代码,
     * 猜测通过mBackStackId比对来进行智能处理。
     */
    ft.addToBackStack(null);
    
    new OhterDialogFragment()
    .show(getFragmentManager(), "dialog_fragment");

设置出现动画

alertDialog.getWindow().getAttributes().windowAnimations = R.style.dialogAnim;

style文件:

<style name="dialogAnim" mce_bogus="1" parent="android:Animation">
    <item name="android:windowEnterAnimation">@anim/dialog_push_in</item>
    <item name="android:windowExitAnimation">@anim/dialog_push_out</item>
</style>

动画xml文件:dialog_push_in

<?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>

动画xml文件:dialog_push_out

<?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>

自定义DialogFragment出现位置和宽高

    Window window = dialog.getWindow();
    WindowManager.LayoutParams wlp = window.getAttributes();
    wlp.gravity = Gravity.BOTTOM;
    wlp.width = WindowManager.LayoutParams.MATCH_PARENT;
    window.setAttributes(wlp);

dialog 宽度占满屏幕实例,设置 dialog 宽高

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog dialog = new AlertDialog.Builder(getActivity()).create();
    dialog.show();
    Window window = dialog.getWindow();
    window.setBackgroundDrawable(null);
    window.setContentView(R.layout.share_fragment);
    window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);     // 设置宽高
    WindowManager.LayoutParams attributes = window.getAttributes();
    attributes.windowAnimations = R.style.dialogAnim;   // 出现动画
    attributes.gravity = Gravity.BOTTOM;
    window.setAttributes(attributes);
    return dialog;
}

下面的方法有时候可行

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog dialog = new AlertDialog.Builder(getActivity()).create();
    dialog.show();
    Window window = dialog.getWindow();
    window.setContentView(R.layout.share_fragment);
    WindowManager.LayoutParams attributes = window.getAttributes();
    attributes.windowAnimations = R.style.dialogAnim;
    attributes.gravity = Gravity.BOTTOM;
    attributes.width = WindowManager.LayoutParams.MATCH_PARENT;
    window.setAttributes(attributes);
    return dialog;
}

DialogFragment里面EditText调出键盘

//只用下面这一行弹出对话框时需要点击输入框才能弹出软键盘  
alert_leaveMsg.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);  
//加上下面这一行弹出对话框时软键盘随之弹出  
alert_leaveMsg.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);  

设置圆角Dialog

public Dialog onCreateDialog(Bundle savedInstanceState) {

    View view = LayoutInflater.from(getContext()).inflate(R.layout.meida_dialog, null);
    AlertDialog alertDialog = new AlertDialog.Builder(getContext()).create();

    alertDialog.show();
    Window window = alertDialog.getWindow();
        window.setBackgroundDrawable(null);
        window.setContentView(view);
。。。
}

shape:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">

    <corners android:radius="10dp"/>

    <stroke
    android:width="1dp"
    android:color="@color/colorPrimary"/>

    <solid android:color="@android:color/white"/>


</shape>

点击外面不取消Dialog

alertDialog.setCanceledOnTouchOutside(false);

方法二:

@Override      
 public void onCreate(Bundle icicle)  
 {  
    super.onCreate(icicle);  
    this.setCancelable(false);// 设置点击屏幕Dialog不消失  
     int style = DialogFragment.STYLE_NORMAL, theme = 0;  
     setStyle(style,theme);  
}  

点击 Dialog 确定或者取消按钮的时候Dialog不消失

canCloseDialog(dialogInterface, false);//不关闭对话框  
canCloseDialog(dialogInterface, true);//关闭对话框  

//  关键部分在这里  
private void canCloseDialog(DialogInterface dialogInterface, boolean close) {  
    try {  
         Field field = dialogInterface.getClass().getSuperclass().getDeclaredField("mShowing");  
         field.setAccessible(true);  
         field.set(dialogInterface, close);  
     } catch (Exception e) {  
         e.printStackTrace();  
     }  
 }  

DialogFragment 设置背景透明

在 onStart 中设置 window 背景透明

    @Override
    public void onStart() {
        super.onStart();
        Window window = getDialog().getWindow();
        WindowManager.LayoutParams windowParams = window.getAttributes();
        windowParams.dimAmount = 0.0f;
        window.setAttributes(windowParams);
    }

下面代码设置 dialog 背景透明

alertDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容