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