Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2012 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.deskclock.widget;
     18 
     19 import android.animation.Animator;
     20 import android.animation.AnimatorInflater;
     21 import android.animation.AnimatorListenerAdapter;
     22 import android.content.Context;
     23 import android.util.AttributeSet;
     24 import android.view.LayoutInflater;
     25 import android.view.MotionEvent;
     26 import android.view.View;
     27 import android.widget.FrameLayout;
     28 import android.widget.ImageView;
     29 import android.widget.LinearLayout;
     30 import android.widget.TextView;
     31 
     32 import com.android.deskclock.R;
     33 
     34 /**
     35  * A custom {@link View} that exposes an action to the user.
     36  * <p>
     37  * This is a copy of packages/apps/UnifiedEmail/src/com/android/mail/ui/ActionableToastBar.java
     38  * with minor modifications.
     39  */
     40 public class ActionableToastBar extends LinearLayout {
     41     private boolean mHidden = false;
     42     private Animator mShowAnimation;
     43     private Animator mHideAnimation;
     44     private final int mBottomMarginSizeInConversation;
     45 
     46     /** Icon for the description. */
     47     private ImageView mActionDescriptionIcon;
     48     /** The clickable view */
     49     private View mActionButton;
     50     /** Icon for the action button. */
     51     private View mActionIcon;
     52     /** The view that contains the description. */
     53     private TextView mActionDescriptionView;
     54     /** The view that contains the text for the action button. */
     55     private TextView mActionText;
     56     //private ToastBarOperation mOperation;
     57 
     58     public ActionableToastBar(Context context) {
     59         this(context, null);
     60     }
     61 
     62     public ActionableToastBar(Context context, AttributeSet attrs) {
     63         this(context, attrs, 0);
     64     }
     65 
     66     public ActionableToastBar(Context context, AttributeSet attrs, int defStyle) {
     67         super(context, attrs, defStyle);
     68         mBottomMarginSizeInConversation = context.getResources().getDimensionPixelSize(
     69                 R.dimen.toast_bar_bottom_margin_in_conversation);
     70         LayoutInflater.from(context).inflate(R.layout.actionable_toast_row, this, true);
     71     }
     72 
     73     @Override
     74     protected void onFinishInflate() {
     75         super.onFinishInflate();
     76 
     77         mActionDescriptionIcon = (ImageView) findViewById(R.id.description_icon);
     78         mActionDescriptionView = (TextView) findViewById(R.id.description_text);
     79         mActionButton = findViewById(R.id.action_button);
     80         mActionIcon = findViewById(R.id.action_icon);
     81         mActionText = (TextView) findViewById(R.id.action_text);
     82     }
     83 
     84     /**
     85      * Tells the view that it will be appearing in the conversation pane
     86      * and should adjust its layout parameters accordingly.
     87      * @param isInConversationMode true if the view will be shown in the conversation view
     88      */
     89     public void setConversationMode(boolean isInConversationMode) {
     90         final FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
     91         params.bottomMargin = isInConversationMode ? mBottomMarginSizeInConversation : 0;
     92         setLayoutParams(params);
     93     }
     94 
     95     /**
     96      * Displays the toast bar and makes it visible. Allows the setting of
     97      * parameters to customize the display.
     98      * @param listener performs some action when the action button is clicked
     99      * @param descriptionIconResourceId resource ID for the description icon or
    100      * 0 if no icon should be shown
    101      * @param descriptionText a description text to show in the toast bar
    102      * @param showActionIcon if true, the action button icon should be shown
    103      * @param actionTextResource resource ID for the text to show in the action button
    104      * @param replaceVisibleToast if true, this toast should replace any currently visible toast.
    105      * Otherwise, skip showing this toast.
    106      */
    107     public void show(final ActionClickedListener listener, int descriptionIconResourceId,
    108             CharSequence descriptionText, boolean showActionIcon, int actionTextResource,
    109             boolean replaceVisibleToast) {
    110 
    111         if (!mHidden && !replaceVisibleToast) {
    112             return;
    113         }
    114 
    115         mActionButton.setOnClickListener(new OnClickListener() {
    116             @Override
    117             public void onClick(View widget) {
    118                 if (listener != null) {
    119                     listener.onActionClicked();
    120                 }
    121                 hide(true);
    122             }
    123         });
    124 
    125         // Set description icon.
    126         if (descriptionIconResourceId == 0) {
    127             mActionDescriptionIcon.setVisibility(GONE);
    128         } else {
    129             mActionDescriptionIcon.setVisibility(VISIBLE);
    130             mActionDescriptionIcon.setImageResource(descriptionIconResourceId);
    131         }
    132 
    133         mActionDescriptionView.setText(descriptionText);
    134         mActionIcon.setVisibility(showActionIcon ? VISIBLE : GONE);
    135         mActionText.setText(actionTextResource);
    136 
    137         mHidden = false;
    138         getShowAnimation().start();
    139     }
    140 
    141     /**
    142      * Hides the view and resets the state.
    143      */
    144     public void hide(boolean animate) {
    145         // Prevent multiple call to hide.
    146         // Also prevent hiding if show animation is going on.
    147         if (!mHidden && !getShowAnimation().isRunning()) {
    148             mHidden = true;
    149             if (getVisibility() == View.VISIBLE) {
    150                 mActionDescriptionView.setText("");
    151                 mActionButton.setOnClickListener(null);
    152                 // Hide view once it's clicked.
    153                 if (animate) {
    154                     getHideAnimation().start();
    155                 } else {
    156                     setAlpha(0);
    157                     setVisibility(View.GONE);
    158                 }
    159             }
    160         }
    161     }
    162 
    163     private Animator getShowAnimation() {
    164         if (mShowAnimation == null) {
    165             mShowAnimation = AnimatorInflater.loadAnimator(getContext(), R.animator.fade_in);
    166             mShowAnimation.addListener(new AnimatorListenerAdapter() {
    167                 @Override
    168                 public void onAnimationStart(Animator animation) {
    169                     setVisibility(View.VISIBLE);
    170                 }
    171 
    172                 @Override
    173                 public void onAnimationEnd(Animator animation) {
    174                     // There is a tiny change that and hide animation could have finished right
    175                     // before the show animation finished.  In that case, the hide will mark the
    176                     // view as GONE.  We need to make sure the last one wins.
    177                     setVisibility(View.VISIBLE);
    178                 }
    179             });
    180             mShowAnimation.setTarget(this);
    181         }
    182         return mShowAnimation;
    183     }
    184 
    185     private Animator getHideAnimation() {
    186         if (mHideAnimation == null) {
    187             mHideAnimation = AnimatorInflater.loadAnimator(getContext(), R.animator.fade_out);
    188             mHideAnimation.addListener(new AnimatorListenerAdapter() {
    189                 @Override
    190                 public void onAnimationEnd(Animator animation) {
    191                     setVisibility(View.GONE);
    192                 }
    193             });
    194             mHideAnimation.setTarget(this);
    195         }
    196         return mHideAnimation;
    197     }
    198 
    199     public boolean isEventInToastBar(MotionEvent event) {
    200         if (!isShown()) {
    201             return false;
    202         }
    203         int[] xy = new int[2];
    204         float x = event.getX();
    205         float y = event.getY();
    206         getLocationOnScreen(xy);
    207         return (x > xy[0] && x < (xy[0] + getWidth()) && y > xy[1] && y < xy[1] + getHeight());
    208     }
    209 
    210     /**
    211      * Classes that wish to perform some action when the action button is clicked
    212      * should implement this interface.
    213      */
    214     public interface ActionClickedListener {
    215         public void onActionClicked();
    216     }
    217 }
    218