BatchStepSensor / src / com.example.android.batchstepsensor / cardstream /

CardStreamFragment.java

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.os.Bundle;
23
import android.support.v4.app.Fragment;
24
import android.view.LayoutInflater;
25
import android.view.View;
26
import android.view.ViewGroup;
27
 
28
import java.util.Collection;
29
import java.util.HashMap;
30
import java.util.HashSet;
31
import java.util.LinkedHashMap;
32
 
33
import com.example.android.batchstepsensor.R;
34
 
35
/**
36
 * A Fragment that handles a stream of cards.
37
 * Cards can be shown or hidden. When a card is shown it can also be marked as not-dismissible, see
38
 * {@link CardStreamLinearLayout#addCard(android.view.View, boolean)}.
39
 */
40
public class CardStreamFragment extends Fragment {
41
 
42
    private static final int INITIAL_SIZE = 15;
43
    private CardStreamLinearLayout mLayout = null;
44
    private LinkedHashMap<String, Card> mVisibleCards = new LinkedHashMap<String, Card>(INITIAL_SIZE);
45
    private HashMap<String, Card> mHiddenCards = new HashMap<String, Card>(INITIAL_SIZE);
46
    private HashSet<String> mDismissibleCards = new HashSet<String>(INITIAL_SIZE);
47
 
48
    // Set the listener to handle dismissed cards by moving them to the hidden cards map.
49
    private CardStreamLinearLayout.OnDissmissListener mCardDismissListener =
50
            new CardStreamLinearLayout.OnDissmissListener() {
51
                @Override
52
                public void onDismiss(String tag) {
53
                    dismissCard(tag);
54
                }
55
            };
56
 
57
 
58
    @Override
59
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
60
                             Bundle savedInstanceState) {
61
 
62
        View view = inflater.inflate(R.layout.cardstream, container, false);
63
        mLayout = (CardStreamLinearLayout) view.findViewById(R.id.card_stream);
64
        mLayout.setOnDismissListener(mCardDismissListener);
65
 
66
        return view;
67
    }
68
 
69
    /**
70
     * Add a visible, dismissible card to the card stream.
71
     *
72
     * @param card
73
     */
74
    public void addCard(Card card) {
75
        final String tag = card.getTag();
76
 
77
        if (!mVisibleCards.containsKey(tag) && !mHiddenCards.containsKey(tag)) {
78
            final View view = card.getView();
79
            view.setTag(tag);
80
            mHiddenCards.put(tag, card);
81
        }
82
    }
83
 
84
    /**
85
     * Add and show a card.
86
     *
87
     * @param card
88
     * @param show
89
     */
90
    public void addCard(Card card, boolean show) {
91
        addCard(card);
92
        if (show) {
93
            showCard(card.getTag());
94
        }
95
    }
96
 
97
    /**
98
     * Remove a card and return true if it has been successfully removed.
99
     *
100
     * @param tag
101
     * @return
102
     */
103
    public boolean removeCard(String tag) {
104
        // Attempt to remove a visible card first
105
        Card card = mVisibleCards.get(tag);
106
        if (card != null) {
107
            // Card is visible, also remove from layout
108
            mVisibleCards.remove(tag);
109
            mLayout.removeView(card.getView());
110
            return true;
111
        } else {
112
            // Card is hidden, no need to remove from layout
113
            card = mHiddenCards.remove(tag);
114
            return card != null;
115
        }
116
    }
117
 
118
    /**
119
     * Show a dismissible card, returns false if the card could not be shown.
120
     *
121
     * @param tag
122
     * @return
123
     */
124
    public boolean showCard(String tag) {
125
        return showCard(tag, true);
126
    }
127
 
128
    /**
129
     * Show a card, returns false if the card could not be shown.
130
     *
131
     * @param tag
132
     * @param dismissible
133
     * @return
134
     */
135
    public boolean showCard(String tag, boolean dismissible) {
136
        final Card card = mHiddenCards.get(tag);
137
        // ensure the card is hidden and not already visible
138
        if (card != null && !mVisibleCards.containsValue(tag)) {
139
            mHiddenCards.remove(tag);
140
            mVisibleCards.put(tag, card);
141
            mLayout.addCard(card.getView(), dismissible);
142
            if (dismissible) {
143
                mDismissibleCards.add(tag);
144
            }
145
            return true;
146
        }
147
        return false;
148
    }
149
 
150
    /**
151
     * Hides the card, returns false if the card could not be hidden.
152
     *
153
     * @param tag
154
     * @return
155
     */
156
    public boolean hideCard(String tag) {
157
        final Card card = mVisibleCards.get(tag);
158
        if (card != null) {
159
            mVisibleCards.remove(tag);
160
            mDismissibleCards.remove(tag);
161
            mHiddenCards.put(tag, card);
162
 
163
            mLayout.removeView(card.getView());
164
            return true;
165
        }
166
        return mHiddenCards.containsValue(tag);
167
    }
168
 
169
 
170
    private void dismissCard(String tag) {
171
        final Card card = mVisibleCards.get(tag);
172
        if (card != null) {
173
            mDismissibleCards.remove(tag);
174
            mVisibleCards.remove(tag);
175
            mHiddenCards.put(tag, card);
176
        }
177
    }
178
 
179
 
180
    public boolean isCardVisible(String tag) {
181
        return mVisibleCards.containsValue(tag);
182
    }
183
 
184
    /**
185
     * Returns true if the card is shown and is dismissible.
186
     *
187
     * @param tag
188
     * @return
189
     */
190
    public boolean isCardDismissible(String tag) {
191
        return mDismissibleCards.contains(tag);
192
    }
193
 
194
    /**
195
     * Returns the Card for this tag.
196
     *
197
     * @param tag
198
     * @return
199
     */
200
    public Card getCard(String tag) {
201
        final Card card = mVisibleCards.get(tag);
202
        if (card != null) {
203
            return card;
204
        } else {
205
            return mHiddenCards.get(tag);
206
        }
207
    }
208
 
209
    /**
210
     * Moves the view port to show the card with this tag.
211
     *
212
     * @param tag
213
     * @see CardStreamLinearLayout#setFirstVisibleCard(String)
214
     */
215
    public void setFirstVisibleCard(String tag) {
216
        final Card card = mVisibleCards.get(tag);
217
        if (card != null) {
218
            mLayout.setFirstVisibleCard(tag);
219
        }
220
    }
221
 
222
    public int getVisibleCardCount() {
223
        return mVisibleCards.size();
224
    }
225
 
226
    public Collection<Card> getVisibleCards() {
227
        return mVisibleCards.values();
228
    }
229
 
230
    public void restoreState(CardStreamState state, OnCardClickListener callback) {
231
        // restore hidden cards
232
        for (Card c : state.hiddenCards) {
233
            Card card = new Card.Builder(callback,c).build(getActivity());
234
            mHiddenCards.put(card.getTag(), card);
235
        }
236
 
237
        // temporarily set up list of dismissible
238
        final HashSet<String> dismissibleCards = state.dismissibleCards;
239
 
240
        //restore shown cards
241
        for (Card c : state.visibleCards) {
242
            Card card = new Card.Builder(callback,c).build(getActivity());
243
            addCard(card);
244
            final String tag = card.getTag();
245
            showCard(tag, dismissibleCards.contains(tag));
246
        }
247
 
248
        // move to first visible card
249
        final String firstShown = state.shownTag;
250
        if (firstShown != null) {
251
            mLayout.setFirstVisibleCard(firstShown);
252
        }
253
 
254
        mLayout.triggerShowInitialAnimation();
255
    }
256
 
257
    public CardStreamState dumpState() {
258
        final Card[] visible = cloneCards(mVisibleCards.values());
259
        final Card[] hidden = cloneCards(mHiddenCards.values());
260
        final HashSet<String> dismissible = new HashSet<String>(mDismissibleCards);
261
        final String firstVisible = mLayout.getFirstVisibleCardTag();
262
 
263
        return new CardStreamState(visible, hidden, dismissible, firstVisible);
264
    }
265
 
266
    private Card[] cloneCards(Collection<Card> cards) {
267
        Card[] cardArray = new Card[cards.size()];
268
        int i = 0;
269
        for (Card c : cards) {
270
            cardArray[i++] = c.createShallowClone();
271
        }
272
 
273
        return cardArray;
274
    }
275
 
276
}