blob: d28866ef80012fc8710e7aaf7ed0706d2a706820 [file] [log] [blame]
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();
}
}