欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android Style\Theme动态切换

程序员文章站 2022-04-20 16:37:55
...
若转载请注明出处!

本文的主题思想是:
1》设置activity的theme,这个好设置,可参考 http://blog.csdn.net/wsscy2004/article/details/7562909
2》设置xml里面组件的style,我的实现是通过:获取组件,然后遍历他们去设置style(其中style的内容查找比较麻烦,我是通过反射R.class和解析style.xml做到的,有些地方需要人为手动设置)

public static void onActivityCreateSetStyle(ViewGroup viewGroup) {
		Log.d(tag, "onActivityCreateSetStyle");
		if (mButtonStyle != 0) {
			List<Button> list = getWidgetButton(viewGroup);
			Log.d(tag, "onActivityCreateSetStyle button num == " + list.size());
			if (list != null && !list.isEmpty()) {
				String styleName = mApp.styles.get(mButtonStyle);// 得到样式name
				Log.d(tag, "onActivityCreateSetStyle styleName == " + styleName);
				StyleBean style = null;
				for (StyleBean item : mApp.styledata) {
					if (styleName.equals(item.getName())) {
						style = item;// 得到样式的具体内容
					}
				}
				List<String> methodNames = style.getMethodNames();
				List<Class> paramTypes = style.getTypeClasses();
				List<Object> values = style.getValues();
				for (Button button : list) {
					Log.d(tag, "method num == " + methodNames.size());
					for (int i = 0; i < methodNames.size(); i++) {
						Log.d(tag, "Button setMethod : " + methodNames.get(i));
						Method method = getClassMethod(Button.class,
								methodNames.get(i),
								new Class[] { paramTypes.get(i) });
						try {
							if ("setTextColor".equals(methodNames.get(i))) {
								method.invoke(
										button,
										context.getResources().getColor(
												Integer.parseInt(values.get(i)
														.toString())));
							} else if ("setTextSize".equals(methodNames.get(i))) {
								method.invoke(button, Float.parseFloat(values
										.get(i).toString()));
							}
						} catch (IllegalArgumentException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (IllegalAccessException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (InvocationTargetException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
			}
		}
	}


这是上面用到的StyleBean
import java.util.List;

/**
 * Style element bean
 * 
 * @author Administrator
 * 
 */
@SuppressWarnings("rawtypes")
public class StyleBean {
	private String name;
	/**
	 * the method name associated with the attribute
	 */
	private List<String> methodNames;
	/**
	 * the class associated with the attribute
	 */
	private List<Class> typeClasses;
	/**
	 * the value associated with the attribute
	 */
	private List<Object> values;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public List<String> getMethodNames() {
		return methodNames;
	}

	public void setMethodNames(List<String> methodNames) {
		this.methodNames = methodNames;
	}

	public List<Class> getTypeClasses() {
		return typeClasses;
	}

	public void setTypeClasses(List<Class> typeClasses) {
		this.typeClasses = typeClasses;
	}

	public List<Object> getValues() {
		return values;
	}

	public void setValues(List<Object> values) {
		this.values = values;
	}
}


###反射R.class、解析style.xml,把R和style中的信息整理到类中,解析xml用的是sax,在解析style.xml的时候,注意把对应的方法、方法的参数类型记录下来,因为后面要通过反射来操作,eg:
@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		// TODO Auto-generated method stub
		super.startElement(uri, localName, qName, attributes);
		buffer.delete(0, buffer.length());
		itemName.delete(0, itemName.length());
		if (localName.equals("style")) {
			style = new StyleBean();
			style.setName(attributes.getValue("name"));
			Log.d(tag, "style name == " + style.getName());
			methodNames = new ArrayList<String>();
			typeClasses = new ArrayList<Class>();
			values = new ArrayList<Object>();
		} else if (localName.equals("item")) {
			itemName.append(attributes.getValue("name"));
			Log.d(tag, "item name == " + attributes.getValue("name") + "   "
					+ itemName.toString());
			Log.d(tag, "" + itemName.toString().equals("android:textColor"));
			if (itemName.toString().equals("android:textColor")) {
				methodNames.add("setTextColor");// 手动设置
				typeClasses.add(int.class);
			} else if (itemName.toString().equals("android:textSize")) {
				methodNames.add("setTextSize");// 手动设置
				typeClasses.add(float.class);
			}
		}
	}
//.....只贴关键的部分其他的方法就省略了
@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		// TODO Auto-generated method stub
		super.endElement(uri, localName, qName);
		if (localName.equals("item")) {
			String value = buffer.toString();
			if (itemName.toString().equals("android:textColor")) {
				if (value.contains("@color/")) {
					RChildBean bean = getRChildBean("color");
					if (bean != null) {
						int color = getRValue(bean, value.substring(
								value.lastIndexOf("/") + 1, value.length()));
						Log.d(tag, "color == " + color);
						if (color != -1) {
							values.add(color);
						}
					}
					bean = null;
				}
			} else if (itemName.toString().equals("android:textSize")) {
				Log.d(tag, "size == " + value.substring(0, value.indexOf("sp")));
				values.add(value.substring(0, value.indexOf("sp")));
			}
		} else if (localName.equals("style")) {
			style.setMethodNames(methodNames);
			style.setTypeClasses(typeClasses);
			style.setValues(values);
			styles.add(style);
		}
	}

  private RChildBean getRChildBean(String name) {
		for (RChildBean item : app.rchildlist) {
			if (name.equals(item.getName())) {
				return item;
			}
		}
		return null;
	}

	private int getRValue(RChildBean child, String name) {
		if (child.getItems().containsKey(name)) {
			return child.getItems().get(name);
		}
		return -1;
	}


这是上面用到的RChildBean
import java.util.Map;

/**
 * R child class bean
 * 
 * @author Administrator
 */
public class RChildBean {

	/**
	 * R child name
	 */
	private String name;
	/**
	 * R child items
	 */
	private Map<String, Integer> items;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Map<String, Integer> getItems() {
		return items;
	}

	public void setItems(Map<String, Integer> items) {
		this.items = items;
	}
}