package com.door43.translationstudio.dialogs; import android.app.Activity; import android.app.DialogFragment; import android.app.FragmentManager; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.support.annotation.Nullable; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.door43.translationstudio.R; import org.sufficientlysecure.htmltextview.HtmlTextView; /** * Created by blm on 11/28/15. * The intent of this is to create an AlertDialog replacement that has a modern UI appearance even * on older devices. Many of the calls are chainable to simplify code. * * Limitations: * not all features of AlertDialog supported * Dialog buttons are modal and will dismiss dialog. No support for modeless buttons. */ public class CustomAlertDialog extends DialogFragment { static int testCntr = 0; static String TAG = CustomAlertDialog.class.getSimpleName(); private int mMessageID = 0; private int mMessageHtmlID = 0; private int mTitleID = 0; private int mIconID = 0; private Button mPositiveButton; private View.OnClickListener mPositiveListener; private int mPositiveTextID = 0; private Button mNegativeButton; private View.OnClickListener mNegativeListener; private int mNegativeTextID = 0; private Button mNeutralButton; private View.OnClickListener mNeutralListener; private int mNeutralTextID = 0; private CharSequence mTitle = null; private CharSequence mMessage = null; private String mMessageHtml = ""; private EditText mEditText = null; private View mContentView = null; private Activity mContext; private boolean mAutoDismiss = true; private boolean mCancellable = true; private boolean mDialogDismissed = false; private OnDismissListener mOnDismissListener = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); int style = DialogFragment.STYLE_NO_TITLE, theme = 0; setStyle(style, theme); if(savedInstanceState != null) { dismiss(); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.dialog_custom_alert, container, false); final TextView message = (TextView) rootView.findViewById(R.id.dialog_content); if(mMessageHtmlID != 0) { mMessageHtml = mContext.getResources().getString(mMessageHtmlID); } if(!mMessageHtml.isEmpty()) { mContentView = inflater.inflate(R.layout.dialog_html_alert, null); HtmlTextView text = (HtmlTextView) mContentView.findViewById(R.id.text); text.setHtmlFromString(mMessageHtml, true); } else { if (0 != mMessageID) { message.setText(mMessageID); } else if (null != mMessage) { message.setText(mMessage); } } final ImageView icon = (ImageView) rootView.findViewById(R.id.dialog_icon); if (0 != mIconID) { icon.setImageResource(mIconID); } else { icon.setVisibility(View.GONE); } if (null != mContentView) { final TextView content = (TextView) rootView.findViewById(R.id.dialog_content); ViewGroup parent = (ViewGroup) content.getParent(); int index = parent.indexOfChild(content); parent.removeView(content); parent.addView(mContentView, index); } if (null != mEditText) { final LinearLayout layout = (LinearLayout) rootView.findViewById(R.id.content_layout); LinearLayout.LayoutParams linLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); mEditText.setLayoutParams(linLayoutParams); layout.addView(mEditText); } mPositiveButton = setupButton( rootView, R.id.positiveButton, mPositiveTextID); mPositiveButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(null != mPositiveListener) { mPositiveListener.onClick(v); } if(mAutoDismiss) { dismiss(); } } }); mNegativeButton = setupButton( rootView, R.id.negativeButton, mNegativeTextID); mNegativeButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(null != mNegativeListener) { mNegativeListener.onClick(v); } if(mAutoDismiss) { dismiss(); } } }); mNeutralButton = setupButton( rootView, R.id.neutralButton, mNeutralTextID); mNeutralButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(null != mNeutralListener) { mNeutralListener.onClick(v); } if(mAutoDismiss) { dismiss(); } } }); final TextView title = (TextView) rootView.findViewById(R.id.dialog_title); if (0 != mTitleID) { title.setText(mTitleID); } else if(mTitle != null) { title.setText(mTitle); } else { // if not set then hide title.setVisibility(View.GONE); } return rootView; } @Override public void onDismiss(DialogInterface dialog) { super.onDismiss(dialog); if(mOnDismissListener != null) { mOnDismissListener.onDismiss(); } } public CustomAlertDialog setOnDismissListener(OnDismissListener listener) { mOnDismissListener = listener; return this; } @Override public void onCancel(DialogInterface dialog) { super.onCancel(dialog); if(mCancellable && !mDialogDismissed) { mNegativeButton.callOnClick(); } } @Override public void dismiss() { // clear windows and listeners mDialogDismissed = true; mNeutralListener = mPositiveListener = mNegativeListener = null; mEditText = null; mContentView = null; mContext = null; super.dismiss(); } /** * Chainable - set context to use for resources * @param context * @return */ public CustomAlertDialog setContext(final Activity context) { mContext = context; return this; } /** * Chainable - set resource to display in title * @param textResId * @return */ public CustomAlertDialog setTitle(int textResId) { mTitleID = textResId; mTitle = null; return this; } /** * Chainable - set text to display in title * @param text * @return */ public CustomAlertDialog setTitle(CharSequence text) { mTitle = text; mTitleID = 0; return this; } /** * Chainable - set resource to display in message * @param textResId * @return */ public CustomAlertDialog setMessage(int textResId) { mMessageID = textResId; mMessage = null; return this; } /** * Chainable - set text to display in message * @param text * @return */ public CustomAlertDialog setMessage(CharSequence text) { mMessage = text; mMessageID = 0; return this; } /** * Chainable - set HTML string to display in message * @param textHtml * @return */ public CustomAlertDialog setMessageHtml(String textHtml) { mMessageHtml = textHtml; mMessageHtmlID = 0; return this; } /** * Chainable - set HTML resource to display in message * @param textResId * @return */ public CustomAlertDialog setMessageHtml(int textResId) { mMessageHtmlID = textResId; mMessageHtml = ""; return this; } /** * display the dialog * @param tag - string identifier to associate with dialog */ public void show(final String tag) { FragmentManager fm = mContext.getFragmentManager(); show(fm, tag); } /** * Chainable - enables display of a positive button (right most) on button bar * @param textResId * @param l - optional click listener. Set null if not needed. * @return */ public CustomAlertDialog setPositiveButton(int textResId, View.OnClickListener l) { mPositiveListener = l; mPositiveTextID = textResId; return this; } /** * Chainable - enables display of a negative button (left most) on button bar * @param textResId * @param l - optional click listener. Set null if not needed. * @return */ public CustomAlertDialog setNegativeButton(int textResId, View.OnClickListener l) { mNegativeListener = l; mNegativeTextID = textResId; return this; } /** * Chainable - enables display of an extra button on button bar between the negative and positive buttons * @param textResId * @param l - optional click listener. Set null if not needed. * @return */ public CustomAlertDialog setNeutralButton(int textResId, View.OnClickListener l) { mNeutralListener = l; mNeutralTextID = textResId; return this; } /** * Chainable - replaces message text with custom view * @param v * @return */ public CustomAlertDialog setView(View v) { mContentView = v; return this; } /** * Chainable - displays an icon in title * @param textResId * @return */ public CustomAlertDialog setIcon(int textResId) { mIconID = textResId; return this; } /** * Chainable - adds a text input field if enableInput is true * @param enableInput * @return */ public CustomAlertDialog addInputPrompt(boolean enableInput) { if(enableInput) { if(null == mEditText) { mEditText = new EditText(mContext); } } else { mEditText = null; } return this; } /** * if text input was selected, then this returns the text enterred by the user * @return */ @Nullable public CharSequence getEnteredText() { if(mEditText != null) { return mEditText.getText(); } return null; } /** * Chainable - enable/disable auto dismiss of dialog. If autoDismiss is set false, then dismiss() * must be explicitly called on dialog to remove it. * @param autoDismiss * @return */ public CustomAlertDialog setAutoDismiss(boolean autoDismiss) { this.mAutoDismiss = autoDismiss; return this; } /** * applies cancelable setting in a Chainable fashion * @param cancelable * @return */ public CustomAlertDialog setCancelableChainable(boolean cancelable) { super.setCancelable(cancelable); mCancellable = cancelable; return this; } /** * shared button setup code * @param rootView * @param buttonResID * @param buttonTextID * @return */ private Button setupButton(View rootView, int buttonResID, int buttonTextID) { Button button = (Button) rootView.findViewById(buttonResID); if(null != button) { String label = ""; if(0 != buttonTextID) { label = getResources().getText(buttonTextID).toString().toUpperCase(); } if (!label.isEmpty()) { // convert string to upper case manually, because on older devices uppercase attribute // in UI button.setText(label); } else { button.setVisibility(View.GONE); } } return button; } /** * creates an instance of a custom alert dialog (not displayed until show() is called) * @param context * @return */ static public CustomAlertDialog Create(final Activity context) { CustomAlertDialog dlg = new CustomAlertDialog(); dlg.setContext(context); return dlg; } public interface OnDismissListener { void onDismiss(); } // static public void test(final Activity context) { // // Log.d(TAG, "Test pass: " + testCntr); // // switch (testCntr++) { // // default: // testCntr = 1; // // case 0: // LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); // View layout = inflater.inflate(R.layout.dialog_html_alert, null); // HtmlTextView text = (HtmlTextView)layout.findViewById(R.id.text); // text.setHtmlFromString(context.getResources().getString(R.string.chunk_checklist_body), true); // // CustomAlertDialog.Create(context) // .setTitle(R.string.chunk_checklist_title) // .setView(layout) // .setPositiveButton(R.string.confirm, new View.OnClickListener() { // @Override // public void onClick(View v) { // Log.d(TAG, "Positive"); // } // } // ) // .setNegativeButton(R.string.title_cancel, null) // .show("Chunk2"); // break; // // case 5: // CustomAlertDialog.Create(context) // .setTitle(R.string.success) // .setIcon(R.drawable.ic_done_black_24dp) // .setMessage(R.string.download_complete) // .setCancelableChainable(true) // .setPositiveButton(R.string.label_ok, null) // .show("Success"); // // break; // // case 4: // CustomAlertDialog.Create(context) // .setTitle("Chunk Checklist") // .setMessage("Are you sure you are done with this chunk?\n" + // " * I have placed the verses correctly\n" + // " * I have reviewed the words and meaning\n" + // " * I have reviewed the translation questions" // ) // .setPositiveButton(R.string.confirm, new View.OnClickListener() { // @Override // public void onClick(View v) { // Log.d(TAG, "Positive"); // } // } // ) // .setNegativeButton(R.string.title_cancel, null) // .show("Chunk2"); // break; // // case 3: // CustomAlertDialog.Create(context) // .setTitle(R.string.apk_update_available) // .setMessage(R.string.upload_report_or_download_latest_apk) // .setNegativeButton(R.string.title_cancel, new View.OnClickListener() { // @Override // public void onClick(View v) { // Log.d(TAG, "Negative"); // } // }) // .setNeutralButton(R.string.download_update, new View.OnClickListener() { // @Override // public void onClick(View v) { // Log.d(TAG, "Neutral"); // } // }) // .setPositiveButton(R.string.label_continue, new View.OnClickListener() { // @Override // public void onClick(View v) { // Log.d(TAG, "Positive"); // } // }) // .show("ReleaseNotify"); // break; // // case 1: // CustomAlertDialog.Create(context) // .setTitle(R.string.update_projects) // .setIcon(R.drawable.ic_local_library_black_24dp) // .setMessage(R.string.use_internet_confirmation) // .setPositiveButton(R.string.yes, new View.OnClickListener() { // @Override // public void onClick(View v) { // Log.d(TAG, "Positive"); // } // }) // .setNegativeButton(R.string.no, null) // .show("Update"); // break; // // case 2: // CustomAlertDialog.Create(context) // .setTitle(R.string.publish) // .setMessage(R.string.upload_failed) // .setPositiveButton(R.string.dismiss, null) // .setNeutralButton(R.string.menu_bug, new View.OnClickListener() { // @Override // public void onClick(View v) { // Log.d(TAG, "Neutral"); // } // }).show("PublishFail"); // break; // // } // } }