LayoutInflater偷天换日,自定义属性巧解析
来源:互联网 发布:zbtc 数字图像 算法 编辑:程序博客网 时间:2024/06/05 13:34
近期有一个比较特殊的需求,就是给所有View上添加一个特殊属性,可以在XML中赋值(例如:tag = “https://static.byr.cn/files/imgupload/2011-07-22-00-24-26.jpg“),在View创建时根据属性做一些操作。如载入URL等。
这个需求有些限制:
1.因为希望是通用的架构,各种View如ImageView、各种Layout、还有自定义View等都可以使用。
所以没法去继承某个单独的View。
2.尽量不修改现有的代码。对使用者透明。
问题最难的地方还是在于缺少一个合适的切入点来读取并且应用属性。后来使用了一些比较tricky的方式来解决这个问题:
1.已知LayoutInflater 中有一个onCreateView的方法。这个方法是public可以被复写,而且可以获取到读取xml获取到的各种属性值。因此,这是一个理想的切入点。
插一句话,虽然LayoutInflater 可以通过setFactory
之类的方式来定制View的生产,但是在这里并不合适,因为我们并不想去关注 View是如何构建出来的,只是希望在View被构建出来之后做一些额外工作。
因此希望可以替换掉系统的LayoutInfalter。
2.LayoutInflater的日常使用方式多为:
LayoutInfater.from(context)
或者Activit#getLayoutInflater
等,到最后的调用都会走到context.getSystemService(LAYOUT_INFLATER)
上来。
// LayoutInflater.javapublic static LayoutInflater from(Context context) { LayoutInflater LayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); if (LayoutInflater == null) { throw new AssertionError("LayoutInflater not found."); } return LayoutInflater; }
而系统中的“正牌”LayoutInflate是使用的PhoneLayoutInflater
//ContextImpl.java @Override public Object getSystemService(String name) { return SystemServiceRegistry.getSystemService(this, name); }
//SystemServiceRegistry registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class, new CachedServiceFetcher<LayoutInflater>() { @Override public LayoutInflater createService(ContextImpl ctx) { return new PhoneLayoutInflater(ctx.getOuterContext()); }});
我们在Activity中就可以通过重写getSystemService就可以替换成我们的LayoutInflater。
public class MainActivity extends Activity { LayoutInflater layoutInflater; @Override public Object getSystemService(String name) { if (name.equals(LAYOUT_INFLATER_SERVICE)) { if (layoutInflater == null) { LayoutInflater origin = (LayoutInflater) super.getSystemService(name); //使用这种 ni layoutInflater = new PPLayoutInflater(origin, this); } return layoutInflater; } return super.getSystemService(name); } @Override public LayoutInflater getLayoutInflater() { return layoutInflater; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }}
自定义InflaterLayout的实现
这个实现参考了PhoneLayoutInflater核心代码:
@Override protected View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException { Log.e("shitshit", "【" + this.getClass().getSimpleName() + "】 onCreateView() called with: " + "name = [" + name + "], attrs = [" + attrs + "]"); for (String prefix : sClassPrefixList) { try { // 使用默认构造方法 这一步不是我们所关心的 View view = createView(name, prefix, attrs); if (view != null) { //do custom here...先用ImageView来做个实验 if(view instanceof ImageView) { if (attrs != null) { for (int i = 0; i < attrs.getAttributeCount(); i++) { String attributeName = attrs.getAttributeName(i); String attributeValue = attrs.getAttributeValue(i); //拥有了View和其各种从xml中解析出来的属性 processAttrs(attributeName, attributeValue, view); } } } return view; } } catch (ClassNotFoundException e) { // In this case we want to let the base class take a crack // at it. } } return super.onCreateView(name, attrs); }
一个简单的processAttrs的栗子:
public void processAttrs(String attrName, String attrValue, View view){ if(attrName.equals("tag")){ view.setBackgroundColor(Color.parseColor(attrValue)); } }
本文完整代码已经上传至git
https://github.com/BFridge/CustomLayoutInflater
其实关于替换SystemService的类似的小tricky也有高人专门研究过:
https://github.com/square/mortar
- LayoutInflater偷天换日,自定义属性巧解析
- LayoutInflater解析
- LayoutInflater解析
- LayoutInflater解析
- LayoutInflater解析
- LayoutInflater 解析
- LayoutInflater解析
- Android自定义属性解析
- 自定义View 属性解析
- 解析自定义属性
- Android自定义View解析之LayoutInflater类(三)
- Android自定义属性:format解析
- Android自定义控件之自定义属性解析
- 自定义LayoutInflater.Factory
- LayoutInflater.inflate方法解析
- Android LayoutInflater深度解析
- Android LayoutInflater深度解析
- Android LayoutInflater深度解析
- 基于GDI+计算机图形程序设计
- 关于图片的工具类
- TIM_CtrlPWMOutputs()函数功能介绍
- javascript 点击事件执行两次js问题
- 其实和app无关的anr问题分析
- LayoutInflater偷天换日,自定义属性巧解析
- 震惊!Android 手机为什么没有 iPhone 安全,看完这篇你就知道了
- Linux守护进程
- leetcode226. Invert Binary Tree
- 2017.8.14--2017.8.25
- 以软硬一体化SaaS平台技术切入 奥付云瞄准的是所有自助设备的运营提升空间
- 排序算法——希尔排序
- 用pgrouting对openstreetmap数据进行路径分析
- 数据挖掘的主要技术