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