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