平常设置或者获取一个View时,用的较多的是setContentView或LayoutInflater#inflate,setContentView内部也是通过调用LayoutInflater#inflate实现(具体调用在AppCompatViewInflater#setContentView(ind resId)中)。

通过LayoutInflater#inflate可以将xml布局文件解析为所需要的View,通过分析LayoutInflate#inflate源码,可以看到.xml布局文件在解析的过程中会调用LayoutInflater#rInflate,随后会通过调用LayoutInflater#createViewFromTag来创建View。这里推荐《遇见LayoutInflater&Factory》
下面一起看看View的创建过程LayoutInflate#createViewFormTag:

View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
boolean ignoreThemeAttr) {
if (name.equals("view")) {
name = attrs.getAttributeValue(null, "class");
}

// Apply a theme wrapper, if allowed and one is specified.
if (!ignoreThemeAttr) {
final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
final int themeResId = ta.getResourceId(0, 0);
if (themeResId != 0) {
context = new ContextThemeWrapper(context, themeResId);
}
ta.recycle();
}

if (name.equals(TAG_1995)) {
// Let's party like it's 1995!
return new BlinkLayout(context, attrs);
}

try {
View view;
if (mFactory2 != null) {
//根据attrs信息,通过mFactory2创建View
view = mFactory2.onCreateView(parent, name, context, attrs);
} else if (mFactory != null) {
//根据attrs信息,通过mFactory创建View
view = mFactory.onCreateView(name, context, attrs);
} else {
view = null;
}

if (view == null && mPrivateFactory != null) {
view = mPrivateFactory.onCreateView(parent, name, context, attrs);
}

if (view == null) {
final Object lastContext = mConstructorArgs[0];
mConstructorArgs[0] = context;
try {
if (-1 == name.indexOf('.')) {
//创建Android原生的View(android.view包下面的view)
view = onCreateView(parent, name, attrs);
} else {
//创建自定义View或者依赖包中的View(xml中声明的是全路径)
view = createView(name, null, attrs);
}
} finally {
mConstructorArgs[0] = lastContext;
}
}

return view;
} catch (InflateException e) {
throw e;

} catch (ClassNotFoundException e) {
final InflateException ie = new InflateException(attrs.getPositionDescription()
+ ": Error inflating class " + name, e);
ie.setStackTrace(EMPTY_STACK_TRACE);
throw ie;

} catch (Exception e) {
final InflateException ie = new InflateException(attrs.getPositionDescription()
+ ": Error inflating class " + name, e);
ie.setStackTrace(EMPTY_STACK_TRACE);
throw ie;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
从上述源码中可以看出View的创建过程中,会首先找Factory2#onCreateView和Factory#onCreateView进行创建,然后走默认的创建流程。所以,我们可以在此处创建自定义的Factory2或Factory,并将自定义的Factory2或Factory对象添加到LayoutInflater对象当中,来对View的创建进行干预,LayoutInflate也提供了相关的API供我们添加自己的ViewFactory。

例如:下面我们通过设置LayoutInflater的Factory来,将视图中的Button转换为TextView

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
LayoutInflater.from(this).setFactory(new LayoutInflater.Factory() {
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
for (int i = 0; i < attrs.getAttributeCount(); i ++){
String attrName = attrs.getAttributeName(i);
String attrValue = attrs.getAttributeValue(i);
Log.i(TAG, String.format("name = %s, attrName = %s, attrValue= %s", name, attrName, attrValue));
}
TextView textView = null;
if (name.equals("Button")){
textView = new TextView(context, attrs);
}

return textView;
}
});
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_theme_change);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
让后启动Activity后,视图中的Button都转化成了TextView,并且能看到输出:

name = Button, attrName = id, attrValue= @2131230758
name = Button, attrName = background, attrValue= @2131034152
name = Button, attrName = layout_width, attrValue= -2
name = Button, attrName = layout_height, attrValue= -2
name = Button, attrName = id, attrValue= @2131230757
name = Button, attrName = background, attrValue= @2131034150
name = Button, attrName = layout_width, attrValue= -2
name = Button, attrName = layout_height, attrValue= -2
1
2
3
4
5
6
7
8
获取任意一个apk压缩文件的Resource对象
上述过程已经提供了更改View类型以及属性的方式,下面我们见介绍如何获取一个apk压缩文件中的res资源。

我们通常通过Context#getSource()获取res目录下的资源,Context#getAssets()(想当于Context#getSource().getAssets())获取asset目录下的资源。所以要获取一个apk压缩文件的资源文件,创建对应该压缩文件的Resource实例,然后通过这个实例获取压缩文件中的资源信息。
比如,新创建的的Resource实例为mResource,则可以使用mResource.getColor(colorId),来获取实例内colorId所对应的颜色。

那么接下来的问题分为两步:
---------------------

认识setFactory的更多相关文章

  1. hibernate多对一单向关联

    关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...

  2. Google C++单元测试框架GoogleTest---GMock的CheatSheet文档

    CheatSheet文档中包含了GMock所有常用的东西,看了这个基本上就可以用它了,本文接上篇博文:Google C++单元测试框架GoogleTest---Google Mock简介--概念及基础 ...

  3. Android中使用GridView和ImageViewSwitcher实现电子相册简单功能

    我们在手机上查看相册时,首先看到的是网格状的图片展示界面,然后我们选择想要欣赏的照片点击进入,这样就可以全屏观看该照片,并且可以通过左右滑动来切换照片.如下图的显示效果: 首先我们先罗列一下本次实现所 ...

  4. Android中使用ImageViewSwitcher实现图片切换轮播导航效果

    前面写过了使用ViewFlipper和ViewPager实现屏幕中视图切换的效果(ViewPager未实现轮播)附链接: Android中使用ViewFlipper实现屏幕切换 Android中使用V ...

  5. Android 轮换控件

    首先是控件轮换 一.创建主布局 1.用到的控件是 TextSwitcher (文本轮换) 那么其他对应的也就是 ImageSwitcher (图片轮换) <LinearLayout xmlns: ...

  6. Android 中常见控件的介绍和使用

    1 TextView文本框 1.1 TextView类的结构 TextView 是用于显示字符串的组件,对于用户来说就是屏幕中一块用于显示文本的区域.TextView类的层次关系如下: java.la ...

  7. java安全管理器SecurityManager入门

    table { margin-left: 30px; width: 95%; border: 1px; border-collapse: collapse } img { border: 1px so ...

  8. Android什么时候进行View中Background的加载

    对大多数Android的开发者来说,最经常的操作莫过于对界面进行布局,View中背景图片的加载是最经常做的.但是我们很少关注这个过程,这篇文章主要解析view中背景图片加载的流程.了解view中背景图 ...

  9. Android动画例子。

    例子一: 补间动画效果,从右进,从左出. ImageSwitcher mImageSwitcher = new ImageSwitcher(this); mImageSwitcher.setFacto ...

随机推荐

  1. Vagrant 手册之 Vagrantfile - 配置版本

    原文地址 配置版本是 Vagrant 1.1+(引入了大量新功能和配置选项) 能够与 Vagrant 1.0.x Vagrantfiles 保持向后兼容的机制. 现在运行 vagrant init 时 ...

  2. SqlServer 高级查询

    高级查询在数据库中用得是最频繁的,也是应用最广泛的. Ø 基本常用查询 --select select * from student;   --all 查询所有 select all sex from ...

  3. Elasticsearch+Logstash+Kibana搭建日志平台

    1 ELK简介 ELK是Elasticsearch+Logstash+Kibana的简称 ElasticSearch是一个基于Lucene的分布式全文搜索引擎,提供 RESTful API进行数据读写 ...

  4. JavaScript实现的发布/订阅(Pub/Sub)模式

    JavaScript实现的发布/订阅(Pub/Sub)模式 时间 2016-05-02 18:47:58  GiantMing's blog 原文  http://giantming.net/java ...

  5. [Python3] 022 面向对象 第二弹

    目录 6. 面向对象的三大特性 6.1 封装 6.1.1 私有 private 6.1.2 受保护 protected 6.1.3 公开 public 6.2 继承 6.2.1 继承的概念与作用 6. ...

  6. 记录XorDDos木马清理步骤

    1.检查 查看定时任务文件发现有两个异常定时任务 [root@manage ~]# cat /etc/crontab # * * * * * user-name command to be execu ...

  7. 在没有iis的情况下,webApi自托管(转自momo314)

    第一步 新建一个控制台应用程序 并添加WebApi相关引用,注意,添加之后会默认帮你添加 System.Web.Http.WebHost 的引用,不过,折并没有什么鸟用,干掉他,然后手动添加引用 Sy ...

  8. div在上一层容器居中的方法

    今天又学了一种新方法,其实不算新,只是我不知道而已,想想学了一年多,现在什么动效都能写点出来了,但是一些基础的东西还是掌握不好,所以我现在依然会一遍遍的复习h5和css3,这就是自学的坏处,不知道的东 ...

  9. [Codeforces 280D]k-Maximum Subsequence Sum(线段树)

    [Codeforces 280D]k-Maximum Subsequence Sum(线段树) 题面 给出一个序列,序列里面的数有正有负,有两种操作 1.单点修改 2.区间查询,在区间中选出至多k个不 ...

  10. redis setNx方法

    Redis有一系列的命令,特点是以NX结尾,NX是Not eXists的缩写,如SETNX命令就应该理解为:SET if Not eXists.这系列的命令非常有用,这里讲使用SETNX来实现分布式锁 ...