Home | History | Annotate | Download | only in cardstream
      1 /*
      2 * Copyright 2013 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.example.android.batchstepsensor.cardstream;
     18 
     19 import android.animation.Animator;
     20 import android.animation.AnimatorListenerAdapter;
     21 import android.animation.ObjectAnimator;
     22 import android.app.Activity;
     23 import android.graphics.Color;
     24 import android.view.LayoutInflater;
     25 import android.view.View;
     26 import android.view.ViewGroup;
     27 import android.widget.Button;
     28 import android.widget.ProgressBar;
     29 import android.widget.TextView;
     30 
     31 import com.example.android.batchstepsensor.R;
     32 
     33 import java.util.ArrayList;
     34 
     35 /**
     36  * A Card contains a description and has a visual state. Optionally a card also contains a title,
     37  * progress indicator and zero or more actions. It is constructed through the {@link Builder}.
     38  */
     39 public class Card {
     40 
     41     public static final int ACTION_POSITIVE = 1;
     42     public static final int ACTION_NEGATIVE = 2;
     43     public static final int ACTION_NEUTRAL = 3;
     44 
     45     public static final int PROGRESS_TYPE_NO_PROGRESS = 0;
     46     public static final int PROGRESS_TYPE_NORMAL = 1;
     47     public static final int PROGRESS_TYPE_INDETERMINATE = 2;
     48     public static final int PROGRESS_TYPE_LABEL = 3;
     49 
     50     private OnCardClickListener mClickListener;
     51 
     52 
     53     // The card model contains a reference to its desired layout (for extensibility), title,
     54     // description, zero to many action buttons, and zero or 1 progress indicators.
     55     private int mLayoutId = R.layout.card;
     56 
     57     /**
     58      * Tag that uniquely identifies this card.
     59      */
     60     private String mTag = null;
     61 
     62     private String mTitle = null;
     63     private String mDescription = null;
     64 
     65     private View mCardView = null;
     66     private View mOverlayView = null;
     67     private TextView mTitleView = null;
     68     private TextView mDescView = null;
     69     private View mActionAreaView = null;
     70 
     71     private Animator mOngoingAnimator = null;
     72 
     73     /**
     74      * Visual state, either {@link #CARD_STATE_NORMAL}, {@link #CARD_STATE_FOCUSED} or
     75      * {@link #CARD_STATE_INACTIVE}.
     76      */
     77     private int mCardState = CARD_STATE_NORMAL;
     78     public static final int CARD_STATE_NORMAL = 1;
     79     public static final int CARD_STATE_FOCUSED = 2;
     80     public static final int CARD_STATE_INACTIVE = 3;
     81 
     82     /**
     83      * Represent actions that can be taken from the card.  Stylistically the developer can
     84      * designate the action as positive, negative (ok/cancel, for instance), or neutral.
     85      * This "type" can be used as a UI hint.
     86      * @see com.example.android.sensors.batchstepsensor.Card.CardAction
     87      */
     88     private ArrayList<CardAction> mCardActions = new ArrayList<CardAction>();
     89 
     90     /**
     91      * Some cards will have a sense of "progress" which should be associated with, but separated
     92      * from its "parent" card.  To push for simplicity in samples, Cards are designed to have
     93      * a maximum of one progress indicator per Card.
     94      */
     95     private CardProgress mCardProgress = null;
     96 
     97     public Card() {
     98     }
     99 
    100     public String getTag() {
    101         return mTag;
    102     }
    103 
    104     public View getView() {
    105         return mCardView;
    106     }
    107 
    108 
    109     public Card setDescription(String desc) {
    110         if (mDescView != null) {
    111             mDescription = desc;
    112             mDescView.setText(desc);
    113         }
    114         return this;
    115     }
    116 
    117     public Card setTitle(String title) {
    118         if (mTitleView != null) {
    119             mTitle = title;
    120             mTitleView.setText(title);
    121         }
    122         return this;
    123     }
    124 
    125 
    126     /**
    127      * Return the UI state, either {@link #CARD_STATE_NORMAL}, {@link #CARD_STATE_FOCUSED}
    128      * or {@link #CARD_STATE_INACTIVE}.
    129      */
    130     public int getState() {
    131         return mCardState;
    132     }
    133 
    134     /**
    135      * Set the UI state. The parameter describes the state and must be either
    136      * {@link #CARD_STATE_NORMAL}, {@link #CARD_STATE_FOCUSED} or {@link #CARD_STATE_INACTIVE}.
    137      * Note: This method must be called from the UI Thread.
    138      * @param state
    139      * @return The card itself, allows for chaining of calls
    140      */
    141     public Card setState(int state) {
    142         mCardState = state;
    143         if (null != mOverlayView) {
    144             if (null != mOngoingAnimator) {
    145                 mOngoingAnimator.end();
    146                 mOngoingAnimator = null;
    147             }
    148             switch (state) {
    149                 case CARD_STATE_NORMAL: {
    150                     mOverlayView.setVisibility(View.GONE);
    151                     mOverlayView.setAlpha(1.f);
    152                     break;
    153                 }
    154                 case CARD_STATE_FOCUSED: {
    155                     mOverlayView.setVisibility(View.VISIBLE);
    156                     mOverlayView.setBackgroundResource(R.drawable.card_overlay_focused);
    157                     ObjectAnimator animator = ObjectAnimator.ofFloat(mOverlayView, "alpha", 0.f);
    158                     animator.setRepeatMode(ObjectAnimator.REVERSE);
    159                     animator.setRepeatCount(ObjectAnimator.INFINITE);
    160                     animator.setDuration(1000);
    161                     animator.start();
    162                     mOngoingAnimator = animator;
    163                     break;
    164                 }
    165                 case CARD_STATE_INACTIVE: {
    166                     mOverlayView.setVisibility(View.VISIBLE);
    167                     mOverlayView.setAlpha(1.f);
    168                     mOverlayView.setBackgroundColor(Color.argb(0xaa, 0xcc, 0xcc, 0xcc));
    169                     break;
    170                 }
    171             }
    172         }
    173         return this;
    174     }
    175 
    176     /**
    177      * Set the type of progress indicator.
    178      * The progress type can only be changed if the Card was initially build with a progress
    179      * indicator.
    180      * See {@link Builder#setProgressType(int)}.
    181      * Must be a value of either {@link #PROGRESS_TYPE_NORMAL},
    182      * {@link #PROGRESS_TYPE_INDETERMINATE}, {@link #PROGRESS_TYPE_LABEL} or
    183      * {@link #PROGRESS_TYPE_NO_PROGRESS}.
    184      * @param progressType
    185      * @return The card itself, allows for chaining of calls
    186      */
    187     public Card setProgressType(int progressType) {
    188         if (mCardProgress == null) {
    189             mCardProgress = new CardProgress();
    190         }
    191         mCardProgress.setProgressType(progressType);
    192         return this;
    193     }
    194 
    195     /**
    196      * Return the progress indicator type. A value of either {@link #PROGRESS_TYPE_NORMAL},
    197      * {@link #PROGRESS_TYPE_INDETERMINATE}, {@link #PROGRESS_TYPE_LABEL}. Otherwise if no progress
    198      * indicator is enabled, {@link #PROGRESS_TYPE_NO_PROGRESS} is returned.
    199      * @return
    200      */
    201     public int getProgressType() {
    202         if (mCardProgress == null) {
    203             return PROGRESS_TYPE_NO_PROGRESS;
    204         }
    205         return mCardProgress.progressType;
    206     }
    207 
    208     /**
    209      * Set the progress to the specified value. Only applicable if the card has a
    210      * {@link #PROGRESS_TYPE_NORMAL} progress type.
    211      * @param progress
    212      * @return
    213      * @see #setMaxProgress(int)
    214      */
    215     public Card setProgress(int progress) {
    216         if (mCardProgress != null) {
    217             mCardProgress.setProgress(progress);
    218         }
    219         return this;
    220     }
    221 
    222     /**
    223      * Set the range of the progress to 0...max. Only applicable if the card has a
    224      * {@link #PROGRESS_TYPE_NORMAL} progress type.
    225      * @return
    226      */
    227     public Card setMaxProgress(int max){
    228         if (mCardProgress != null) {
    229             mCardProgress.setMax(max);
    230         }
    231         return this;
    232     }
    233 
    234     /**
    235      * Set the label text for the progress if the card has a progress type of
    236      * {@link #PROGRESS_TYPE_NORMAL}, {@link #PROGRESS_TYPE_INDETERMINATE} or
    237      * {@link #PROGRESS_TYPE_LABEL}
    238      * @param text
    239      * @return
    240      */
    241     public Card setProgressLabel(String text) {
    242         if (mCardProgress != null) {
    243             mCardProgress.setProgressLabel(text);
    244         }
    245         return this;
    246     }
    247 
    248     /**
    249      * Toggle the visibility of the progress section of the card. Only applicable if
    250      * the card has a progress type of
    251      * {@link #PROGRESS_TYPE_NORMAL}, {@link #PROGRESS_TYPE_INDETERMINATE} or
    252      * {@link #PROGRESS_TYPE_LABEL}.
    253      * @param isVisible
    254      * @return
    255      */
    256     public Card setProgressVisibility(boolean isVisible) {
    257         if (mCardProgress.progressView == null) {
    258             return this; // Card does not have progress
    259         }
    260         mCardProgress.progressView.setVisibility(isVisible ? View.VISIBLE : View.GONE);
    261 
    262         return this;
    263     }
    264 
    265     /**
    266      * Adds an action to this card during build time.
    267      *
    268      * @param label
    269      * @param id
    270      * @param type
    271      */
    272     private void addAction(String label, int id, int type) {
    273         CardAction cardAction = new CardAction();
    274         cardAction.label = label;
    275         cardAction.id = id;
    276         cardAction.type = type;
    277         mCardActions.add(cardAction);
    278     }
    279 
    280     /**
    281      * Toggles the visibility of a card action.
    282      * @param actionId
    283      * @param isVisible
    284      * @return
    285      */
    286     public Card setActionVisibility(int actionId, boolean isVisible) {
    287         int visibilityFlag = isVisible ? View.VISIBLE : View.GONE;
    288         for (CardAction action : mCardActions) {
    289             if (action.id == actionId && action.actionView != null) {
    290                 action.actionView.setVisibility(visibilityFlag);
    291             }
    292         }
    293         return this;
    294     }
    295 
    296     /**
    297      * Toggles visibility of the action area of this Card through an animation.
    298      * @param isVisible
    299      * @return
    300      */
    301     public Card setActionAreaVisibility(boolean isVisible) {
    302         if (mActionAreaView == null) {
    303             return this; // Card does not have an action area
    304         }
    305 
    306         if (isVisible) {
    307             // Show the action area
    308             mActionAreaView.setVisibility(View.VISIBLE);
    309             mActionAreaView.setPivotY(0.f);
    310             mActionAreaView.setPivotX(mCardView.getWidth() / 2.f);
    311             mActionAreaView.setAlpha(0.5f);
    312             mActionAreaView.setRotationX(-90.f);
    313             mActionAreaView.animate().rotationX(0.f).alpha(1.f).setDuration(400);
    314         } else {
    315             // Hide the action area
    316             mActionAreaView.setPivotY(0.f);
    317             mActionAreaView.setPivotX(mCardView.getWidth() / 2.f);
    318             mActionAreaView.animate().rotationX(-90.f).alpha(0.f).setDuration(400).setListener(
    319                     new AnimatorListenerAdapter() {
    320                         @Override
    321                         public void onAnimationEnd(Animator animation) {
    322                             mActionAreaView.setVisibility(View.GONE);
    323                         }
    324                     });
    325         }
    326         return this;
    327     }
    328 
    329 
    330     /**
    331      * Creates a shallow clone of the card.  Shallow means all values are present, but no views.
    332      * This is useful for saving/restoring in the case of configuration changes, like screen
    333      * rotation.
    334      *
    335      * @return A shallow clone of the card instance
    336      */
    337     public Card createShallowClone() {
    338         Card cloneCard = new Card();
    339 
    340         // Outer card values
    341         cloneCard.mTitle = mTitle;
    342         cloneCard.mDescription = mDescription;
    343         cloneCard.mTag = mTag;
    344         cloneCard.mLayoutId = mLayoutId;
    345         cloneCard.mCardState = mCardState;
    346 
    347         // Progress
    348         if (mCardProgress != null) {
    349             cloneCard.mCardProgress = mCardProgress.createShallowClone();
    350         }
    351 
    352         // Actions
    353         for (CardAction action : mCardActions) {
    354             cloneCard.mCardActions.add(action.createShallowClone());
    355         }
    356 
    357         return cloneCard;
    358     }
    359 
    360 
    361     /**
    362      * Prepare the card to be stored for configuration change.
    363      */
    364     public void prepareForConfigurationChange() {
    365         // Null out views.
    366         mCardView = null;
    367         for (CardAction action : mCardActions) {
    368             action.actionView = null;
    369         }
    370         mCardProgress.progressView = null;
    371     }
    372 
    373     /**
    374      * Creates a new {@link #Card}.
    375      */
    376     public static class Builder {
    377         private Card mCard;
    378 
    379         /**
    380          * Instantiate the builder with data from a shallow clone.
    381          * @param listener
    382          * @param card
    383          * @see Card#createShallowClone()
    384          */
    385         protected Builder(OnCardClickListener listener, Card card) {
    386             mCard = card;
    387             mCard.mClickListener = listener;
    388         }
    389 
    390         /**
    391          * Instantiate the builder with the tag of the card.
    392          * @param listener
    393          * @param tag
    394          */
    395         public Builder(OnCardClickListener listener, String tag) {
    396             mCard = new Card();
    397             mCard.mTag = tag;
    398             mCard.mClickListener = listener;
    399         }
    400 
    401         public Builder setTitle(String title) {
    402             mCard.mTitle = title;
    403             return this;
    404         }
    405 
    406         public Builder setDescription(String desc) {
    407             mCard.mDescription = desc;
    408             return this;
    409         }
    410 
    411         /**
    412          * Add an action.
    413          * The type describes how this action will be displayed. Accepted values are
    414          * {@link #ACTION_NEUTRAL}, {@link #ACTION_POSITIVE} or {@link #ACTION_NEGATIVE}.
    415          *
    416          * @param label The text to display for this action
    417          * @param id Identifier for this action, supplied in the click listener
    418          * @param type UI style of action
    419          * @return
    420          */
    421         public Builder addAction(String label, int id, int type) {
    422             mCard.addAction(label, id, type);
    423             return this;
    424         }
    425 
    426         /**
    427          * Override the default layout.
    428          * The referenced layout file has to contain the same identifiers as defined in the default
    429          * layout configuration.
    430          * @param layout
    431          * @return
    432          * @see R.layout.card
    433          */
    434         public Builder setLayout(int layout) {
    435             mCard.mLayoutId = layout;
    436             return this;
    437         }
    438 
    439         /**
    440          * Set the type of progress bar to display.
    441          * Accepted values are:
    442          * <ul>
    443          *     <li>{@link #PROGRESS_TYPE_NO_PROGRESS} disables the progress indicator</li>
    444          *     <li>{@link #PROGRESS_TYPE_NORMAL}
    445          *     displays a standard, linear progress indicator.</li>
    446          *     <li>{@link #PROGRESS_TYPE_INDETERMINATE} displays an indeterminate (infite) progress
    447          *     indicator.</li>
    448          *     <li>{@link #PROGRESS_TYPE_LABEL} only displays a label text in the progress area
    449          *     of the card.</li>
    450          * </ul>
    451          *
    452          * @param progressType
    453          * @return
    454          */
    455         public Builder setProgressType(int progressType) {
    456             mCard.setProgressType(progressType);
    457             return this;
    458         }
    459 
    460         public Builder setProgressLabel(String label) {
    461             // ensure the progress layout has been initialized, use 'no progress' by default
    462             if (mCard.mCardProgress == null) {
    463                 mCard.setProgressType(PROGRESS_TYPE_NO_PROGRESS);
    464             }
    465             mCard.mCardProgress.label = label;
    466             return this;
    467         }
    468 
    469         public Builder setProgressMaxValue(int maxValue) {
    470             // ensure the progress layout has been initialized, use 'no progress' by default
    471             if (mCard.mCardProgress == null) {
    472                 mCard.setProgressType(PROGRESS_TYPE_NO_PROGRESS);
    473             }
    474             mCard.mCardProgress.maxValue = maxValue;
    475             return this;
    476         }
    477 
    478         public Builder setStatus(int status) {
    479             mCard.setState(status);
    480             return this;
    481         }
    482 
    483         public Card build(Activity activity) {
    484             LayoutInflater inflater = activity.getLayoutInflater();
    485             // Inflating the card.
    486             ViewGroup cardView = (ViewGroup) inflater.inflate(mCard.mLayoutId,
    487                     (ViewGroup) activity.findViewById(R.id.card_stream), false);
    488 
    489             // Check that the layout contains a TextView with the card_title id
    490             View viewTitle = cardView.findViewById(R.id.card_title);
    491             if (mCard.mTitle != null && viewTitle != null) {
    492                 mCard.mTitleView = (TextView) viewTitle;
    493                 mCard.mTitleView.setText(mCard.mTitle);
    494             } else if (viewTitle != null) {
    495                 viewTitle.setVisibility(View.GONE);
    496             }
    497 
    498             // Check that the layout contains a TextView with the card_content id
    499             View viewDesc = cardView.findViewById(R.id.card_content);
    500             if (mCard.mDescription != null && viewDesc != null) {
    501                 mCard.mDescView = (TextView) viewDesc;
    502                 mCard.mDescView.setText(mCard.mDescription);
    503             } else if (viewDesc != null) {
    504                 cardView.findViewById(R.id.card_content).setVisibility(View.GONE);
    505             }
    506 
    507 
    508             ViewGroup actionArea = (ViewGroup) cardView.findViewById(R.id.card_actionarea);
    509 
    510             // Inflate Progress
    511             initializeProgressView(inflater, actionArea);
    512 
    513             // Inflate all action views.
    514             initializeActionViews(inflater, cardView, actionArea);
    515 
    516             mCard.mCardView = cardView;
    517             mCard.mOverlayView = cardView.findViewById(R.id.card_overlay);
    518 
    519             return mCard;
    520         }
    521 
    522         /**
    523          * Initialize data from the given card.
    524          * @param card
    525          * @return
    526          * @see Card#createShallowClone()
    527          */
    528         public Builder cloneFromCard(Card card) {
    529             mCard = card.createShallowClone();
    530             return this;
    531         }
    532 
    533         /**
    534          * Build the action views by inflating the appropriate layouts and setting the text and
    535          * values.
    536          * @param inflater
    537          * @param cardView
    538          * @param actionArea
    539          */
    540         private void initializeActionViews(LayoutInflater inflater, ViewGroup cardView,
    541                                            ViewGroup actionArea) {
    542             if (!mCard.mCardActions.isEmpty()) {
    543                 // Set action area to visible only when actions are visible
    544                 actionArea.setVisibility(View.VISIBLE);
    545                 mCard.mActionAreaView = actionArea;
    546             }
    547 
    548             // Inflate all card actions
    549             for (final CardAction action : mCard.mCardActions) {
    550 
    551                 int useActionLayout = 0;
    552                 switch (action.type) {
    553                     case Card.ACTION_POSITIVE:
    554                         useActionLayout = R.layout.card_button_positive;
    555                         break;
    556                     case Card.ACTION_NEGATIVE:
    557                         useActionLayout = R.layout.card_button_negative;
    558                         break;
    559                     case Card.ACTION_NEUTRAL:
    560                     default:
    561                         useActionLayout = R.layout.card_button_neutral;
    562                         break;
    563                 }
    564 
    565                 action.actionView = inflater.inflate(useActionLayout, actionArea, false);
    566                 Button actionButton = (Button) action.actionView.findViewById(R.id.card_button);
    567 
    568                 actionButton.setText(action.label);
    569                 actionButton.setOnClickListener(new View.OnClickListener() {
    570                     @Override
    571                     public void onClick(View v) {
    572                         mCard.mClickListener.onCardClick(action.id, mCard.mTag);
    573                     }
    574                 });
    575                 actionArea.addView(action.actionView);
    576             }
    577         }
    578 
    579         /**
    580          * Build the progress view into the given ViewGroup.
    581          *
    582          * @param inflater
    583          * @param actionArea
    584          */
    585         private void initializeProgressView(LayoutInflater inflater, ViewGroup actionArea) {
    586 
    587             // Only inflate progress layout if a progress type other than NO_PROGRESS was set.
    588             if (mCard.mCardProgress != null) {
    589                 //Setup progress card.
    590                 View progressView = inflater.inflate(R.layout.card_progress, actionArea, false);
    591                 ProgressBar progressBar =
    592                         (ProgressBar) progressView.findViewById(R.id.card_progress);
    593                 ((TextView) progressView.findViewById(R.id.card_progress_text))
    594                         .setText(mCard.mCardProgress.label);
    595                 progressBar.setMax(mCard.mCardProgress.maxValue);
    596                 progressBar.setProgress(0);
    597                 mCard.mCardProgress.progressView = progressView;
    598                 mCard.mCardProgress.setProgressType(mCard.getProgressType());
    599                 actionArea.addView(progressView);
    600             }
    601         }
    602     }
    603 
    604     /**
    605      * Represents a clickable action, accessible from the bottom of the card.
    606      * Fields include the label, an ID to specify the action that was performed in the callback,
    607      * an action type (positive, negative, neutral), and the callback.
    608      */
    609     public class CardAction {
    610 
    611         public String label;
    612         public int id;
    613         public int type;
    614         public View actionView;
    615 
    616         public CardAction createShallowClone() {
    617             CardAction actionClone = new CardAction();
    618             actionClone.label = label;
    619             actionClone.id = id;
    620             actionClone.type = type;
    621             return actionClone;
    622             // Not the view.  Never the view (don't want to hold view references for
    623             // onConfigurationChange.
    624         }
    625 
    626     }
    627 
    628     /**
    629      * Describes the progress of a {@link Card}.
    630      * Three types of progress are supported:
    631      * <ul><li>{@link Card#PROGRESS_TYPE_NORMAL: Standard progress bar with label text</li>
    632      * <li>{@link Card#PROGRESS_TYPE_INDETERMINATE}: Indeterminate progress bar with label txt</li>
    633      * <li>{@link Card#PROGRESS_TYPE_LABEL}: Label only, no progresss bar</li>
    634      * </ul>
    635      */
    636     public class CardProgress {
    637         private int progressType = Card.PROGRESS_TYPE_NO_PROGRESS;
    638         private String label = "";
    639         private int currProgress = 0;
    640         private int maxValue = 100;
    641 
    642         public View progressView = null;
    643         private ProgressBar progressBar = null;
    644         private TextView progressLabel = null;
    645 
    646         public CardProgress createShallowClone() {
    647             CardProgress progressClone = new CardProgress();
    648             progressClone.label = label;
    649             progressClone.currProgress = currProgress;
    650             progressClone.maxValue = maxValue;
    651             progressClone.progressType = progressType;
    652             return progressClone;
    653         }
    654 
    655         /**
    656          * Set the progress. Only useful for the type {@link #PROGRESS_TYPE_NORMAL}.
    657          * @param progress
    658          * @see android.widget.ProgressBar#setProgress(int)
    659          */
    660         public void setProgress(int progress) {
    661             currProgress = progress;
    662             final ProgressBar bar = getProgressBar();
    663             if (bar != null) {
    664                 bar.setProgress(currProgress);
    665                 bar.invalidate();
    666             }
    667         }
    668 
    669         /**
    670          * Set the range of the progress to 0...max.
    671          * Only useful for the type {@link #PROGRESS_TYPE_NORMAL}.
    672          * @param max
    673          * @see android.widget.ProgressBar#setMax(int)
    674          */
    675         public void setMax(int max) {
    676             maxValue = max;
    677             final ProgressBar bar = getProgressBar();
    678             if (bar != null) {
    679                 bar.setMax(maxValue);
    680             }
    681         }
    682 
    683         /**
    684          * Set the label text that appears near the progress indicator.
    685          * @param text
    686          */
    687         public void setProgressLabel(String text) {
    688             label = text;
    689             final TextView labelView = getProgressLabel();
    690             if (labelView != null) {
    691                 labelView.setText(text);
    692             }
    693         }
    694 
    695         /**
    696          * Set how progress is displayed. The parameter must be one of three supported types:
    697          * <ul><li>{@link Card#PROGRESS_TYPE_NORMAL: Standard progress bar with label text</li>
    698          * <li>{@link Card#PROGRESS_TYPE_INDETERMINATE}:
    699          * Indeterminate progress bar with label txt</li>
    700          * <li>{@link Card#PROGRESS_TYPE_LABEL}: Label only, no progresss bar</li>
    701          * @param type
    702          */
    703         public void setProgressType(int type) {
    704             progressType = type;
    705             if (progressView != null) {
    706                 switch (type) {
    707                     case PROGRESS_TYPE_NO_PROGRESS: {
    708                         progressView.setVisibility(View.GONE);
    709                         break;
    710                     }
    711                     case PROGRESS_TYPE_NORMAL: {
    712                         progressView.setVisibility(View.VISIBLE);
    713                         getProgressBar().setIndeterminate(false);
    714                         break;
    715                     }
    716                     case PROGRESS_TYPE_INDETERMINATE: {
    717                         progressView.setVisibility(View.VISIBLE);
    718                         getProgressBar().setIndeterminate(true);
    719                         break;
    720                     }
    721                 }
    722             }
    723         }
    724 
    725         private TextView getProgressLabel() {
    726             if (progressLabel != null) {
    727                 return progressLabel;
    728             } else if (progressView != null) {
    729                 progressLabel = (TextView) progressView.findViewById(R.id.card_progress_text);
    730                 return progressLabel;
    731             } else {
    732                 return null;
    733             }
    734         }
    735 
    736         private ProgressBar getProgressBar() {
    737             if (progressBar != null) {
    738                 return progressBar;
    739             } else if (progressView != null) {
    740                 progressBar = (ProgressBar) progressView.findViewById(R.id.card_progress);
    741                 return progressBar;
    742             } else {
    743                 return null;
    744             }
    745         }
    746 
    747     }
    748 }
    749 
    750