diff --git a/library/src/com/devspark/appmsg/AppMsg.java b/library/src/com/devspark/appmsg/AppMsg.java
index 5a8ceff..e862737 100644
--- a/library/src/com/devspark/appmsg/AppMsg.java
+++ b/library/src/com/devspark/appmsg/AppMsg.java
@@ -21,6 +21,7 @@
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
@@ -64,6 +65,27 @@ public class AppMsg {
*/
public static final int LENGTH_STICKY = -1;
+ /**
+ * Lowest priority, messages with this priority will be showed after all messages with priority
+ * {@link #PRIORITY_HIGH} and {@link #PRIORITY_NORMAL} have been shown.
+ *
+ * @see #setPriority(int)
+ */
+ public static final int PRIORITY_LOW = Integer.MIN_VALUE;
+ /**
+ * Normal priority, messages with this priority will be showed after all messages with priority
+ * {@link #PRIORITY_HIGH} but before {@link #PRIORITY_LOW} have been shown.
+ *
+ * @see #setPriority(int)
+ */
+ public static final int PRIORITY_NORMAL = 0;
+ /**
+ * Highest priority, messages with this priority will be showed before any other message.
+ *
+ * @see #setPriority(int)
+ */
+ public static final int PRIORITY_HIGH = Integer.MAX_VALUE;
+
/**
* Show the text notification for a long period of time with a negative style.
*/
@@ -82,9 +104,11 @@ public class AppMsg {
private final Activity mActivity;
private int mDuration = LENGTH_SHORT;
private View mView;
+ private ViewGroup mParent;
private LayoutParams mLayoutParams;
private boolean mFloating;
Animation mInAnimation, mOutAnimation;
+ int mPriority = PRIORITY_NORMAL;
/**
* Construct an empty AppMsg object. You must call {@link #setView} before
@@ -448,6 +472,70 @@ public AppMsg setAnimation(Animation inAnimation, Animation outAnimation) {
return this;
}
+ /**
+ * @return
+ * Current priority
+ *
+ * @see #PRIORITY_HIGH
+ * @see #PRIORITY_NORMAL
+ * @see #PRIORITY_LOW
+ */
+ public int getPriority() {
+ return mPriority;
+ }
+
+ /**
+ *
Set priority for this message
+ *
Note: This only affects the order in which the messages get shown,
+ * not the stacking order of the views.
+ *
+ *
Example: In the queue there are 3 messages [A, B, C],
+ * all of them with priority {@link #PRIORITY_NORMAL}, currently message A is being shown
+ * so we add a new message D with priority {@link #PRIORITY_HIGH}, after A goes away, given that
+ * D has a higher priority than B an the reset, D will be shown, then once that D is gone,
+ * B will be shown, and then finally C.
+ *
+ * @param priority
+ * A value indicating priority, although you can use any integer value, usage of already
+ * defined is highly encouraged.
+ *
+ * @see #PRIORITY_HIGH
+ * @see #PRIORITY_NORMAL
+ * @see #PRIORITY_LOW
+ */
+ public void setPriority(int priority) {
+ mPriority = priority;
+ }
+
+ /**
+ * @return
+ * Provided parent to add {@link #getView()} to using {@link #getLayoutParams()}.
+ */
+ public ViewGroup getParent() {
+ return mParent;
+ }
+
+ /**
+ * Provide a different parent than Activity decor view
+ * @param parent
+ * Provided parent to add {@link #getView()} to using {@link #getLayoutParams()}.
+ *
+ */
+ public void setParent(ViewGroup parent) {
+ mParent = parent;
+ }
+
+ /**
+ * Provide a different parent than Activity decor view
+ *
+ * @param parentId
+ * Provided parent id to add {@link #getView()} to using {@link #getLayoutParams()}.
+ *
+ */
+ public void setParent(int parentId) {
+ setParent((ViewGroup) mActivity.findViewById(parentId));
+ }
+
/**
* The style for a {@link AppMsg}.
*
diff --git a/library/src/com/devspark/appmsg/MsgManager.java b/library/src/com/devspark/appmsg/MsgManager.java
index 1a12916..9626485 100644
--- a/library/src/com/devspark/appmsg/MsgManager.java
+++ b/library/src/com/devspark/appmsg/MsgManager.java
@@ -29,9 +29,11 @@
import java.lang.ref.WeakReference;
import java.util.Collection;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
+import java.util.PriorityQueue;
import java.util.Queue;
import java.util.WeakHashMap;
@@ -43,7 +45,7 @@
/**
* @author Evgeny Shishkin
*/
-class MsgManager extends Handler {
+class MsgManager extends Handler implements Comparator {
private static final int MESSAGE_DISPLAY = 0xc2007;
private static final int MESSAGE_ADD_VIEW = 0xc20074dd;
@@ -53,10 +55,10 @@ class MsgManager extends Handler {
private static ReleaseCallbacks sReleaseCallbacks;
private final Queue msgQueue;
- private Queue stickyQueue;
+ private final Queue stickyQueue;
private MsgManager() {
- msgQueue = new LinkedList();
+ msgQueue = new PriorityQueue(1, this);
stickyQueue = new LinkedList();
}
@@ -216,10 +218,14 @@ private void removeMsg(final AppMsg appMsg) {
private void addMsgToView(AppMsg appMsg) {
View view = appMsg.getView();
- if (view.getParent() == null) {
- appMsg.getActivity().addContentView(
- view,
- appMsg.getLayoutParams());
+ if (view.getParent() == null) { // Not added yet
+ final ViewGroup targetParent = appMsg.getParent();
+ final ViewGroup.LayoutParams params = appMsg.getLayoutParams();
+ if (targetParent != null) {
+ targetParent.addView(view, params);
+ } else {
+ appMsg.getActivity().addContentView(view, params);
+ }
}
view.clearAnimation();
view.startAnimation(appMsg.mInAnimation);
@@ -258,6 +264,15 @@ public void handleMessage(Message msg) {
}
}
+ @Override
+ public int compare(AppMsg lhs, AppMsg rhs) {
+ return inverseCompareInt(lhs.mPriority, rhs.mPriority);
+ }
+
+ static int inverseCompareInt(int lhs, int rhs) {
+ return lhs < rhs ? 1 : (lhs == rhs ? 0 : -1);
+ }
+
private static class OutAnimationListener implements Animation.AnimationListener {
private final AppMsg appMsg;
diff --git a/sample/AndroidManifest.xml b/sample/AndroidManifest.xml
index 9233577..e14c182 100644
--- a/sample/AndroidManifest.xml
+++ b/sample/AndroidManifest.xml
@@ -11,7 +11,7 @@
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.Sherlock.Light.DarkActionBar">
-
+
diff --git a/sample/res/layout/activity_main.xml b/sample/res/layout/activity_main.xml
index 39a3730..92c0a16 100644
--- a/sample/res/layout/activity_main.xml
+++ b/sample/res/layout/activity_main.xml
@@ -5,58 +5,86 @@
android:fillViewport="true">
-
+
+
+
+ android:minHeight="48dp"
+ android:spinnerMode="dropdown"
+ android:entries="@array/priorities"
+ android:prompt="@string/priority"
+ />
-
+ android:text="@string/bottom" />
-
+ android:minHeight="48dp"
+ android:orientation="vertical" />
-
+ android:text="@string/custom_parent" />
-
+ android:hint="@string/your_message_here"
+ />
-
+ android:onClick="buttonClick"
+ android:text="@string/show_appmsg" />
diff --git a/sample/res/values/arrays.xml b/sample/res/values/arrays.xml
new file mode 100644
index 0000000..b519eef
--- /dev/null
+++ b/sample/res/values/arrays.xml
@@ -0,0 +1,16 @@
+
+
+
+ @string/alert
+ @string/confirm
+ @string/info
+ @string/custom
+ @string/sticky
+
+
+
+ @string/high
+ @string/normal
+ @string/low
+
+
\ No newline at end of file
diff --git a/sample/res/values/strings.xml b/sample/res/values/strings.xml
index 7dcacae..13defd8 100644
--- a/sample/res/values/strings.xml
+++ b/sample/res/values/strings.xml
@@ -9,5 +9,13 @@
Show at bottom of screenRemoveCancel All
+ High
+ Normal
+ Low
+ Show AppMsg!
+ Style
+ Priority
+ Your message here
+ Custom parent
\ No newline at end of file
diff --git a/sample/src/com/devspark/appmsg/sample/MainActivity.java b/sample/src/com/devspark/appmsg/sample/MainActivity.java
index bb918fe..71722f2 100644
--- a/sample/src/com/devspark/appmsg/sample/MainActivity.java
+++ b/sample/src/com/devspark/appmsg/sample/MainActivity.java
@@ -16,17 +16,26 @@
package com.devspark.appmsg.sample;
+import android.animation.LayoutTransition;
+import android.annotation.TargetApi;
import android.os.Bundle;
import android.view.View;
-import android.widget.Button;
+import android.view.ViewGroup;
import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.EditText;
+import android.widget.Spinner;
import com.actionbarsherlock.app.SherlockActivity;
import com.devspark.appmsg.AppMsg;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
+import static android.os.Build.VERSION_CODES.JELLY_BEAN;
+import static android.text.TextUtils.isEmpty;
import static android.view.Gravity.BOTTOM;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
import static com.devspark.appmsg.AppMsg.LENGTH_SHORT;
import static com.devspark.appmsg.AppMsg.LENGTH_STICKY;
@@ -37,12 +46,48 @@
*
*/
public class MainActivity extends SherlockActivity {
- private int mStickyCount;
+ private static final int NORMAL_POSITION = 1;
+ private static final int INFO_POSITION = 2;
+
+ private int mMsgCount;
+ private Spinner mStyle;
+ private Spinner mPriority;
+ private EditText mProvidedMsg;
+ private CheckBox mBottom;
+ private CheckBox mParent;
+ private ViewGroup mAltParent;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
+
+ mProvidedMsg = (EditText) findViewById(R.id.provided_txt);
+ mStyle = (Spinner) findViewById(R.id.style_spnr);
+ mStyle.setSelection(INFO_POSITION);
+ mPriority = (Spinner) findViewById(R.id.priority_spnr);
+ mPriority.setSelection(NORMAL_POSITION);
+ mBottom = (CheckBox) findViewById(R.id.bottom);
+ mParent = (CheckBox) findViewById(R.id.parent_chk);
+ mAltParent = (ViewGroup) findViewById(R.id.alt_parent);
+
+ mParent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ mAltParent.setVisibility(isChecked ? VISIBLE : GONE);
+ mBottom.setVisibility(isChecked ? GONE : VISIBLE);
+ }
+ });
+
+ if (SDK_INT >= JELLY_BEAN) {
+ enableChangingTransition();
+ }
+ }
+
+ @TargetApi(JELLY_BEAN)
+ private void enableChangingTransition() {
+ ViewGroup animatedRoot = (ViewGroup) findViewById(R.id.animated_root);
+ animatedRoot.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
}
/**
@@ -50,59 +95,92 @@ public void onCreate(Bundle savedInstanceState) {
*
* @param v
*/
- public void showAppMsg(View v) {
- final CharSequence msg = ((Button) v).getText();
+ public void buttonClick(View v) {
+ switch (v.getId()) {
+ case R.id.show:
+ showAppMsg();
+ break;
+ case R.id.cancel_all:
+ AppMsg.cancelAll(this);
+ break;
+ default:
+ return;
+ }
+ }
+
+ private void showAppMsg() {
+ mMsgCount++;
+ final int styleSelected = mStyle.getSelectedItemPosition();
+ final int priority = positionToPriority(mPriority.getSelectedItemPosition());
+ final CharSequence providedMsg = mProvidedMsg.getText();
+ final CharSequence msg = isEmpty(providedMsg)
+ ? new StringBuilder().append(mStyle.getSelectedItem())
+ .append(" ").append(mPriority.getSelectedItem())
+ .append(" msg#").append(mMsgCount).toString()
+ : providedMsg;
final AppMsg.Style style;
boolean customAnimations = false;
AppMsg provided = null;
- switch (v.getId()) {
- case R.id.alert:
+ switch (styleSelected) {
+ case 0:
style = AppMsg.STYLE_ALERT;
break;
- case R.id.confirm:
+ case 1:
style = AppMsg.STYLE_CONFIRM;
break;
- case R.id.info:
- style = AppMsg.STYLE_INFO;
- break;
- case R.id.custom:
+ case 3:
style = new AppMsg.Style(LENGTH_SHORT, R.color.custom);
customAnimations = true;
break;
- case R.id.sticky:
+ case 4:
style = new AppMsg.Style(LENGTH_STICKY, R.color.sticky);
- provided = AppMsg.makeText(this, msg + " #" + ++mStickyCount, style, R.layout.sticky);
+ provided = AppMsg.makeText(this, msg, style, R.layout.sticky);
provided.getView()
.findViewById(R.id.remove_btn)
.setOnClickListener(new CancelAppMsg(provided));
break;
- case R.id.cancel_all:
- AppMsg.cancelAll(this);
- return;
default:
- return;
+ style = AppMsg.STYLE_INFO;
+ break;
}
// create {@link AppMsg} with specify type
AppMsg appMsg = provided != null ? provided : AppMsg.makeText(this, msg, style);
- if (((CheckBox) (findViewById(R.id.bottom))).isChecked()) {
- appMsg.setLayoutGravity(BOTTOM);
+ appMsg.setPriority(priority);
+ if (mParent.isChecked()) {
+ appMsg.setParent(mAltParent);
+ } else {
+ if (mBottom.isChecked()) {
+ appMsg.setLayoutGravity(BOTTOM);
+ }
}
if (customAnimations) {
appMsg.setAnimation(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
}
appMsg.show();
+
+ }
+
+ private static int positionToPriority(int selectedItemPosition) {
+ switch (selectedItemPosition) {
+ case 0:
+ return AppMsg.PRIORITY_HIGH;
+ case 2:
+ return AppMsg.PRIORITY_LOW;
+ default:
+ return AppMsg.PRIORITY_NORMAL;
+ }
}
- @Override
- protected void onPause() {
- super.onPause();
- // This is optional for 14+,
- // also you may want to call it at your later convenience, e.g. onDestroy
- if (SDK_INT < ICE_CREAM_SANDWICH) {
- AppMsg.cancelAll(this);
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // This is optional for 14+,
+ // also you may want to call it at your later convenience, e.g. onDestroy
+ if (SDK_INT < ICE_CREAM_SANDWICH) {
+ AppMsg.cancelAll(this);
+ }
}
- }
static class CancelAppMsg implements View.OnClickListener {
private final AppMsg mAppMsg;