The below code is working fine 2.3.6(test on device and emulator).
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.exit_menu, menu);
setMenuBackground();
return true;
}
protected void setMenuBackground()
{
getLayoutInflater().setFactory(new Factory() {
@Override
public View onCreateView(final String name, final Context context,
final AttributeSet attrs) {
if (name.equalsIgnoreCase("com.android.internal.view.menu.IconMenuItemView")) {
try { // Ask our inflater to create the view
final LayoutInflater f = getLayoutInflater();
final View[] view = new View[1];
try {
view[0] = f.createView(name, null, attrs);
} catch (InflateException e) {
hackAndroid23(name, attrs, f, view);
}
// Kind of apply our own background
new Handler().post(new Runnable() {
public void run() {
view[0].setBackgroundColor(Color.BLUE);
/*
* view[0].getBackground().setColorFilter(
* Color.parseColor("#292821"),
* PorterDuff.Mode.DARKEN);
*/
}
});
return view[0];
} catch (InflateException e) {
} catch (ClassNotFoundException e) {
}
}
return null;
}
});
}
static void hackAndroid23(final String name,
final android.util.AttributeSet attrs, final LayoutInflater f,
final View[] view) {
try {
f.inflate(new XmlPullParser() {
@Override
public int next() throws XmlPullParserException, IOException {
try {
view[0] = (TextView) f.createView(name, null, attrs);
} catch (InflateException e) {
} catch (ClassNotFoundException e) {
}
throw new XmlPullParserException("exit");
}
@Override
public void defineEntityReplacementText(String entityName,
String replacementText)
throws XmlPullParserException {
// TODO Auto-generated method stub
}
@Override
public int getAttributeCount() {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getAttributeName(int index) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getAttributeNamespace(int index) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getAttributePrefix(int index) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getAttributeType(int index) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getAttributeValue(int index) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getAttributeValue(String namespace,
String name) {
// TODO Auto-generated method stub
return null;
}
@Override
public int getColumnNumber() {
// TODO Auto-generated method stub
return 0;
}
@Override
public int getDepth() {
// TODO Auto-generated method stub
return 0;
}
@Override
public int getEventType() throws XmlPullParserException {
// TODO Auto-generated method stub
return 0;
}
@Override
public boolean getFeature(String name) {
// TODO Auto-generated method stub
return false;
}
@Override
public String getInputEncoding() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getLineNumber() {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getNamespace() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getNamespace(String prefix) {
// TODO Auto-generated method stub
return null;
}
@Override
public int getNamespaceCount(int depth)
throws XmlPullParserException {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getNamespacePrefix(int pos)
throws XmlPullParserException {
// TODO Auto-generated method stub
return null;
}
@Override
public String getNamespaceUri(int pos)
throws XmlPullParserException {
// TODO Auto-generated method stub
return null;
}
@Override
public String getPositionDescription() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getPrefix() {
// TODO Auto-generated method stub
return null;
}
@Override
public Object getProperty(String name) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getText() {
// TODO Auto-generated method stub
return null;
}
@Override
public char[] getTextCharacters(
int[] holderForStartAndLength) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isAttributeDefault(int index) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isEmptyElementTag()
throws XmlPullParserException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isWhitespace() throws XmlPullParserException {
// TODO Auto-generated method stub
return false;
}
@Override
public int nextTag() throws XmlPullParserException,
IOException {
// TODO Auto-generated method stub
return 0;
}
@Override
public String nextText() throws XmlPullParserException,
IOException {
// TODO Auto-generated method stub
return null;
}
@Override
public int nextToken() throws XmlPullParserException,
IOException {
// TODO Auto-generated method stub
return 0;
}
@Override
public void require(int type, String namespace, String name)
throws XmlPullParserException, IOException {
// TODO Auto-generated method stub
}
@Override
public void setFeature(String name, boolean state)
throws XmlPullParserException {
// TODO Auto-generated method stub
}
@Override
public void setInput(Reader in)
throws XmlPullParserException {
// TODO Auto-generated method stub
}
@Override
public void setInput(InputStream inputStream,
String inputEncoding) throws XmlPullParserException {
// TODO Auto-generated method stub
}
@Override
public void setProperty(String name, Object value)
throws XmlPullParserException {
// TODO Auto-generated method stub
}
}, null, false);
} catch (InflateException e1) {
// "exit" ignored
}
}
OR --> Do following:
I have used the code as shown below on 2.3.1 version and it works and just call in onCreat method addOptionsMenuHackerInflaterFactory();
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.exit_menu, menu);
setMenuBackground();
return true;
}
protected void setMenuBackground()
{
getLayoutInflater().setFactory(new Factory() {
@Override
public View onCreateView(final String name, final Context context,
final AttributeSet attrs) {
if (name.equalsIgnoreCase("com.android.internal.view.menu.IconMenuItemView")) {
try { // Ask our inflater to create the view
final LayoutInflater f = getLayoutInflater();
final View[] view = new View[1];
try {
view[0] = f.createView(name, null, attrs);
} catch (InflateException e) {
hackAndroid23(name, attrs, f, view);
}
// Kind of apply our own background
new Handler().post(new Runnable() {
public void run() {
view[0].setBackgroundColor(Color.BLUE);
/*
* view[0].getBackground().setColorFilter(
* Color.parseColor("#292821"),
* PorterDuff.Mode.DARKEN);
*/
}
});
return view[0];
} catch (InflateException e) {
} catch (ClassNotFoundException e) {
}
}
return null;
}
});
}
static void hackAndroid23(final String name,
final android.util.AttributeSet attrs, final LayoutInflater f,
final View[] view) {
try {
f.inflate(new XmlPullParser() {
@Override
public int next() throws XmlPullParserException, IOException {
try {
view[0] = (TextView) f.createView(name, null, attrs);
} catch (InflateException e) {
} catch (ClassNotFoundException e) {
}
throw new XmlPullParserException("exit");
}
@Override
public void defineEntityReplacementText(String entityName,
String replacementText)
throws XmlPullParserException {
// TODO Auto-generated method stub
}
@Override
public int getAttributeCount() {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getAttributeName(int index) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getAttributeNamespace(int index) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getAttributePrefix(int index) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getAttributeType(int index) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getAttributeValue(int index) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getAttributeValue(String namespace,
String name) {
// TODO Auto-generated method stub
return null;
}
@Override
public int getColumnNumber() {
// TODO Auto-generated method stub
return 0;
}
@Override
public int getDepth() {
// TODO Auto-generated method stub
return 0;
}
@Override
public int getEventType() throws XmlPullParserException {
// TODO Auto-generated method stub
return 0;
}
@Override
public boolean getFeature(String name) {
// TODO Auto-generated method stub
return false;
}
@Override
public String getInputEncoding() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getLineNumber() {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getNamespace() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getNamespace(String prefix) {
// TODO Auto-generated method stub
return null;
}
@Override
public int getNamespaceCount(int depth)
throws XmlPullParserException {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getNamespacePrefix(int pos)
throws XmlPullParserException {
// TODO Auto-generated method stub
return null;
}
@Override
public String getNamespaceUri(int pos)
throws XmlPullParserException {
// TODO Auto-generated method stub
return null;
}
@Override
public String getPositionDescription() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getPrefix() {
// TODO Auto-generated method stub
return null;
}
@Override
public Object getProperty(String name) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getText() {
// TODO Auto-generated method stub
return null;
}
@Override
public char[] getTextCharacters(
int[] holderForStartAndLength) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isAttributeDefault(int index) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isEmptyElementTag()
throws XmlPullParserException {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isWhitespace() throws XmlPullParserException {
// TODO Auto-generated method stub
return false;
}
@Override
public int nextTag() throws XmlPullParserException,
IOException {
// TODO Auto-generated method stub
return 0;
}
@Override
public String nextText() throws XmlPullParserException,
IOException {
// TODO Auto-generated method stub
return null;
}
@Override
public int nextToken() throws XmlPullParserException,
IOException {
// TODO Auto-generated method stub
return 0;
}
@Override
public void require(int type, String namespace, String name)
throws XmlPullParserException, IOException {
// TODO Auto-generated method stub
}
@Override
public void setFeature(String name, boolean state)
throws XmlPullParserException {
// TODO Auto-generated method stub
}
@Override
public void setInput(Reader in)
throws XmlPullParserException {
// TODO Auto-generated method stub
}
@Override
public void setInput(InputStream inputStream,
String inputEncoding) throws XmlPullParserException {
// TODO Auto-generated method stub
}
@Override
public void setProperty(String name, Object value)
throws XmlPullParserException {
// TODO Auto-generated method stub
}
}, null, false);
} catch (InflateException e1) {
// "exit" ignored
}
}
OR --> Do following:
I have used the code as shown below on 2.3.1 version and it works and just call in onCreat method addOptionsMenuHackerInflaterFactory();
private static final int COLOR_MENU_ID = Menu.FIRST;
private static final int EMBOSS_MENU_ID = Menu.FIRST + 1;
private static final int BLUR_MENU_ID = Menu.FIRST + 2;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(0, COLOR_MENU_ID, 0, "Color").setShortcut('3', 'c');
menu.add(0, EMBOSS_MENU_ID, 0, "Emboss").setShortcut('4', 's');
menu.add(0, BLUR_MENU_ID, 0, "Blur").setShortcut('5', 'z');
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
@SuppressWarnings("rawtypes")
static Class IconMenuItemView_class = null;
@SuppressWarnings("rawtypes")
static Constructor IconMenuItemView_constructor = null;
// standard signature of constructor expected by inflater of all View classes
@SuppressWarnings("rawtypes")
private static final Class[] standard_inflater_constructor_signature =
new Class[] { Context.class, AttributeSet.class };
protected void addOptionsMenuHackerInflaterFactory()
{
final LayoutInflater infl = getLayoutInflater();
infl.setFactory(new Factory()
{
public View onCreateView(final String name,
final Context context,
final AttributeSet attrs)
{
if (!name.equalsIgnoreCase("com.android.internal.view.menu.IconMenuItemView"))
return null; // use normal inflater
View view = null;
// "com.android.internal.view.menu.IconMenuItemView"
// - is the name of an internal Java class
// - that exists in Android <= 3.2 and possibly beyond
// - that may or may not exist in other Android revs
// - is the class whose instance we want to modify to set background etc.
// - is the class we want to instantiate with the standard constructor:
// IconMenuItemView(context, attrs)
// - this is what the LayoutInflater does if we return null
// - unfortunately we cannot just call:
// infl.createView(name, null, attrs);
// here because on Android 3.2 (and possibly later):
// 1. createView() can only be called inside inflate(),
// because inflate() sets the context parameter ultimately
// passed to the IconMenuItemView constructor's first arg,
// storing it in a LayoutInflater instance variable.
// 2. we are inside inflate(),
// 3. BUT from a different instance of LayoutInflater (not infl)
// 4. there is no way to get access to the actual instance being used
// - so we must do what createView() would have done for us
//
if (IconMenuItemView_class == null)
{
try
{
IconMenuItemView_class = getClassLoader().loadClass(name);
}
catch (ClassNotFoundException e)
{
// this OS does not have IconMenuItemView - fail gracefully
return null; // hack failed: use normal inflater
}
}
if (IconMenuItemView_class == null)
return null; // hack failed: use normal inflater
if (IconMenuItemView_constructor == null)
{
try
{
IconMenuItemView_constructor =
IconMenuItemView_class.getConstructor(standard_inflater_constructor_signature);
}
catch (SecurityException e)
{
return null; // hack failed: use normal inflater
}
catch (NoSuchMethodException e)
{
return null; // hack failed: use normal inflater
}
}
if (IconMenuItemView_constructor == null)
return null; // hack failed: use normal inflater
try
{
Object[] args = new Object[] { context, attrs };
view = (View)(IconMenuItemView_constructor.newInstance(args));
}
catch (IllegalArgumentException e)
{
return null; // hack failed: use normal inflater
}
catch (InstantiationException e)
{
return null; // hack failed: use normal inflater
}
catch (IllegalAccessException e)
{
return null; // hack failed: use normal inflater
}
catch (InvocationTargetException e)
{
return null; // hack failed: use normal inflater
}
if (null == view) // in theory handled above, but be safe...
return null; // hack failed: use normal inflater
// apply our own View settings after we get back to runloop
// - android will overwrite almost any setting we make now
final View v = view;
new Handler().post(new Runnable()
{
public void run()
{
v.setBackgroundColor(Color.BLUE);
try
{
// in Android <= 3.2, IconMenuItemView implemented with TextView
// guard against possible future change in implementation
TextView tv = (TextView)v;
tv.setTextColor(Color.RED);
}
catch (ClassCastException e)
{
// hack failed: do not set TextView attributes
}
}
});
return view;
}
});
}
Comments
Post a Comment