Skip to content

Commit 9260c5e

Browse files
Merge pull request #10 from mutualmobile/development
Added JavaDoc #3
2 parents d1779c7 + 23c258f commit 9260c5e

File tree

2 files changed

+153
-20
lines changed

2 files changed

+153
-20
lines changed

cardstack/src/main/java/com/mutualmobile/cardstack/CardStackAdapter.java

Lines changed: 94 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,25 @@
1616
import java.util.ArrayList;
1717
import java.util.List;
1818

19+
/**
20+
* This class acts as an adapter for the {@link CardStackLayout} view. This adapter is intentionally
21+
* made an abstract class with following abstract methods -
22+
* <p/>
23+
* <p/>
24+
* {@link #getCount()} - Decides the number of views present in the view
25+
* <p/>
26+
* {@link #createView(int, ViewGroup)} - Creates the view for all positions in range [0, {@link #getCount()})
27+
* <p/>
28+
* Contains the logic for touch events in {@link #onTouch(View, MotionEvent)}
29+
*/
1930
public abstract class CardStackAdapter implements View.OnTouchListener, View.OnClickListener {
2031

2132

2233
public static final int ANIM_DURATION = 600;
2334
public static final int DECELERATION_FACTOR = 2;
2435

36+
public static final int INVALID_CARD_POSITION = -1;
37+
2538
// Settings for the adapter from layout
2639
private float mCardGapBottom;
2740
private float mCardGap;
@@ -43,25 +56,39 @@ public abstract class CardStackAdapter implements View.OnTouchListener, View.OnC
4356
private float mTouchFirstY = -1;
4457
private float mTouchPrevY = -1;
4558
private float mTouchDistance = 0;
46-
private int mSelectedCardPosition = -1;
59+
private int mSelectedCardPosition = INVALID_CARD_POSITION;
4760
private float scaleFactorForElasticEffect;
4861
private int mParentPaddingTop = 0;
4962
private int mCardPaddingInternal = 0;
5063

51-
public View getCardView(int position) {
52-
if (mCardViews == null) return null;
53-
54-
return mCardViews[position];
55-
}
56-
64+
/**
65+
* Defines and initializes the view to be shown in the {@link CardStackLayout}
66+
* Provides two parameters to the sub-class namely -
67+
*
68+
* @param position
69+
* @param container
70+
*
71+
* @return View corresponding to the position and parent container
72+
*/
5773
public abstract View createView(int position, ViewGroup container);
5874

75+
/**
76+
* Defines the number of cards that are present in the {@link CardStackLayout}
77+
*
78+
* @return cardCount - Number of views in the related {@link CardStackLayout}
79+
*/
5980
public abstract int getCount();
6081

61-
public void setScreenTouchable(boolean screenTouchable) {
82+
private void setScreenTouchable(boolean screenTouchable) {
6283
this.mScreenTouchable = screenTouchable;
6384
}
6485

86+
/**
87+
* Returns true if no animation is in progress currently. Can be used to disable any events
88+
* if they are not allowed during an animation. Returns false if an animation is in progress.
89+
*
90+
* @return - true if animation in progress, false otherwise
91+
*/
6592
public boolean isScreenTouchable() {
6693
return mScreenTouchable;
6794
}
@@ -78,7 +105,7 @@ public CardStackAdapter(Context context) {
78105
mCardViews = new View[getCount()];
79106
}
80107

81-
public void addView(final int position) {
108+
void addView(final int position) {
82109
View root = createView(position, mParent);
83110
root.setOnTouchListener(this);
84111
root.setTag(R.id.cardstack_internal_position_tag, position);
@@ -101,14 +128,19 @@ public void addView(final int position) {
101128
mParent.addView(root);
102129
}
103130

104-
public float getCardFinalY(int position) {
131+
private float getCardFinalY(int position) {
105132
return mScreenHeight - dp30 - ((getCount() - position) * mCardGapBottom) - mCardPaddingInternal;
106133
}
107134

108135
private float getCardOriginalY(int position) {
109136
return mParentPaddingTop + mCardGap * position;
110137
}
111138

139+
/**
140+
* Resets all cards in {@link CardStackLayout} to their initial positions
141+
*
142+
* @param r Execute r.run() once the reset animation is done
143+
*/
112144
public void resetCards(Runnable r) {
113145
List<Animator> animations = new ArrayList<>(getCount());
114146
for (int i = 0; i < getCount(); i++) {
@@ -118,6 +150,13 @@ public void resetCards(Runnable r) {
118150
startAnimations(animations, r, true);
119151
}
120152

153+
/**
154+
* Plays together all animations passed in as parameter. Once animation is completed, r.run() is
155+
* executed. If parameter isReset is set to true, {@link #mSelectedCardPosition} is set to {@link #INVALID_CARD_POSITION}
156+
* @param animations
157+
* @param r
158+
* @param isReset
159+
*/
121160
private void startAnimations(List<Animator> animations, final Runnable r, final boolean isReset) {
122161
AnimatorSet animatorSet = new AnimatorSet();
123162
animatorSet.playTogether(animations);
@@ -129,7 +168,7 @@ public void onAnimationEnd(Animator animation) {
129168
if (r != null) r.run();
130169
setScreenTouchable(true);
131170
if (isReset)
132-
mSelectedCardPosition = -1;
171+
mSelectedCardPosition = INVALID_CARD_POSITION;
133172
}
134173
});
135174
animatorSet.start();
@@ -153,13 +192,13 @@ public boolean onTouch(View v, MotionEvent event) {
153192
mTouchDistance = 0;
154193
break;
155194
case MotionEvent.ACTION_MOVE:
156-
if (mSelectedCardPosition == -1)
195+
if (mSelectedCardPosition == INVALID_CARD_POSITION)
157196
moveCards(positionOfCardToMove, y - mTouchFirstY);
158197
mTouchDistance += Math.abs(y - mTouchPrevY);
159198
break;
160199
case MotionEvent.ACTION_CANCEL:
161200
case MotionEvent.ACTION_UP:
162-
if (mTouchDistance < dp8 && Math.abs(y - mTouchFirstY) < dp8 && mSelectedCardPosition == -1) {
201+
if (mTouchDistance < dp8 && Math.abs(y - mTouchFirstY) < dp8 && mSelectedCardPosition == INVALID_CARD_POSITION) {
163202
onClick(v);
164203
} else {
165204
resetCards();
@@ -178,7 +217,7 @@ public void onClick(final View v) {
178217
return;
179218
}
180219
setScreenTouchable(false);
181-
if (mSelectedCardPosition == -1) {
220+
if (mSelectedCardPosition == INVALID_CARD_POSITION) {
182221
mSelectedCardPosition = (int) v.getTag(R.id.cardstack_internal_position_tag);
183222

184223
List<Animator> animations = new ArrayList<>(getCount());
@@ -203,7 +242,7 @@ public void run() {
203242
}
204243
}
205244

206-
public void moveCards(int positionOfCardToMove, float diff) {
245+
private void moveCards(int positionOfCardToMove, float diff) {
207246
if (diff < 0 || positionOfCardToMove < 0 || positionOfCardToMove >= getCount()) return;
208247
for (int i = positionOfCardToMove; i < getCount(); i++) {
209248
final View child = mCardViews[i];
@@ -220,7 +259,12 @@ public void moveCards(int positionOfCardToMove, float diff) {
220259
}
221260
}
222261

223-
public void setAdapterParams(CardStackLayout cardStackLayout) {
262+
/**
263+
* Provides an API to {@link CardStackLayout} to set the parameters provided to it in its XML
264+
*
265+
* @param cardStackLayout Parent of all cards
266+
*/
267+
void setAdapterParams(CardStackLayout cardStackLayout) {
224268
mParent = cardStackLayout;
225269
mCardGapBottom = cardStackLayout.getCardGapBottom();
226270
mCardGap = cardStackLayout.getCardGap();
@@ -233,11 +277,43 @@ public void setAdapterParams(CardStackLayout cardStackLayout) {
233277
fullCardHeight = (int) (mScreenHeight - dp30 - dp8 - getCount() * mCardGapBottom);
234278
}
235279

280+
/**
281+
* Resets all cards in {@link CardStackLayout} to their initial positions
282+
*/
236283
public void resetCards() {
237284
resetCards(null);
238285
}
239286

287+
/**
288+
* Returns false if all the cards are in their initial position i.e. no card is selected
289+
*
290+
* Returns true if the {@link CardStackLayout} has a card selected and all other cards are
291+
* at the bottom of the screen.
292+
*
293+
* @return true if any card is selected, false otherwise
294+
*/
240295
public boolean isCardSelected() {
241-
return mSelectedCardPosition != -1;
296+
return mSelectedCardPosition != INVALID_CARD_POSITION;
297+
}
298+
299+
/**
300+
* Returns the position of selected card. If no card
301+
* is selected, returns {@link #INVALID_CARD_POSITION}
302+
*/
303+
public int getSelectedCardPosition() {
304+
return mSelectedCardPosition;
305+
}
306+
307+
/**
308+
* Since there is no view recycling in {@link CardStackLayout}, we maintain an instance of every
309+
* view that is set for every position. This method returns a view at the requested position.
310+
*
311+
* @param position Position of card in {@link CardStackLayout}
312+
* @return View at requested position
313+
*/
314+
public View getCardView(int position) {
315+
if (mCardViews == null) return null;
316+
317+
return mCardViews[position];
242318
}
243-
}
319+
}

cardstack/src/main/java/com/mutualmobile/cardstack/CardStackLayout.java

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,19 @@
88
import android.view.View;
99
import android.widget.FrameLayout;
1010

11+
/**
12+
* Displays a list of cards as a stack on the screen.
13+
* <p/>
14+
* <b>XML attributes</b>
15+
* <p/>
16+
* See {@link R.styleable#CardStackLayout CardStackLayout Attributes}
17+
*
18+
* {@link R.styleable#CardStackLayout_showInitAnimation}
19+
* {@link R.styleable#CardStackLayout_card_gap}
20+
* {@link R.styleable#CardStackLayout_card_gap_bottom}
21+
* {@link R.styleable#CardStackLayout_parallax_enabled}
22+
* {@link R.styleable#CardStackLayout_parallax_scale}
23+
*/
1124
public class CardStackLayout extends FrameLayout {
1225
public static final boolean PARALLAX_ENABLED_DEFAULT = false;
1326
public static final boolean SHOW_INIT_ANIMATION_DEFAULT = true;
@@ -26,11 +39,20 @@ public CardStackLayout(Context context) {
2639
resetDefaults();
2740
}
2841

29-
public OnCardSelected getOnCardSelectedListener() {
42+
/**
43+
* package restricted
44+
*/
45+
OnCardSelected getOnCardSelectedListener() {
3046
return mOnCardSelectedListener;
3147
}
3248

33-
public void setOnCardSelected(OnCardSelected onCardSelectedListener) {
49+
/**
50+
* Listen on card selection events for {@link CardStackLayout}. Sends clicked view and it's
51+
* corresponding position in the callback.
52+
*
53+
* @param onCardSelectedListener listener
54+
*/
55+
public void setOnCardSelectedListener(OnCardSelected onCardSelectedListener) {
3456
this.mOnCardSelectedListener = onCardSelectedListener;
3557
}
3658

@@ -67,10 +89,17 @@ private void handleArgs(Context context, AttributeSet attrs, int defStyleAttr, i
6789
a.recycle();
6890
}
6991

92+
/**
93+
* @return adapter of type {@link CardStackAdapter} that is set for this view.
94+
*/
7095
public CardStackAdapter getAdapter() {
7196
return mAdapter;
7297
}
7398

99+
/**
100+
* Set the adapter for this {@link CardStackLayout}
101+
* @param adapter Should extend {@link CardStackAdapter}
102+
*/
74103
public void setAdapter(CardStackAdapter adapter) {
75104
this.mAdapter = adapter;
76105
mAdapter.setAdapterParams(this);
@@ -88,10 +117,17 @@ public void run() {
88117
}
89118
}
90119

120+
/**
121+
* @return currently set parallax scale value.
122+
*/
91123
public int getParallaxScale() {
92124
return mParallaxScale;
93125
}
94126

127+
/**
128+
* Sets the value of parallax scale. Parallax scale is the factor which decides how much
129+
* distance a card will scroll when the user drags it down.
130+
*/
95131
public void setParallaxScale(int mParallaxScale) {
96132
this.mParallaxScale = mParallaxScale;
97133
}
@@ -112,14 +148,23 @@ public void setShowInitAnimation(boolean mShowInitAnimation) {
112148
this.mShowInitAnimation = mShowInitAnimation;
113149
}
114150

151+
/**
152+
* @return the gap (in pixels) between two consecutive cards
153+
*/
115154
public float getCardGap() {
116155
return mCardGap;
117156
}
118157

158+
/**
159+
* Set the gap (in pixels) between two consecutive cards
160+
*/
119161
public void setCardGap(float mCardGap) {
120162
this.mCardGap = mCardGap;
121163
}
122164

165+
/**
166+
* @return gap between the two consecutive cards when collapsed to the bottom of the screen
167+
*/
123168
public float getCardGapBottom() {
124169
return mCardGapBottom;
125170
}
@@ -128,21 +173,33 @@ public void setCardGapBottom(float mCardGapBottom) {
128173
this.mCardGapBottom = mCardGapBottom;
129174
}
130175

176+
/**
177+
* @return true if a card is selected, false otherwise
178+
*/
131179
public boolean isCardSelected() {
132180
return mAdapter.isCardSelected();
133181
}
134182

183+
/**
184+
* Removes the adapter that was previously set using {@link #setAdapter(CardStackAdapter)}
185+
*/
135186
public void removeAdapter() {
136187
if (getChildCount() > 0)
137188
removeAllViews();
138189
mAdapter = null;
139190
mOnCardSelectedListener = null;
140191
}
141192

193+
/**
194+
* Animates the cards to their initial position in the layout.
195+
*/
142196
public void restoreCards() {
143197
mAdapter.resetCards();
144198
}
145199

200+
/**
201+
* Intimates the implementing class about the selection of a card
202+
*/
146203
public interface OnCardSelected {
147204
void onCardSelected(View v, int position);
148205
}

0 commit comments

Comments
 (0)