Android LayoutInflater.Factory to overwrite menu item style
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
package org.santamonica.module; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.Reader; | |
import java.lang.reflect.Method; | |
import org.santamonica.R; | |
import org.xmlpull.v1.XmlPullParser; | |
import org.xmlpull.v1.XmlPullParserException; | |
import android.content.Context; | |
import android.content.res.Resources; | |
import android.graphics.Typeface; | |
import android.graphics.PorterDuff.Mode; | |
import android.graphics.drawable.Drawable; | |
import android.os.Handler; | |
import android.util.AttributeSet; | |
import android.view.InflateException; | |
import android.view.LayoutInflater; | |
import android.view.Menu; | |
import android.view.MenuItem; | |
import android.view.LayoutInflater.Factory; | |
import android.view.View; | |
import android.view.ViewGroup.LayoutParams; | |
import android.widget.TextView; | |
public class ThemedMenuLayoutInflaterFactory implements Factory | |
{ | |
private static class FakeXmlPullParser implements XmlPullParser{ | |
private View mView; | |
private String mName; | |
private LayoutInflater mInflater; | |
private AttributeSet mAttrs; | |
public FakeXmlPullParser(String name, AttributeSet attrs, LayoutInflater inf){ | |
mName = name; | |
mAttrs = attrs; | |
mInflater = inf; | |
} | |
public View getView() | |
{ | |
return mView; | |
} | |
public int next() throws XmlPullParserException, IOException { | |
try { | |
mView = mInflater.createView( mName, null, mAttrs ); | |
} catch (Exception e) { | |
} | |
throw new XmlPullParserException("exit"); | |
} | |
public void defineEntityReplacementText(String entityName, | |
String replacementText) throws XmlPullParserException { | |
} | |
public int getAttributeCount() { | |
return 0; | |
} | |
public String getAttributeName(int index) { | |
return null; | |
} | |
public String getAttributeNamespace(int index) { | |
return null; | |
} | |
public String getAttributePrefix(int index) { | |
return null; | |
} | |
public String getAttributeType(int index) { | |
return null; | |
} | |
public String getAttributeValue(int index) { | |
return null; | |
} | |
public String getAttributeValue(String namespace, String name) { | |
return null; | |
} | |
public int getColumnNumber() { | |
return 0; | |
} | |
public int getDepth() { | |
return 0; | |
} | |
public int getEventType() throws XmlPullParserException { | |
return 0; | |
} | |
public boolean getFeature(String name) { | |
return false; | |
} | |
public String getInputEncoding() { | |
return null; | |
} | |
public int getLineNumber() { | |
return 0; | |
} | |
public String getName() { | |
return null; | |
} | |
public String getNamespace() { | |
return null; | |
} | |
public String getNamespace(String prefix) { | |
return null; | |
} | |
public int getNamespaceCount(int depth) throws XmlPullParserException { | |
return 0; | |
} | |
public String getNamespacePrefix(int pos) throws XmlPullParserException { | |
return null; | |
} | |
public String getNamespaceUri(int pos) throws XmlPullParserException { | |
return null; | |
} | |
public String getPositionDescription() { | |
return null; | |
} | |
public String getPrefix() { | |
return null; | |
} | |
public Object getProperty(String name) { | |
return null; | |
} | |
public String getText() { | |
return null; | |
} | |
public char[] getTextCharacters(int[] holderForStartAndLength) { | |
return null; | |
} | |
public boolean isAttributeDefault(int index) { | |
return false; | |
} | |
public boolean isEmptyElementTag() throws XmlPullParserException { | |
return false; | |
} | |
public boolean isWhitespace() throws XmlPullParserException { | |
return false; | |
} | |
public int nextTag() throws XmlPullParserException, IOException { | |
return 0; | |
} | |
public String nextText() throws XmlPullParserException, IOException { | |
return null; | |
} | |
public int nextToken() throws XmlPullParserException, IOException { | |
return 0; | |
} | |
public void require(int type, String namespace, String name) | |
throws XmlPullParserException, IOException { | |
} | |
public void setFeature(String name, boolean state) | |
throws XmlPullParserException { | |
} | |
public void setInput(Reader in) throws XmlPullParserException { | |
} | |
public void setInput(InputStream inputStream, String inputEncoding) | |
throws XmlPullParserException { | |
} | |
public void setProperty(String name, Object value) | |
throws XmlPullParserException { | |
} | |
} | |
private View inflateView(String name, AttributeSet attrs, LayoutInflater inflater) throws ClassNotFoundException { | |
try { | |
return inflater.createView( name, null, attrs ); | |
} catch (InflateException e) { | |
return hackAndroid23(name, attrs, inflater); | |
} | |
} | |
private View hackAndroid23(String name, AttributeSet attrs, LayoutInflater inflater){ | |
FakeXmlPullParser parser = new FakeXmlPullParser(name, attrs, inflater); | |
try { | |
inflater.inflate(parser, null); | |
} catch (Exception e1) { | |
// "exit" ignored | |
} | |
return parser.getView(); | |
} | |
public View onCreateView(String name, final Context context, AttributeSet attrs) { | |
String className = "com.android.internal.view.menu.IconMenuItemView" ; | |
if (!name.equalsIgnoreCase(className) ) { | |
return null; | |
} | |
try { | |
LayoutInflater inflater = LayoutInflater.from(context); | |
final View view = inflateView(name, attrs, inflater); | |
new Handler().post( new Runnable() { | |
public void run () { | |
fixMenuItemView(view, context); | |
} | |
} ); | |
return view; | |
}catch ( Exception e ) { | |
} | |
return null; | |
} | |
protected Drawable getMenuItemIcon(View view){ | |
try { | |
Class itemClass = Class.forName("com.android.internal.view.menu.IconMenuItemView"); | |
Class dataClass = Class.forName("com.android.internal.view.menu.MenuItemImpl"); | |
Method getData = itemClass.getDeclaredMethod("getItemData"); | |
Method getIcon = dataClass.getDeclaredMethod("getIcon"); | |
Object data = getData.invoke(view); | |
Object icon = getIcon.invoke(data); | |
if(icon instanceof Drawable){ | |
return (Drawable) icon; | |
} | |
} catch (Exception e) { | |
} | |
return null; | |
} | |
protected void fixMenuItemView(View view, Context context){ | |
Drawable icon = getMenuItemIcon(view); | |
if(icon != null){ | |
int color = context.getResources().getColor(R.color.themeColorExtraForeground); | |
icon.setColorFilter(color, Mode.MULTIPLY); | |
} | |
if(view instanceof TextView){ | |
TextView text = (TextView) view; | |
text.setTextAppearance(context, R.style.themeMenuItem); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment