Instantly share code, notes, and snippets.

Embed
What would you like to do?
Android LayoutInflater.Factory to overwrite menu item style
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