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