1 /* 2 * Copyright (C) 2023 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.tv.settings; 18 19 import android.graphics.drawable.Icon; 20 import android.os.Bundle; 21 import android.text.TextUtils; 22 import android.view.ContextThemeWrapper; 23 import android.view.LayoutInflater; 24 import android.view.View; 25 import android.view.ViewGroup; 26 import android.widget.Button; 27 import android.widget.ImageView; 28 import android.widget.TextView; 29 30 import androidx.fragment.app.Fragment; 31 32 /** 33 * Full screen dialog fragment. 34 * 35 * Use {@link DialogBuilder} to set up the arguments to the fragment. 36 * To be used with the {@link R.style#TvSettingsDialog_FullScreen} theme. 37 */ 38 public class FullScreenDialogFragment extends Fragment { 39 /** Constant for {@link #onButtonPressed(int)} indicating the positive button was pressed. */ 40 public static final int ACTION_POSITIVE = 0; 41 /** Constant for {@link #onButtonPressed(int)} indicating the negative button was pressed. */ 42 public static final int ACTION_NEGATIVE = 1; 43 44 private static final String ARGUMENT_ICON = "ARGUMENT_ICON"; 45 private static final String ARGUMENT_TITLE = "ARGUMENT_TITLE"; 46 private static final String ARGUMENT_MESSAGE = "ARGUMENT_MESSAGE"; 47 private static final String ARGUMENT_HINT_ICON = "ARGUMENT_HINT_ICON"; 48 private static final String ARGUMENT_HINT_TEXT = "ARGUMENT_HINT_TEXT"; 49 private static final String ARGUMENT_POSITIVE_BUTTON_LABEL = "ARGUMENT_POSITIVE_BUTTON_LABEL"; 50 private static final String ARGUMENT_NEGATIVE_BUTTON_LABEL = "ARGUMENT_NEGATIVE_BUTTON_LABEL"; 51 52 /** Builder that sets up arguments to the dialog fragment */ 53 public static final class DialogBuilder { 54 private final Bundle mArgs = new Bundle(); 55 56 /** Builder that sets up arguments to the dialog fragment */ DialogBuilder()57 public DialogBuilder() { 58 } 59 60 /** Sets the icon of the dialog */ setIcon(Icon icon)61 public DialogBuilder setIcon(Icon icon) { 62 mArgs.putParcelable(ARGUMENT_ICON, icon); 63 return this; 64 } 65 66 /** Sets the title of the dialog */ setTitle(String title)67 public DialogBuilder setTitle(String title) { 68 mArgs.putString(ARGUMENT_TITLE, title); 69 return this; 70 } 71 72 /** Sets the message of the dialog */ setMessage(String message)73 public DialogBuilder setMessage(String message) { 74 mArgs.putString(ARGUMENT_MESSAGE, message); 75 return this; 76 } 77 78 /** Sets the hint icon (shown below the message) of the dialog */ setHintIcon(Icon hintIcon)79 public DialogBuilder setHintIcon(Icon hintIcon) { 80 mArgs.putParcelable(ARGUMENT_HINT_ICON, hintIcon); 81 return this; 82 } 83 84 /** Sets the hint text (shown below the message) of the dialog */ setHintText(String hintText)85 public DialogBuilder setHintText(String hintText) { 86 mArgs.putString(ARGUMENT_HINT_TEXT, hintText); 87 return this; 88 } 89 90 /** Sets the label of the positive button */ setPositiveButton(String positiveButtonLabel)91 public DialogBuilder setPositiveButton(String positiveButtonLabel) { 92 mArgs.putString(ARGUMENT_POSITIVE_BUTTON_LABEL, positiveButtonLabel); 93 return this; 94 } 95 96 /** Sets the label of the negative button */ setNegativeButton(String negativeButtonLabel)97 public DialogBuilder setNegativeButton(String negativeButtonLabel) { 98 mArgs.putString(ARGUMENT_NEGATIVE_BUTTON_LABEL, negativeButtonLabel); 99 return this; 100 } 101 102 /** Returns arguments for the dialog fragment */ build()103 public Bundle build() { 104 return mArgs; 105 } 106 } 107 108 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)109 public View onCreateView(LayoutInflater inflater, ViewGroup container, 110 Bundle savedInstanceState) { 111 LayoutInflater themedInflater = inflater.cloneInContext( 112 new ContextThemeWrapper(inflater.getContext(), 113 R.style.TvSettingsDialog_FullScreen)); 114 View view = themedInflater.inflate(R.layout.full_screen_dialog, container, false); 115 116 ImageView iconView = view.findViewById(R.id.dialog_icon); 117 TextView titleView = view.findViewById(R.id.dialog_title); 118 TextView messageView = view.findViewById(R.id.dialog_message); 119 ViewGroup customViewContainer = view.findViewById(R.id.custom_view_container); 120 ImageView hintIconView = view.findViewById(R.id.hint_icon); 121 TextView hintTextView = view.findViewById(R.id.hint_text); 122 ViewGroup hintContainerView = view.findViewById(R.id.hint_container); 123 Button positiveButton = view.findViewById(R.id.positive_button); 124 Button negativeButton = view.findViewById(R.id.negative_button); 125 126 final Bundle args = getArguments(); 127 final Icon icon = args.getParcelable(ARGUMENT_ICON, Icon.class); 128 if (icon != null) { 129 iconView.setVisibility(View.VISIBLE); 130 iconView.setImageIcon(icon); 131 } 132 133 titleView.setText(args.getString(ARGUMENT_TITLE)); 134 CharSequence message = getMessage(); 135 if (!TextUtils.isEmpty(message)) { 136 messageView.setText(message); 137 } else { 138 messageView.setVisibility(View.GONE); 139 } 140 141 View customView = createCustomView(customViewContainer); 142 if (customView != null) { 143 customViewContainer.addView(customView); 144 } else { 145 customViewContainer.setVisibility(View.GONE); 146 } 147 148 final Icon hintIcon = args.getParcelable(ARGUMENT_HINT_ICON, Icon.class); 149 final String hintText = args.getString(ARGUMENT_HINT_TEXT); 150 final boolean hasHint = !TextUtils.isEmpty(hintText); 151 hintContainerView.setVisibility(hasHint ? View.VISIBLE : View.GONE); 152 if (hasHint) { 153 hintTextView.setText(hintText); 154 if (hintIcon != null) { 155 hintIconView.setVisibility(View.VISIBLE); 156 hintIconView.setImageIcon(hintIcon); 157 } 158 } 159 160 final String positiveButtonLabel = args.getString(ARGUMENT_POSITIVE_BUTTON_LABEL); 161 positiveButton.setVisibility( 162 TextUtils.isEmpty(positiveButtonLabel) ? View.GONE : View.VISIBLE); 163 positiveButton.setText(positiveButtonLabel); 164 positiveButton.setOnClickListener((v) -> onButtonPressed(ACTION_POSITIVE)); 165 166 final String negativeButtonLabel = args.getString(ARGUMENT_NEGATIVE_BUTTON_LABEL); 167 negativeButton.setVisibility( 168 TextUtils.isEmpty(negativeButtonLabel) ? View.GONE : View.VISIBLE); 169 negativeButton.setText(negativeButtonLabel); 170 negativeButton.setOnClickListener((v) -> onButtonPressed(ACTION_NEGATIVE)); 171 172 173 return view; 174 } 175 176 /** Returns the dialog message. */ getMessage()177 public CharSequence getMessage() { 178 return getArguments().getString(ARGUMENT_MESSAGE); 179 } 180 181 /** Returns the custom view (shown below the message) */ createCustomView(ViewGroup parent)182 public View createCustomView(ViewGroup parent) { 183 return null; 184 } 185 186 /** 187 * Called when a dialog button was pressed. 188 * 189 * @param action Indicates which button was pressed 190 * @see #ACTION_POSITIVE 191 * @see #ACTION_NEGATIVE 192 */ onButtonPressed(int action)193 public void onButtonPressed(int action) { 194 } 195 } 196