1 /* 2 * Copyright 2016, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.managedprovisioning.common; 18 19 import android.app.Activity; 20 import android.app.AlertDialog; 21 import android.app.Dialog; 22 import android.app.DialogFragment; 23 import android.content.DialogInterface; 24 import android.os.Bundle; 25 26 /** 27 * Utility class wrapping a {@link AlertDialog} in a {@link DialogFragment} 28 * <p> In order to properly handle Dialog lifecycle we follow the practice of wrapping of them 29 * in a Dialog Fragment. 30 * <p> If buttons are to be used (enabled by setting a button message), the creator {@link Activity} 31 * must implement {@link SimpleDialogListener}. 32 */ 33 public class SimpleDialog extends DialogFragment { 34 private static final String TITLE = "title"; 35 private static final String MESSAGE = "message"; 36 private static final String NEGATIVE_BUTTON_MESSAGE = "negativeButtonMessage"; 37 private static final String POSITIVE_BUTTON_MESSAGE = "positiveButtonMessage"; 38 39 /** 40 * Use the {@link Builder} instead. Keeping the constructor public only because 41 * a {@link DialogFragment} must have an empty constructor that is public. 42 */ SimpleDialog()43 public SimpleDialog() { 44 } 45 46 @Override onCreateDialog(Bundle savedInstanceState)47 public AlertDialog onCreateDialog(Bundle savedInstanceState) { 48 final SimpleDialogListener dialogListener = (SimpleDialogListener) getActivity(); 49 50 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 51 52 Bundle args = getArguments(); 53 if (args.containsKey(TITLE)) { 54 builder.setTitle(args.getInt(TITLE)); 55 } 56 57 if (args.containsKey(MESSAGE)) { 58 builder.setMessage(args.getInt(MESSAGE)); 59 } 60 61 if (args.containsKey(NEGATIVE_BUTTON_MESSAGE)) { 62 builder.setNegativeButton(args.getInt(NEGATIVE_BUTTON_MESSAGE), 63 new DialogInterface.OnClickListener() { 64 @Override 65 public void onClick(DialogInterface dialog, int which) { 66 dialogListener.onNegativeButtonClick(SimpleDialog.this); 67 } 68 }); 69 } 70 71 if (args.containsKey(POSITIVE_BUTTON_MESSAGE)) { 72 builder.setPositiveButton(args.getInt(POSITIVE_BUTTON_MESSAGE), 73 new DialogInterface.OnClickListener() { 74 @Override 75 public void onClick(DialogInterface dialog, int which) { 76 dialogListener.onPositiveButtonClick(SimpleDialog.this); 77 } 78 }); 79 } 80 81 return builder.create(); 82 } 83 84 /** 85 * Throws an exception informing of a lack of a handler for a dialog button click 86 * <p> Useful when implementing {@link SimpleDialogListener} 87 */ throwButtonClickHandlerNotImplemented(DialogFragment dialog)88 public static void throwButtonClickHandlerNotImplemented(DialogFragment dialog) { 89 throw new IllegalArgumentException("Button click handler not implemented for dialog: " 90 + dialog.getTag()); 91 } 92 93 public static class Builder implements DialogBuilder { 94 private Integer mTitle; 95 private Integer mMessage; 96 private Integer mNegativeButtonMessage; 97 private Integer mPositiveButtonMessage; 98 private Boolean mCancelable; 99 100 /** 101 * Sets the title 102 * @param title Title resource id. 103 */ setTitle(Integer title)104 public Builder setTitle(Integer title) { 105 mTitle = title; 106 return this; 107 } 108 109 /** 110 * Sets the message 111 * @param message Message resource id. 112 */ setMessage(int message)113 public Builder setMessage(int message) { 114 mMessage = message; 115 return this; 116 } 117 118 /** 119 * Sets a message for the button. 120 * <p> Makes the button appear (without setting a button message, a button is not displayed) 121 * <p> Callback must be handled by a creator {@link Activity}, 122 * which must implement {@link SimpleDialogListener}. 123 * @param negativeButtonMessage Message resource id. 124 */ setNegativeButtonMessage(int negativeButtonMessage)125 public Builder setNegativeButtonMessage(int negativeButtonMessage) { 126 mNegativeButtonMessage = negativeButtonMessage; 127 return this; 128 } 129 130 /** 131 * Sets a message for the button. 132 * <p> Makes the button appear (without setting a button message, a button is not displayed) 133 * <p> Callback must be handled by a creator {@link Activity}, 134 * which must implement {@link SimpleDialogListener}. 135 * @param positiveButtonMessage Message resource id. 136 */ setPositiveButtonMessage(int positiveButtonMessage)137 public Builder setPositiveButtonMessage(int positiveButtonMessage) { 138 mPositiveButtonMessage = positiveButtonMessage; 139 return this; 140 } 141 142 /** 143 * Sets whether the dialog is cancelable or not. Default is true. 144 */ setCancelable(boolean cancelable)145 public Builder setCancelable(boolean cancelable) { 146 mCancelable = cancelable; 147 return this; 148 } 149 150 /** 151 * Creates an {@link SimpleDialog} with the arguments supplied to this builder. 152 */ 153 @Override build()154 public SimpleDialog build() { 155 SimpleDialog instance = new SimpleDialog(); 156 Bundle args = new Bundle(); 157 158 if (mTitle != null) { 159 args.putInt(TITLE, mTitle); 160 } 161 162 if (mMessage != null) { 163 args.putInt(MESSAGE, mMessage); 164 } 165 166 if (mNegativeButtonMessage != null) { 167 args.putInt(NEGATIVE_BUTTON_MESSAGE, mNegativeButtonMessage); 168 } 169 170 if (mPositiveButtonMessage != null) { 171 args.putInt(POSITIVE_BUTTON_MESSAGE, mPositiveButtonMessage); 172 } 173 174 if (mCancelable != null) { 175 instance.setCancelable(mCancelable); 176 } 177 178 instance.setArguments(args); 179 return instance; 180 } 181 } 182 183 /** 184 * Interface for handling callbacks from {@link SimpleDialog} buttons. 185 * 186 * <p>If multiple dialogs are used in a context of a single {@link Activity}, 187 * a consumer of the interface can differentiate between dialogs using 188 * e.g. a {@link DialogFragment#getTag()}, or {@link DialogFragment#getArguments()}. 189 */ 190 public interface SimpleDialogListener { 191 /** 192 * Called when a user clicks on the positive dialog button. 193 * <p> To be implemented by a host {@link Activity} object. 194 * @param dialog {@link DialogFragment} where the click happened. 195 */ onPositiveButtonClick(DialogFragment dialog)196 void onPositiveButtonClick(DialogFragment dialog); 197 198 /** 199 * Called when a user clicks on the negative dialog button. 200 * <p> To be implemented by a host {@link Activity} object. 201 * @param dialog {@link DialogFragment} where the click happened. 202 */ onNegativeButtonClick(DialogFragment dialog)203 void onNegativeButtonClick(DialogFragment dialog); 204 } 205 }