From 6161f39f583cf202969125757d78010bdc06457c Mon Sep 17 00:00:00 2001 From: Anthony Hugh Date: Fri, 18 Sep 2015 17:18:10 -0700 Subject: Update Grant Permissions dialog to redlines Changes: - Refactor the ViewHandler a bit to be more generic. This should help with another upcoming Wear dialog. - Update assets for buttons - Add deny asset - Fix margins and other UI number tweaks BUG: 24133550 Change-Id: I330bdf3217fa5c554f71d9105a0475106b6f3e12 --- .../ui/wear/ConfirmationViewHandler.java | 285 +++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 src/com/android/packageinstaller/permission/ui/wear/ConfirmationViewHandler.java (limited to 'src/com/android/packageinstaller/permission/ui/wear/ConfirmationViewHandler.java') diff --git a/src/com/android/packageinstaller/permission/ui/wear/ConfirmationViewHandler.java b/src/com/android/packageinstaller/permission/ui/wear/ConfirmationViewHandler.java new file mode 100644 index 00000000..d28866ef --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/wear/ConfirmationViewHandler.java @@ -0,0 +1,285 @@ +package com.android.packageinstaller.permission.ui.wear; + +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.ScrollView; +import android.widget.TextView; + +import com.android.packageinstaller.R; + +public abstract class ConfirmationViewHandler implements + Handler.Callback, + View.OnClickListener, + ViewTreeObserver.OnScrollChangedListener { + public static final int MODE_HORIZONTAL_BUTTONS = 0; + public static final int MODE_VERTICAL_BUTTONS = 1; + + private static final int MSG_HIDE_BUTTON_BAR = 1001; + private static final long HIDE_ANIM_DURATION = 500; + + private View mRoot; + private TextView mCurrentPageText; + private ImageView mIcon; + private TextView mMessage; + private ScrollView mScrollingContainer; + private ViewGroup mContent; + private ViewGroup mHorizontalButtonBar; + private ViewGroup mVerticalButtonBar; + private Button mVerticalButton1; + private Button mVerticalButton2; + private Button mVerticalButton3; + private View mButtonBarContainer; + + private Context mContext; + + private Handler mHideHandler; + private Interpolator mInterpolator; + private float mButtonBarFloatingHeight; + private ObjectAnimator mButtonBarAnimator; + private float mCurrentTranslation; + private boolean mHiddenBefore; + + // TODO: Move these into a builder + /** In the 2 button layout, this is allow button */ + public abstract void onButton1(); + /** In the 2 button layout, this is deny button */ + public abstract void onButton2(); + public abstract void onButton3(); + public abstract CharSequence getVerticalButton1Text(); + public abstract CharSequence getVerticalButton2Text(); + public abstract CharSequence getVerticalButton3Text(); + public abstract Drawable getVerticalButton1Icon(); + public abstract Drawable getVerticalButton2Icon(); + public abstract Drawable getVerticalButton3Icon(); + public abstract CharSequence getCurrentPageText(); + public abstract Icon getPermissionIcon(); + public abstract CharSequence getMessage(); + + public ConfirmationViewHandler(Context context) { + mContext = context; + } + + public View createView() { + mRoot = LayoutInflater.from(mContext).inflate(R.layout.grant_permissions, null); + + mMessage = (TextView) mRoot.findViewById(R.id.message); + mCurrentPageText = (TextView) mRoot.findViewById(R.id.current_page_text); + mIcon = (ImageView) mRoot.findViewById(R.id.icon); + mButtonBarContainer = mRoot.findViewById(R.id.button_bar_container); + mContent = (ViewGroup) mRoot.findViewById(R.id.content); + mScrollingContainer = (ScrollView) mRoot.findViewById(R.id.scrolling_container); + mHorizontalButtonBar = (ViewGroup) mRoot.findViewById(R.id.horizontal_button_bar); + mVerticalButtonBar = (ViewGroup) mRoot.findViewById(R.id.vertical_button_bar); + + Button horizontalAllow = (Button) mRoot.findViewById(R.id.horizontal_allow_button); + Button horizontalDeny = (Button) mRoot.findViewById(R.id.horizontal_deny_button); + horizontalAllow.setOnClickListener(this); + horizontalDeny.setOnClickListener(this); + + mVerticalButton1 = (Button) mRoot.findViewById(R.id.vertical_button1); + mVerticalButton2 = (Button) mRoot.findViewById(R.id.vertical_button2); + mVerticalButton3 = (Button) mRoot.findViewById(R.id.vertical_button3); + mVerticalButton1.setOnClickListener(this); + mVerticalButton2.setOnClickListener(this); + mVerticalButton3.setOnClickListener(this); + + mInterpolator = AnimationUtils.loadInterpolator(mContext, + android.R.interpolator.fast_out_slow_in); + mButtonBarFloatingHeight = mContext.getResources().getDimension( + R.dimen.conf_diag_floating_height); + mHideHandler = new Handler(this); + + return mRoot; + } + + /** + * Child class should override this for other modes. Call invalidate() to update the UI to the + * new button mode. + * @return The current mode the layout should use for the buttons + */ + public int getButtonBarMode() { + return MODE_HORIZONTAL_BUTTONS; + } + + public void invalidate() { + CharSequence currentPageText = getCurrentPageText(); + if (!TextUtils.isEmpty(currentPageText)) { + mCurrentPageText.setText(currentPageText); + mCurrentPageText.setVisibility(View.VISIBLE); + } else { + mCurrentPageText.setVisibility(View.GONE); + } + + Icon icon = getPermissionIcon(); + if (icon != null) { + mIcon.setImageIcon(icon); + mIcon.setVisibility(View.VISIBLE); + } else { + mIcon.setVisibility(View.GONE); + } + mMessage.setText(getMessage()); + + switch (getButtonBarMode()) { + case MODE_HORIZONTAL_BUTTONS: + mHorizontalButtonBar.setVisibility(View.VISIBLE); + mVerticalButtonBar.setVisibility(View.GONE); + break; + case MODE_VERTICAL_BUTTONS: + mHorizontalButtonBar.setVisibility(View.GONE); + mVerticalButtonBar.setVisibility(View.VISIBLE); + mVerticalButton1.setText(getVerticalButton1Text()); + mVerticalButton2.setText(getVerticalButton2Text()); + mVerticalButton3.setText(getVerticalButton3Text()); + + mVerticalButton1.setCompoundDrawablesWithIntrinsicBounds( + getVerticalButton1Icon(), null, null, null); + mVerticalButton2.setCompoundDrawablesWithIntrinsicBounds( + getVerticalButton2Icon(), null, null, null); + mVerticalButton3.setCompoundDrawablesWithIntrinsicBounds( + getVerticalButton3Icon(), null, null, null); + break; + } + + mScrollingContainer.scrollTo(0, 0); + + mScrollingContainer.getViewTreeObserver().addOnScrollChangedListener(this); + + mRoot.getViewTreeObserver().addOnGlobalLayoutListener( + new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + // Setup Button animation. + // pop the button bar back to full height, stop all animation + if (mButtonBarAnimator != null) { + mButtonBarAnimator.cancel(); + } + + // In order to fake the buttons peeking at the bottom, need to do set the + // padding properly. + if (mContent.getPaddingBottom() != mButtonBarContainer.getHeight()) { + mContent.setPadding(0, 0, 0, mButtonBarContainer.getHeight()); + } + + // stop any calls to hide the button bar in the future + mHideHandler.removeMessages(MSG_HIDE_BUTTON_BAR); + mHiddenBefore = false; + + // determine which mode the scrolling should work at. + if (mContent.getHeight() > mScrollingContainer.getHeight()) { + mButtonBarContainer.setTranslationZ(mButtonBarFloatingHeight); + mHideHandler.sendEmptyMessageDelayed(MSG_HIDE_BUTTON_BAR, 3000); + generateButtonBarAnimator(mButtonBarContainer.getHeight(), 0, 0, + mButtonBarFloatingHeight, 1000); + } else { + mButtonBarContainer.setTranslationY(0); + mButtonBarContainer.setTranslationZ(0); + } + mRoot.getViewTreeObserver().removeOnGlobalLayoutListener(this); + } + }); + + } + + @Override + public void onClick(View v) { + int id = v.getId(); + switch (id) { + case R.id.horizontal_allow_button: + case R.id.vertical_button1: + onButton1(); + break; + case R.id.horizontal_deny_button: + case R.id.vertical_button2: + onButton2(); + break; + case R.id.vertical_button3: + onButton3(); + break; + } + } + + @Override + public boolean handleMessage (Message msg) { + switch (msg.what) { + case MSG_HIDE_BUTTON_BAR: + hideButtonBar(); + return true; + } + return false; + } + + @Override + public void onScrollChanged() { + mHideHandler.removeMessages(MSG_HIDE_BUTTON_BAR); + hideButtonBar(); + } + + private void hideButtonBar() { + // get the offset to the top of the button bar + int offset = mScrollingContainer.getHeight() + mButtonBarContainer.getHeight() - + mContent.getHeight() + Math.max(mScrollingContainer.getScrollY(), 0); + // The desired margin space between the button bar and the bottom of the dialog text + int topMargin = mContext.getResources().getDimensionPixelSize( + R.dimen.conf_diag_button_container_top_margin); + int translationY = topMargin + (offset > 0 ? + mButtonBarContainer.getHeight() - offset : mButtonBarContainer.getHeight()); + + if (!mHiddenBefore || mButtonBarAnimator == null) { + // hasn't hidden the bar yet, just hide now to the right height + generateButtonBarAnimator( + mButtonBarContainer.getTranslationY(), translationY, + mButtonBarFloatingHeight, 0, HIDE_ANIM_DURATION); + } else if (mButtonBarAnimator.isRunning()) { + // we are animating the button bar closing, change to animate to the right place + if (Math.abs(mCurrentTranslation - translationY) > 1e-2f) { + mButtonBarAnimator.cancel(); // stop current animation + + if (Math.abs(mButtonBarContainer.getTranslationY() - translationY) > 1e-2f) { + long duration = Math.max((long) ( + (float) HIDE_ANIM_DURATION + * (translationY - mButtonBarContainer.getTranslationY()) + / mButtonBarContainer.getHeight()), 0); + generateButtonBarAnimator( + mButtonBarContainer.getTranslationY(), translationY, + mButtonBarFloatingHeight, 0, duration); + } else { + mButtonBarContainer.setTranslationY(translationY); + mButtonBarContainer.setTranslationZ(0); + } + } + } else { + // not currently animating, have already hidden, snap to the right offset + mButtonBarContainer.setTranslationY(translationY); + mButtonBarContainer.setTranslationZ(0); + } + + mHiddenBefore = true; + } + + private void generateButtonBarAnimator( + float startY, float endY, float startZ, float endZ, long duration) { + mButtonBarAnimator = + ObjectAnimator.ofPropertyValuesHolder( + mButtonBarContainer, + PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, startY, endY), + PropertyValuesHolder.ofFloat(View.TRANSLATION_Z, startZ, endZ)); + mCurrentTranslation = endY; + mButtonBarAnimator.setDuration(duration); + mButtonBarAnimator.setInterpolator(mInterpolator); + mButtonBarAnimator.start(); + } +} \ No newline at end of file -- cgit v1.2.3