- CompoundButton 源码分析
- LinearLayout 源码分析
- SearchView 源码解析
- LruCache 源码解析
- ViewDragHelper 源码解析
- BottomSheets 源码解析
- Media Player 源码分析
- NavigationView 源码解析
- Service 源码解析
- Binder 源码分析
- Android 应用 Preference 相关及源码浅析 SharePreferences 篇
- ScrollView 源码解析
- Handler 源码解析
- NestedScrollView 源码解析
- SQLiteOpenHelper/SQLiteDatabase/Cursor 源码解析
- Bundle 源码解析
- LocalBroadcastManager 源码解析
- Toast 源码解析
- TextInputLayout
- LayoutInflater 和 LayoutInflaterCompat 源码解析
- TextView 源码解析
- NestedScrolling 事件机制源码解析
- ViewGroup 源码解析
- StaticLayout 源码分析
- AtomicFile 源码解析
- AtomicFile 源码解析
- Spannable 源码分析
- Notification 之 Android 5.0 实现原理
- CoordinatorLayout 源码分析
- Scroller 源码解析
- SwipeRefreshLayout 源码分析
- FloatingActionButton 源码解析
- AsyncTask 源码分析
- TabLayout 源码解析
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
5.5 parseInclude 方法解析
/** * 解析 include 标签 */ private void parseInclude(XmlPullParser parser, Context context, View parent, AttributeSet attrs) throws XmlPullParserException, IOException { int type; // 如果 include 标签的父 View 是 ViewGroup,则继续,否则抛出异常。 if (parent instanceof ViewGroup) { // 使用主题包装。如果 include 中的 View 有自己的 attr 属性,则忽略。 final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME); final int themeResId = ta.getResourceId(0, 0); final boolean hasThemeOverride = themeResId != 0; if (hasThemeOverride) { context = new ContextThemeWrapper(context, themeResId); } ta.recycle(); // 获取 Layout 标签指向布局资源 id int layout = attrs.getAttributeResourceValue(null, ATTR_LAYOUT, 0); if (layout == 0) { // 获取 Layout 的 value 值 final String value = attrs.getAttributeValue(null, ATTR_LAYOUT); if (value == null || value.length() <= 0) { throw new InflateException("You must specify a layout in the" + " include tag: <include layout=\"@layout/layoutID\" />"); } // 尝试解析"?attr/name"成 id 资源 layout = context.getResources().getIdentifier(value.substring(1), null, null); } // include 的布局可能引用了主题属性 if (mTempValue == null) { mTempValue = new TypedValue(); } // 尝试从主题中获取布局资源 id,如果有的话。 if (layout != 0 && context.getTheme().resolveAttribute(layout, mTempValue, true)) { layout = mTempValue.resourceId; } // 如果还是无法找到布局 id,抛出异常。 if (layout == 0) { final String value = attrs.getAttributeValue(null, ATTR_LAYOUT); throw new InflateException("You must specify a valid layout " + "reference. The layout ID " + value + " is not valid."); } else { // 获取 include 标签中布局的解析器 final XmlResourceParser childParser = context.getResources().getLayout(layout); try { final AttributeSet childAttrs = Xml.asAttributeSet(childParser); // 查找根节点 while ((type = childParser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { // Empty. } // 如果找不到根节点,抛出异常。 if (type != XmlPullParser.START_TAG) { throw new InflateException(childParser.getPositionDescription() + ": No start tag found!"); } // 获取标签名 final String childName = childParser.getName(); // 实例化 merge 标签 if (TAG_MERGE.equals(childName)) { // <merge>标签不支持 android:theme,所以不需要其他处理 rInflate(childParser, parent, context, childAttrs, false); } else { // 创建 View 实例化对象 final View view = createViewFromTag(parent, childName, context, childAttrs, hasThemeOverride); final ViewGroup group = (ViewGroup) parent; // 获取 View 的 id 和可见性 final TypedArray a = context.obtainStyledAttributes( attrs, R.styleable.Include); final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID); final int visibility = a.getInt(R.styleable.Include_visibility, -1); a.recycle(); // 尝试加载<include />标签中的布局参数,如果父 View 无法生成布局参数(比如 include 标签下没有宽高参数是要抛出运行时异常的) // 捕获运行时异常,然后用引用的 Layout 的 attrs 来创建布局参数 ViewGroup.LayoutParams params = null; try { // 使用 include 标签的 attrs 来生成布局参数 params = group.generateLayoutParams(attrs); } catch (RuntimeException e) { // Ignore, just fail over to child attrs. } if (params == null) { // 如果 include 标签的 attrs 没有正确的生成布局参数,则使用 Layout 布局的 attrs 来生成布局参数 params = group.generateLayoutParams(childAttrs); } view.setLayoutParams(params); // 实例化所有子 View rInflateChildren(childParser, view, childAttrs, true); if (id != View.NO_ID) { view.setId(id); } switch (visibility) { case 0: view.setVisibility(View.VISIBLE); break; case 1: view.setVisibility(View.INVISIBLE); break; case 2: view.setVisibility(View.GONE); break; } // 把布局实例化的 View 添加到父 View 上。 group.addView(view); } } finally { childParser.close(); } } } else { throw new InflateException("<include /> can only be used inside of a ViewGroup"); } LayoutInflater.consumeChildElements(parser); }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论