-
-
Save slightfoot/d7fb255d6f4d3d43def8 to your computer and use it in GitHub Desktop.
<?xml version="1.0" encoding="utf-8"?> | |
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> | |
<corners android:radius="2dp" /> | |
<stroke android:color="#ff222222" android:width="2dp" /> | |
<solid android:color="#ffff0000" /> | |
</shape> |
<?xml version="1.0" encoding="utf-8"?> | |
<com.dd.test.NotificationActionView | |
xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:tools="http://schemas.android.com/tools" | |
android:layout_width="wrap_content" | |
android:layout_height="match_parent" | |
android:clipToPadding="false" | |
> | |
<ImageView | |
android:id="@android:id/icon" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_centerInParent="true" | |
tools:ignore="ContentDescription" | |
/> | |
<TextView | |
android:id="@android:id/text1" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_alignRight="@android:id/icon" | |
android:layout_alignTop="@android:id/icon" | |
android:layout_marginRight="2dp" | |
android:layout_marginTop="2dp" | |
android:background="@drawable/drawable_notification" | |
android:includeFontPadding="false" | |
android:minWidth="22dp" | |
android:paddingBottom="2dp" | |
android:paddingLeft="2dp" | |
android:paddingRight="4dp" | |
android:paddingTop="2dp" | |
android:textColor="#FFFFFF" | |
android:textSize="12dp" | |
android:gravity="center" | |
tools:ignore="SpUsage" | |
/> | |
</com.dd.test.NotificationActionView> |
import android.app.Activity; | |
import android.content.BroadcastReceiver; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.content.IntentFilter; | |
import android.graphics.Rect; | |
import android.os.Parcel; | |
import android.os.Parcelable; | |
import android.support.v4.content.LocalBroadcastManager; | |
import android.util.AttributeSet; | |
import android.view.Gravity; | |
import android.view.MenuItem; | |
import android.view.View; | |
import android.widget.ImageView; | |
import android.widget.RelativeLayout; | |
import android.widget.TextView; | |
import android.widget.Toast; | |
public class NotificationActionView extends RelativeLayout | |
{ | |
private static final String ACTION_SET_ABS = NotificationActionView.class.getCanonicalName() + ".ACTION_SET_ABS"; | |
private static final String ACTION_SET_DELTA = NotificationActionView.class.getCanonicalName() + ".ACTION_SET_DELTA"; | |
private static final String EXTRA_COUNT = "extraCount"; | |
private ImageView mIcon; | |
private TextView mText; | |
private MenuItem mItemData; | |
private int mCount; | |
public NotificationActionView(Context context) | |
{ | |
this(context, null); | |
} | |
public NotificationActionView(Context context, AttributeSet attrs) | |
{ | |
this(context, attrs, android.R.attr.actionButtonStyle); | |
} | |
public NotificationActionView(Context context, AttributeSet attrs, int defStyle) | |
{ | |
super(context, attrs, defStyle); | |
} | |
@Override | |
protected void onFinishInflate() | |
{ | |
super.onFinishInflate(); | |
mIcon = (ImageView)findViewById(android.R.id.icon); | |
mText = (TextView)findViewById(android.R.id.text1); | |
mText.setVisibility(View.GONE); | |
} | |
public void setItemData(MenuItem itemData) | |
{ | |
mItemData = itemData; | |
if(mItemData != null){ | |
setId(itemData.getItemId()); | |
mIcon.setImageDrawable(itemData.getIcon()); | |
setContentDescription(itemData.getTitleCondensed()); | |
setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE); | |
setEnabled(itemData.isEnabled()); | |
setClickable(true); | |
setLongClickable(true); | |
} | |
} | |
public MenuItem getItemData() | |
{ | |
return mItemData; | |
} | |
public void setCount(int count) | |
{ | |
mCount = count; | |
mText.setText(mCount > 99 ? "99+" : String.valueOf(mCount)); | |
mText.setVisibility((mCount == 0) ? View.GONE : View.VISIBLE); | |
} | |
public int getCount() | |
{ | |
return mCount; | |
} | |
private static Intent createNotificationIntent(Context context, String action, int count) | |
{ | |
return new Intent(action) | |
.setPackage(context.getPackageName()) | |
.putExtra(EXTRA_COUNT, count); | |
} | |
public static void setCountAbs(Context context, int count) | |
{ | |
LocalBroadcastManager.getInstance(context) | |
.sendBroadcast(createNotificationIntent(context, ACTION_SET_ABS, count)); | |
} | |
public static void setCountDelta(Context context, int delta) | |
{ | |
LocalBroadcastManager.getInstance(context) | |
.sendBroadcast(createNotificationIntent(context, ACTION_SET_DELTA, delta)); | |
} | |
@Override | |
protected void onAttachedToWindow() | |
{ | |
super.onAttachedToWindow(); | |
IntentFilter filter = new IntentFilter(); | |
filter.addAction(ACTION_SET_ABS); | |
filter.addAction(ACTION_SET_DELTA); | |
LocalBroadcastManager.getInstance(getContext()) | |
.registerReceiver(mUpdateReceiver, filter); | |
} | |
private BroadcastReceiver mUpdateReceiver = new BroadcastReceiver() | |
{ | |
@Override | |
public void onReceive(Context context, Intent intent) | |
{ | |
int count = intent.getIntExtra(EXTRA_COUNT, 0); | |
if(ACTION_SET_ABS.equals(intent.getAction())){ | |
setCount(count); | |
} | |
else if(ACTION_SET_DELTA.equals(intent.getAction())){ | |
setCount(getCount() + count); | |
} | |
} | |
}; | |
@Override | |
protected void onDetachedFromWindow() | |
{ | |
super.onDetachedFromWindow(); | |
LocalBroadcastManager.getInstance(getContext()) | |
.unregisterReceiver(mUpdateReceiver); | |
} | |
@Override | |
public boolean performClick() | |
{ | |
boolean performed = super.performClick(); | |
if(mItemData != null && !performed){ | |
((Activity)getContext()).onOptionsItemSelected(mItemData); | |
performed = true; | |
} | |
return performed; | |
} | |
@Override | |
public boolean performLongClick() | |
{ | |
boolean performed = super.performLongClick(); | |
if(mItemData != null && !performed){ | |
final int[] screenPos = new int[2]; | |
final Rect displayFrame = new Rect(); | |
getLocationOnScreen(screenPos); | |
getWindowVisibleDisplayFrame(displayFrame); | |
final Context context = getContext(); | |
final int width = getWidth(); | |
final int height = getHeight(); | |
final int midy = screenPos[1] + height / 2; | |
final int screenWidth = context.getResources().getDisplayMetrics().widthPixels; | |
Toast cheatSheet = Toast.makeText(context, mItemData.getTitle(), Toast.LENGTH_SHORT); | |
if(midy < displayFrame.height()){ | |
// Show along the top; follow action buttons | |
cheatSheet.setGravity(Gravity.TOP | Gravity.RIGHT, screenWidth - screenPos[0] - width / 2, height); | |
} | |
else{ | |
// Show along the bottom center | |
cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height); | |
} | |
cheatSheet.show(); | |
performed = true; | |
} | |
return performed; | |
} | |
@Override | |
protected Parcelable onSaveInstanceState() | |
{ | |
SavedState ss = new SavedState(super.onSaveInstanceState()); | |
ss.count = getCount(); | |
return ss; | |
} | |
@Override | |
protected void onRestoreInstanceState(Parcelable state) | |
{ | |
SavedState ss = (SavedState)state; | |
super.onRestoreInstanceState(ss.getSuperState()); | |
setCount(ss.count); | |
} | |
static class SavedState extends BaseSavedState | |
{ | |
int count; | |
protected SavedState(Parcelable superState) | |
{ | |
super(superState); | |
} | |
protected SavedState(Parcel source) | |
{ | |
super(source); | |
count = source.readInt(); | |
} | |
@Override | |
public void writeToParcel(Parcel dest, int flags) | |
{ | |
super.writeToParcel(dest, flags); | |
dest.writeInt(count); | |
} | |
public static final Parcelable.Creator<SavedState> CREATOR = | |
new Parcelable.Creator<SavedState>() | |
{ | |
public SavedState createFromParcel(Parcel source) | |
{ | |
return new SavedState(source); | |
} | |
public SavedState[] newArray(int size) | |
{ | |
return new SavedState[size]; | |
} | |
}; | |
} | |
} |
<resources> | |
<string name="notifications">Show Notifications</string> | |
</resources> |
import android.view.Menu; | |
import android.view.MenuItem; | |
import android.support.v4.app.FragmentActivity; | |
public class TestActivity extends FragmentActivity | |
{ | |
@Override | |
public boolean onCreateOptionsMenu(Menu menu) | |
{ | |
getMenuInflater().inflate(R.menu.menu_notification, menu); | |
return super.onCreateOptionsMenu(menu); | |
} | |
@Override | |
public boolean onPrepareOptionsMenu(Menu menu) | |
{ | |
MenuItem itemData = menu.findItem(R.id.notifications); | |
((NotificationActionView)itemData.getActionView()).setItemData(itemData); | |
return super.onPrepareOptionsMenu(menu); | |
} | |
@Override | |
public boolean onOptionsItemSelected(MenuItem item) | |
{ | |
if(item.getItemId() == R.id.notifications){ | |
NotificationActionView.setCountDelta(this, 3); | |
return true; | |
} | |
return super.onOptionsItemSelected(item); | |
} | |
} |
Sir, Im getting error please see below
your help would be appreciated
01-08 06:41:48.738: E/AndroidRuntime(1982): FATAL EXCEPTION: main
01-08 06:41:48.738: E/AndroidRuntime(1982): java.lang.ClassCastException: android.view.ContextThemeWrapper cannot be cast to android.app.Activity
01-08 06:41:48.738: E/AndroidRuntime(1982): at com.example.cartcounter.NotificationActionView.performClick(NotificationActionView.java:135)
01-08 06:41:48.738: E/AndroidRuntime(1982): at android.view.View$PerformClick.run(View.java:16966)
01-08 06:41:48.738: E/AndroidRuntime(1982): at android.os.Handler.handleCallback(Handler.java:615)
01-08 06:41:48.738: E/AndroidRuntime(1982): at android.os.Handler.dispatchMessage(Handler.java:92)
01-08 06:41:48.738: E/AndroidRuntime(1982): at android.os.Looper.loop(Looper.java:137)
01-08 06:41:48.738: E/AndroidRuntime(1982): at android.app.ActivityThread.main(ActivityThread.java:4745)
01-08 06:41:48.738: E/AndroidRuntime(1982): at java.lang.reflect.Method.invokeNative(Native Method)
01-08 06:41:48.738: E/AndroidRuntime(1982): at java.lang.reflect.Method.invoke(Method.java:511)
01-08 06:41:48.738: E/AndroidRuntime(1982): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
01-08 06:41:48.738: E/AndroidRuntime(1982): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
01-08 06:41:48.738: E/AndroidRuntime(1982): at dalvik.system.NativeStart.main(Native Method)
//add this to the class
private static Activity scanForActivity(Context cont)
{
if (cont == null)
return null;
else if (cont instanceof Activity)
return (Activity)cont;
else if (cont instanceof ContextWrapper)
return scanForActivity(((ContextWrapper)cont).getBaseContext());
return null;
}
//change performClick to this
Activity activity = ActionViewCart.scanForActivity(getContext());
activity.onOptionsItemSelected(mItemData);
//((Activity)getContext()).onOptionsItemSelected(mItemData);
How can i to show Notification view when my activity is created and not when i select item Menu?
You should be able to simply replace this:
@OverRide
public boolean onPrepareOptionsMenu(Menu menu)
{
MenuItem itemData = menu.findItem(R.id.notifications);
NotificationActionView actionView = (NotificationActionView)itemData.getActionView();
actionView.setItemData(itemData);
actionView.setCount(10); // initial value
return super.onPrepareOptionsMenu(menu);
}
I've created a new repo with an updated project based on this gist. See https://github.com/slightfoot/android-notification-action-view
@slightfoot Just I'm trying this code, but in my code there are something curious: when i'm running my app on Nexus 5 Android Emulator, and on huawei P6 device too, it is perfect, but i run my app in a Samsung Galaxy device it doesn't appear the "NotificationView". It is so rare... do you know what is the problem?
How can we use a broadcast receiver in the manifest?
thx, it helps