Created
August 22, 2014 23:21
-
-
Save slightfoot/d7fb255d6f4d3d43def8 to your computer and use it in GitHub Desktop.
Notification Action View
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]; | |
} | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<resources> | |
<string name="notifications">Show Notifications</string> | |
</resources> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
@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?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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