diff options
Diffstat (limited to 'src/android/support/wearable/view')
-rw-r--r-- | src/android/support/wearable/view/AcceptDenyDialog.java | 182 | ||||
-rw-r--r-- | src/android/support/wearable/view/WearableDialogHelper.java | 217 |
2 files changed, 399 insertions, 0 deletions
diff --git a/src/android/support/wearable/view/AcceptDenyDialog.java b/src/android/support/wearable/view/AcceptDenyDialog.java new file mode 100644 index 00000000..8961ee71 --- /dev/null +++ b/src/android/support/wearable/view/AcceptDenyDialog.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package android.support.wearable.view; + +import android.annotation.TargetApi; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.support.annotation.StyleRes; +import android.view.View; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.Space; +import android.widget.TextView; + +import com.android.packageinstaller.R; + +/** + * A dialog to display a title, a message, and/or an icon with a positive and a negative button. + * + * <p>The buttons are hidden away unless there is a listener attached to the button. Since there's + * no click listener attached by default, the buttons are hidden be default. + */ +@TargetApi(Build.VERSION_CODES.LOLLIPOP) +public class AcceptDenyDialog extends Dialog { + /** Icon at the top of the dialog. */ + protected ImageView mIcon; + /** Title at the top of the dialog. */ + protected TextView mTitle; + /** Message content of the dialog. */ + protected TextView mMessage; + /** Panel containing the buttons. */ + protected View mButtonPanel; + /** Positive button in the button panel. */ + protected ImageButton mPositiveButton; + /** Negative button in the button panel. */ + protected ImageButton mNegativeButton; + /** + * Click listener for the positive button. Positive button should hide if this is <code>null + * </code>. + */ + protected DialogInterface.OnClickListener mPositiveButtonListener; + /** + * Click listener for the negative button. Negative button should hide if this is <code>null + * </code>. + */ + protected DialogInterface.OnClickListener mNegativeButtonListener; + /** Spacer between the positive and negative button. Hidden if one button is hidden. */ + protected View mSpacer; + + private final View.OnClickListener mButtonHandler = (v) -> { + if (v == mPositiveButton && mPositiveButtonListener != null) { + mPositiveButtonListener.onClick(this, DialogInterface.BUTTON_POSITIVE); + dismiss(); + } else if (v == mNegativeButton && mNegativeButtonListener != null) { + mNegativeButtonListener.onClick(this, DialogInterface.BUTTON_NEGATIVE); + dismiss(); + } + }; + + public AcceptDenyDialog(Context context) { + this(context, 0 /* use default context theme */); + } + + public AcceptDenyDialog(Context context, @StyleRes int themeResId) { + super(context, themeResId); + + setContentView(R.layout.accept_deny_dialog); + + mTitle = (TextView) findViewById(android.R.id.title); + mMessage = (TextView) findViewById(android.R.id.message); + mIcon = (ImageView) findViewById(android.R.id.icon); + mPositiveButton = (ImageButton) findViewById(android.R.id.button1); + mPositiveButton.setOnClickListener(mButtonHandler); + mNegativeButton = (ImageButton) findViewById(android.R.id.button2); + mNegativeButton.setOnClickListener(mButtonHandler); + mSpacer = (Space) findViewById(R.id.spacer); + mButtonPanel = findViewById(R.id.buttonPanel); + } + + public ImageButton getButton(int whichButton) { + switch (whichButton) { + case DialogInterface.BUTTON_POSITIVE: + return mPositiveButton; + case DialogInterface.BUTTON_NEGATIVE: + return mNegativeButton; + default: + return null; + } + } + + public void setIcon(Drawable icon) { + mIcon.setVisibility(icon == null ? View.GONE : View.VISIBLE); + mIcon.setImageDrawable(icon); + } + + /** + * @param resId the resourceId of the drawable to use as the icon or 0 if you don't want an icon. + */ + public void setIcon(int resId) { + mIcon.setVisibility(resId == 0 ? View.GONE : View.VISIBLE); + mIcon.setImageResource(resId); + } + + /** @param message the content message text of the dialog. */ + public void setMessage(CharSequence message) { + mMessage.setText(message); + mMessage.setVisibility(message == null ? View.GONE : View.VISIBLE); + } + + /** @param title the title text of the dialog. */ + @Override + public void setTitle(CharSequence title) { + mTitle.setText(title); + } + + /** + * Sets a click listener for a button. + * + * <p>Will hide button bar if all buttons are hidden (i.e. their click listeners are <code>null + * </code>). + * + * @param whichButton {@link DialogInterface.BUTTON_POSITIVE} or {@link + * DialogInterface.BUTTON_NEGATIVE} + * @param listener the listener to set for the button. Hide button if <code>null</code>. + */ + public void setButton(int whichButton, DialogInterface.OnClickListener listener) { + switch (whichButton) { + case DialogInterface.BUTTON_POSITIVE: + mPositiveButtonListener = listener; + break; + case DialogInterface.BUTTON_NEGATIVE: + mNegativeButtonListener = listener; + break; + default: + return; + } + + mSpacer.setVisibility(mPositiveButtonListener == null || mNegativeButtonListener == null + ? View.GONE : View.INVISIBLE); + mPositiveButton.setVisibility( + mPositiveButtonListener == null ? View.GONE : View.VISIBLE); + mNegativeButton.setVisibility( + mNegativeButtonListener == null ? View.GONE : View.VISIBLE); + mButtonPanel.setVisibility( + mPositiveButtonListener == null && mNegativeButtonListener == null + ? View.GONE : View.VISIBLE); + } + + /** + * Convenience method for <code>setButton(DialogInterface.BUTTON_POSITIVE, listener)</code>. + * + * @param listener the listener for the positive button. + */ + public void setPositiveButton(DialogInterface.OnClickListener listener) { + setButton(DialogInterface.BUTTON_POSITIVE, listener); + } + + /** + * Convenience method for <code>setButton(DialogInterface.BUTTON_NEGATIVE, listener)</code>. + * + * @param listener the listener for the positive button. + */ + public void setNegativeButton(DialogInterface.OnClickListener listener) { + setButton(DialogInterface.BUTTON_NEGATIVE, listener); + } +} diff --git a/src/android/support/wearable/view/WearableDialogHelper.java b/src/android/support/wearable/view/WearableDialogHelper.java new file mode 100644 index 00000000..0bdc1cc9 --- /dev/null +++ b/src/android/support/wearable/view/WearableDialogHelper.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package android.support.wearable.view; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; +import android.support.annotation.DrawableRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.VisibleForTesting; +import android.util.Log; +import android.widget.Button; + +/** + * Helper to add icons to AlertDialog buttons.AlertDialog buttons. + */ +public class WearableDialogHelper { + private static final String TAG = "WearableDialogHelper"; + + private int mPositiveIconId; + private Drawable mPositiveIcon; + + private int mNeutralIconId; + private Drawable mNeutralIcon; + + private int mNegativeIconId; + private Drawable mNegativeIcon; + + @VisibleForTesting /* package */ Resources mResources; + @VisibleForTesting /* package */ Resources.Theme mTheme; + + /** + * Convenience constructor, equivalent to {@code new WearableDialogHelper(context.getResources(), + * context.getTheme())}. + */ + public WearableDialogHelper(@NonNull Context context) { + this(context.getResources(), context.getTheme()); + } + + /** + * @param resources the Resources used to obtain Drawables from resource IDs. + * @param theme the Theme used to properly obtain Drawables from resource IDs. + */ + public WearableDialogHelper(@NonNull Resources resources, @NonNull Resources.Theme theme) { + mResources = resources; + mTheme = theme; + } + + @Nullable + public Drawable getPositiveIcon() { + return resolveDrawable(mPositiveIcon, mPositiveIconId); + } + + @Nullable + public Drawable getNegativeIcon() { + return resolveDrawable(mNegativeIcon, mNegativeIconId); + } + + @Nullable + public Drawable getNeutralIcon() { + return resolveDrawable(mNeutralIcon, mNeutralIconId); + } + + @NonNull + public WearableDialogHelper setPositiveIcon(@DrawableRes int resId) { + mPositiveIconId = resId; + mPositiveIcon = null; + return this; + } + + @NonNull + public WearableDialogHelper setPositiveIcon(@Nullable Drawable icon) { + mPositiveIcon = icon; + mPositiveIconId = 0; + return this; + } + + @NonNull + public WearableDialogHelper setNegativeIcon(@DrawableRes int resId) { + mNegativeIconId = resId; + mNegativeIcon = null; + return this; + } + + @NonNull + public WearableDialogHelper setNegativeIcon(@Nullable Drawable icon) { + mNegativeIcon = icon; + mNegativeIconId = 0; + return this; + } + + @NonNull + public WearableDialogHelper setNeutralIcon(@DrawableRes int resId) { + mNeutralIconId = resId; + mNeutralIcon = null; + return this; + } + + @NonNull + public WearableDialogHelper setNeutralIcon(@Nullable Drawable icon) { + mNeutralIcon = icon; + mNeutralIconId = 0; + return this; + } + + /** + * Applies the button icons setup in the helper to the buttons in the dialog. + * + * <p>Note that this should be called after {@code AlertDialog.create()}, NOT {@code + * AlertDialog.Builder.create()}. Calling {@code AlertDialog.Builder.show()} would also accomplish + * the same thing. + * + * @param dialog the AlertDialog to style with the helper. + */ + public void apply(@NonNull AlertDialog dialog) { + applyButton(dialog.getButton(DialogInterface.BUTTON_POSITIVE), getPositiveIcon()); + applyButton(dialog.getButton(DialogInterface.BUTTON_NEGATIVE), getNegativeIcon()); + applyButton(dialog.getButton(DialogInterface.BUTTON_NEUTRAL), getNeutralIcon()); + } + + /** Applies the specified drawable to the button. */ + @VisibleForTesting + /* package */ void applyButton(@Nullable Button button, @Nullable Drawable drawable) { + if (button != null) { + button.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null); + button.setAllCaps(false); + } else if (drawable != null) { + Log.w(TAG, "non-null drawable used with missing button, did you call AlertDialog.create()?"); + } + } + + /** Obtain a drawable between a drawable and a resource ID. */ + @VisibleForTesting + /* package */ Drawable resolveDrawable(@Nullable Drawable drawable, @DrawableRes int resId) { + return drawable == null && resId != 0 ? mResources.getDrawable(resId, mTheme) : drawable; + } + + /** Convenience builder to generate an AlertDialog with icons in buttons. */ + public static class DialogBuilder extends AlertDialog.Builder { + private final WearableDialogHelper mHelper; + + public DialogBuilder(Context context) { + super(context); + mHelper = new WearableDialogHelper(context.getResources(), context.getTheme()); + } + + public DialogBuilder(Context context, int themeResId) { + super(context, themeResId); + mHelper = new WearableDialogHelper(context.getResources(), context.getTheme()); + } + + public WearableDialogHelper getHelper() { + return mHelper; + } + + public DialogBuilder setPositiveIcon(@DrawableRes int iconId) { + mHelper.setPositiveIcon(iconId); + return this; + } + + public DialogBuilder setPositiveIcon(@Nullable Drawable icon) { + mHelper.setPositiveIcon(icon); + return this; + } + + public DialogBuilder setNegativeIcon(@DrawableRes int iconId) { + mHelper.setNegativeIcon(iconId); + return this; + } + + public DialogBuilder setNegativeIcon(@Nullable Drawable icon) { + mHelper.setNegativeIcon(icon); + return this; + } + + public DialogBuilder setNeutralIcon(@DrawableRes int iconId) { + mHelper.setNeutralIcon(iconId); + return this; + } + + public DialogBuilder setNeutralIcon(@Nullable Drawable icon) { + mHelper.setNeutralIcon(icon); + return this; + } + + @Override + public AlertDialog create() { + final AlertDialog dialog = super.create(); + dialog.create(); + mHelper.apply(dialog); + return dialog; + } + + @Override + public AlertDialog show() { + final AlertDialog dialog = this.create(); + dialog.show(); + return dialog; + } + } +} |