Skip to content

Commit 25d7f1c

Browse files
Merge pull request #156 from fractalwrench/upstream/master
Upstream/master
2 parents 2d2aeb9 + 8dda205 commit 25d7f1c

33 files changed

+817
-214
lines changed

AndroidBootstrap/build.gradle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@ apply from: 'push.gradle'
33

44
android {
55
compileSdkVersion 23
6-
buildToolsVersion "23.0.2"
6+
buildToolsVersion "23.0.3"
77

88
defaultConfig {
9-
minSdkVersion 11
9+
minSdkVersion 14
1010
targetSdkVersion 23
1111
versionCode = Integer.parseInt(VERSION_CODE)
1212
versionName = VERSION_NAME
1313
}
1414
}
1515

1616
dependencies {
17-
compile 'com.android.support:support-annotations:23.2.0'
18-
compile 'com.android.support:support-v4:23.2.0'
17+
compile 'com.android.support:support-annotations:23.3.0'
18+
compile 'com.android.support:support-v4:23.3.0'
1919
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.beardedhen.androidbootstrap;
2+
3+
/**
4+
* Any class marked with this annotation is subject to Major API changes which may cause client code
5+
* to break between releases. Use with caution!!!
6+
*/
7+
public @interface BetaApi {}

AndroidBootstrap/src/main/java/com/beardedhen/androidbootstrap/BootstrapAlert.java

Lines changed: 186 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,47 @@
2020
import com.beardedhen.androidbootstrap.api.attributes.BootstrapBrand;
2121
import com.beardedhen.androidbootstrap.api.defaults.DefaultBootstrapBrand;
2222
import com.beardedhen.androidbootstrap.utils.DimenUtils;
23+
import com.beardedhen.androidbootstrap.utils.ViewUtils;
2324

2425
import java.util.concurrent.atomic.AtomicInteger;
2526

26-
public class BootstrapAlert extends RelativeLayout {
27+
/**
28+
* See <a href="http://getbootstrap.com/components/#badges>http://getbootstrap.com/components/#alerts</a>
29+
*/
30+
@BetaApi
31+
public class BootstrapAlert extends RelativeLayout implements Animation.AnimationListener {
32+
33+
/**
34+
* Provides methods which receive callbacks in response to changes in the view visibility.
35+
*/
36+
public interface VisibilityChangeListener{
37+
38+
/**
39+
* Called when the alert is set to be dismissed with an animation.
40+
* @param alert the alert
41+
*/
42+
void onAlertDismissStarted(BootstrapAlert alert);
43+
44+
/**
45+
* Called when the alert is no longer visible.
46+
* @param alert the alert
47+
*/
48+
void onAlertDismissCompletion(BootstrapAlert alert);
49+
50+
/**
51+
* Called when the alert set to appear with an animation
52+
* @param alert the alert
53+
*/
54+
void onAlertAppearStarted(BootstrapAlert alert);
55+
56+
/**
57+
* Called when the alert is now visible.
58+
* @param alert the alert
59+
*/
60+
void onAlertAppearCompletion(BootstrapAlert alert);
61+
}
2762

2863
private ImageView closeButton;
29-
private TextView alertText;
3064

3165
private BootstrapBrand bootstrapBrand;
3266

@@ -39,10 +73,9 @@ public class BootstrapAlert extends RelativeLayout {
3973
private AlphaAnimation fadeInAnimation;
4074
private AlphaAnimation fadeOutAnimation;
4175

42-
private boolean dismissible;
43-
private boolean hidden;
76+
private boolean userDismissible;
4477

45-
private OnDismissListener onDismissListener;
78+
private VisibilityChangeListener visibilityChangeListener;
4679

4780
private static final AtomicInteger nextGeneratedId = new AtomicInteger(1);
4881

@@ -71,148 +104,221 @@ private void initialise(AttributeSet attrs) {
71104

72105
strongText = a.getString(R.styleable.BootstrapAlert_strongText);
73106
messageText = a.getString(R.styleable.BootstrapAlert_messageText);
74-
dismissible = a.getBoolean(R.styleable.BootstrapAlert_dismissible, false);
107+
userDismissible = a.getBoolean(R.styleable.BootstrapAlert_dismissible, false);
108+
75109
if (strongText == null) {
76110
strongText = "";
77111
}
78112
if (messageText == null) {
79113
messageText = "";
80114
}
81-
} finally {
115+
}
116+
finally {
82117
a.recycle();
83118
}
84119

85-
baselineFontSize = DimenUtils.pixelsFromSpResource(getContext(), R.dimen.bootstrap_button_default_font_size);
86-
baselinePadding = DimenUtils.pixelsFromDpResource(getContext(), R.dimen.bootstrap_alert_paddings);
87-
120+
baselineFontSize = DimenUtils.pixelsFromSpResource(getContext(),
121+
R.dimen.bootstrap_button_default_font_size);
122+
baselinePadding = DimenUtils.pixelsFromDpResource(getContext(),
123+
R.dimen.bootstrap_alert_paddings);
124+
setupAnimations();
88125
updateBootstrapState();
89126
}
90127

91128
private void updateBootstrapState() {
92-
alertText = new TextView(getContext());
129+
TextView alertText = new TextView(getContext());
93130
closeButton = new ImageView(getContext());
131+
94132
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
95133
alertText.setId(generateViewUniqueId());
96134
closeButton.setId(generateViewUniqueId());
97-
} else {
135+
}
136+
else {
98137
alertText.setId(View.generateViewId());
99138
closeButton.setId(View.generateViewId());
100139
}
101-
fadeInAnimation = new AlphaAnimation(0.0f, 1.0f);
102-
fadeInAnimation.setDuration(300);
103-
fadeInAnimation.setInterpolator(new AccelerateInterpolator());
104-
fadeOutAnimation = new AlphaAnimation(1.0f, 0.0f);
105-
fadeOutAnimation.setDuration(300);
106-
fadeOutAnimation.setInterpolator(new AccelerateInterpolator());
107140

108-
fadeInAnimation.setAnimationListener(new Animation.AnimationListener() {
109-
@Override public void onAnimationStart(Animation animation) {setVisibility(VISIBLE);}
110-
@Override public void onAnimationEnd(Animation animation) {}
111-
@Override public void onAnimationRepeat(Animation animation) {}
112-
});
113-
114-
fadeOutAnimation.setAnimationListener(new Animation.AnimationListener() {
115-
@Override public void onAnimationStart(Animation animation) {}
116-
@Override public void onAnimationEnd(Animation animation) {
117-
setVisibility(GONE);
118-
if (onDismissListener != null) onDismissListener.onDismiss();
119-
}
120-
@Override public void onAnimationRepeat(Animation animation) {}
121-
});
122141

123-
LayoutParams textParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
124-
LayoutParams closeParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
142+
LayoutParams textParams = new LayoutParams(LayoutParams.MATCH_PARENT,
143+
LayoutParams.WRAP_CONTENT);
144+
LayoutParams closeParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
145+
LayoutParams.WRAP_CONTENT);
125146
textParams.addRule(RelativeLayout.LEFT_OF, closeButton.getId());
126147
closeParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
127148

128149
alertText.setLayoutParams(textParams);
129150
alertText.setTextSize(baselineFontSize);
130-
alertText.setGravity(Gravity.LEFT);
131-
alertText.setTextColor(BootstrapDrawableFactory.bootstrapButtonText(
132-
getContext(),
133-
true,
134-
bootstrapBrand));
135-
alertText.setText(Html.fromHtml(String.format("<b>%s</b>%s", strongText, (strongText.length() > 0 ? "&nbsp;" + messageText : messageText))));
151+
alertText.setGravity(Gravity.START);
152+
alertText.setTextColor(
153+
BootstrapDrawableFactory.bootstrapButtonText(getContext(), true, bootstrapBrand));
154+
alertText.setText(Html.fromHtml(String.format("<b>%s</b>%s", strongText,
155+
(strongText.length() > 0 ?
156+
"&nbsp;" + messageText :
157+
messageText))));
136158

137159
closeButton.setLayoutParams(closeParams);
138-
closeButton.setBackgroundDrawable(BootstrapDrawableFactory.bootstrapAlertCloseIcon(
139-
getContext(),
140-
(int) baselineFontSize,
141-
(int) baselineFontSize,
142-
DimenUtils.dpToPixels(6)));
143-
144-
Drawable bg = BootstrapDrawableFactory.bootstrapAlert(
145-
getContext(),
146-
bootstrapBrand);
147-
148-
if (Build.VERSION.SDK_INT >= 16) {
149-
setBackground(bg);
150-
} else {
151-
setBackgroundDrawable(bg);
152-
}
160+
Drawable buttonBg = BootstrapDrawableFactory.bootstrapAlertCloseIcon(
161+
getContext(), (int) baselineFontSize, (int) baselineFontSize,
162+
DimenUtils.dpToPixels(6));
163+
164+
ViewUtils.setBackgroundDrawable(closeButton, buttonBg);
165+
166+
Drawable bg = BootstrapDrawableFactory.bootstrapAlert(getContext(), bootstrapBrand);
167+
ViewUtils.setBackgroundDrawable(this, bg);
168+
153169
addView(alertText);
154-
if (dismissible) {
170+
171+
if (userDismissible) {
155172
addView(closeButton);
156173
((View) closeButton.getParent()).post(new Runnable() {
157174
@Override
158175
public void run() {
159176
Rect bounds = new Rect();
160177
closeButton.getHitRect(bounds);
161-
bounds.top -= DimenUtils.dpToPixels(6);
178+
bounds.top -= DimenUtils.dpToPixels(6);
162179
bounds.bottom += DimenUtils.dpToPixels(6);
163-
bounds.left -= DimenUtils.dpToPixels(6);
164-
bounds.right += DimenUtils.dpToPixels(6);
180+
bounds.left -= DimenUtils.dpToPixels(6);
181+
bounds.right += DimenUtils.dpToPixels(6);
165182
TouchDelegate touchDelegate = new TouchDelegate(bounds, closeButton);
166183
if (View.class.isInstance(closeButton.getParent())) {
167184
((View) closeButton.getParent()).setTouchDelegate(touchDelegate);
168185
}
169186
}
170187
});
171-
closeButton.setOnClickListener(
172-
new OnClickListener() {
173-
@Override public void onClick(View v) {
174-
hide();
175-
}
176-
}
177-
);
188+
closeButton.setOnClickListener(new OnClickListener() {
189+
@Override
190+
public void onClick(View v) {
191+
dismiss(true);
192+
}
193+
});
178194
}
179195

180196
int vert = (int) (baselinePadding * 1.5);
181197
int hori = (int) (baselinePadding * 1.5);
182198
setPadding(hori, vert, hori, vert);
183199
}
184200

185-
public void hide() {
186-
hidden = true;
187-
startAnimation(fadeOutAnimation);
201+
private void setupAnimations() {
202+
fadeInAnimation = new AlphaAnimation(0.0f, 1.0f);
203+
fadeInAnimation.setDuration(300);
204+
fadeInAnimation.setInterpolator(new AccelerateInterpolator());
205+
fadeInAnimation.setAnimationListener(this);
206+
207+
fadeOutAnimation = new AlphaAnimation(1.0f, 0.0f);
208+
fadeOutAnimation.setDuration(300);
209+
fadeOutAnimation.setInterpolator(new AccelerateInterpolator());
210+
fadeOutAnimation.setAnimationListener(this);
211+
}
212+
213+
/**
214+
* Hides the alert with an animation, setting its visibility to {@link View#GONE}
215+
* @param animated whether the dismissal should be animated or not
216+
*/
217+
public void dismiss(boolean animated) {
218+
if (animated) {
219+
if (visibilityChangeListener != null) {
220+
visibilityChangeListener.onAlertDismissStarted(this);
221+
}
222+
startAnimation(fadeOutAnimation);
223+
}
224+
else {
225+
setVisibility(GONE);
226+
}
188227
}
189228

190-
public void show() {
191-
hidden = false;
192-
startAnimation(fadeInAnimation);
229+
/**
230+
* Shows the alert with an animation, setting its visibility to {@link View#VISIBLE}
231+
* @param animated whether the appearance should be animated or not
232+
*/
233+
public void show(boolean animated) {
234+
if (animated) {
235+
if (visibilityChangeListener != null) {
236+
visibilityChangeListener.onAlertAppearStarted(this);
237+
}
238+
startAnimation(fadeInAnimation);
239+
}
240+
else {
241+
setVisibility(VISIBLE);
242+
}
193243
}
194244

195-
public boolean isHidden() {
196-
return hidden;
245+
/**
246+
* Retrieves whether the user can dismiss the dialog or not
247+
* @return true if dismissable
248+
*/
249+
public boolean isUserDismissible() {
250+
return userDismissible;
197251
}
198252

199-
public void setOnDismissListener(OnDismissListener onDismissListener) {
200-
this.onDismissListener = onDismissListener;
253+
/**
254+
* Sets whether the user can dismiss the dialog or not.
255+
* @param userDismissible true if dismissable
256+
*/
257+
public void setUserDismissible(boolean userDismissible) {
258+
this.userDismissible = userDismissible;
259+
updateBootstrapState();
260+
}
261+
262+
/**
263+
* Sets a {@link VisibilityChangeListener} that will be notified on changes
264+
*
265+
* @param visibilityChangeListener the listener
266+
*/
267+
public void setVisibilityChangeListener(VisibilityChangeListener visibilityChangeListener) {
268+
this.visibilityChangeListener = visibilityChangeListener;
201269
}
202270

203271
private int generateViewUniqueId() {
204-
for (;;) {
272+
for (; ; ) {
205273
final int result = nextGeneratedId.get();
206274
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
207275
int newValue = result + 1;
208-
if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
276+
if (newValue > 0x00FFFFFF) {
277+
newValue = 1; // Roll over to 1, not 0.
278+
}
209279
if (nextGeneratedId.compareAndSet(result, newValue)) {
210280
return result;
211281
}
212282
}
213283
}
214284

215-
public interface OnDismissListener {
216-
void onDismiss();
285+
@Override
286+
public void setVisibility(int visibility) {
287+
super.setVisibility(visibility);
288+
289+
if (visibilityChangeListener != null) {
290+
if (GONE == visibility) {
291+
visibilityChangeListener.onAlertDismissCompletion(this);
292+
}
293+
else if (VISIBLE == visibility) {
294+
visibilityChangeListener.onAlertAppearCompletion(this);
295+
}
296+
}
297+
}
298+
299+
// Animation change listener
300+
301+
@Override
302+
public void onAnimationStart(Animation animation) {
303+
304+
}
305+
306+
@Override
307+
public void onAnimationEnd(Animation animation) {
308+
309+
if (animation == fadeInAnimation) {
310+
setVisibility(VISIBLE);
311+
}
312+
else if (animation == fadeOutAnimation) {
313+
setVisibility(GONE);
314+
}
315+
else {
316+
throw new IllegalStateException("Unsupported animation attempted to use this listener");
317+
}
318+
}
319+
320+
@Override
321+
public void onAnimationRepeat(Animation animation) {
322+
217323
}
218324
}

0 commit comments

Comments
 (0)