Android开发之parseInclude方法分析

By heiry on 2017-10-12 [ in 技术 ]
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// 参数说明:
// parser 解析布局的解析器
// context 当前加载布局的上下文对象
// parent 父容器
// attrs 属性集合(XML该节点的属性集合)
private void parseInclude(XmlPullParser parser, Context context, View parent,
AttributeSet attrs) throws XmlPullParserException, IOException {
int type;
// 判断 Include标签是否在 ViewGroup容器之内,因为 include 标签只能存在于 ViewGroup 容器之内。
if (parent instanceof ViewGroup) {
//------------------<第一部分>-------------------//
//当开发者设置 include 主题属性时,可以覆盖被 include 包裹View的主题属性。
//但是这种操作很少会使用。
//所以如果被包裹 View 设置主题属性,我们在设置就会出现覆盖效果。
//以 include 标签的主题属性为最终的主题属性
//提取出 include 的 thme 属性,如果设置了 them 属性,那么include 包裹的View 设置的 theme 将会无效
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 的资源标识符
//先获取 layout 属性(资源 id)是否设置
int layout = attrs.getAttributeResourceValue(null, ATTR_LAYOUT, 0);
if (layout == 0) {
//如果没直接设置布局的资源 id,那么就检索?attr/name这一类的 layout 属性
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: ");
}
//从 ?attr/name 这一类的属性中,获取布局属性
layout = context.getResources().getIdentifier(value.substring(1), null, null);
}
//这个布局资源也许存在主题属性中,所以需要去主题属性中解析
if (mTempValue == null) {
mTempValue = new TypedValue();
}
if (layout != 0 && context.getTheme().resolveAttribute(layout, mTempValue, true)) {
layout = mTempValue.resourceId;
}
//------------------<第三部分>-------------------//
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 {
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();
if (TAG_MERGE.equals(childName)) {
//解析 Meger 标签
rInflate(childParser, parent, context, childAttrs, false);
} else {
//根据 name名称来创建View
final View view = createViewFromTag(parent, childName,
context, childAttrs, hasThemeOverride);
final ViewGroup group = (ViewGroup) parent;
//获取 View 的 id 和其 Visiable 属性
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();
//需要将 Parent中的 LayoutParams 设置为其 Params 属性。
//如果 Parent 没有通用的 Params,那么就会抛出Runtime 异常
//然后会为其设置 include 包裹内容的通用 Params,
ViewGroup.LayoutParams params = null;
try {
params = group.generateLayoutParams(attrs);
} catch (RuntimeException e) {
// Ignore, just fail over to child attrs.
}
if (params == null) {
params = group.generateLayoutParams(childAttrs);
}
view.setLayoutParams(params);
// 解析子标签
rInflateChildren(childParser, view, childAttrs, true);
if (id != View.NO_ID) {
view.setId(id);
}
// 加载include内容时,需要直接设置其 可见性
switch (visibility) {
case 0:
view.setVisibility(View.VISIBLE);
break;
case 1:
view.setVisibility(View.INVISIBLE);
break;
case 2:
view.setVisibility(View.GONE);
break;
}
//添加至父容器中
group.addView(view);
}
} finally {
childParser.close();
}
}
} else {
throw new InflateException(" can only be used inside of a ViewGroup");
}
LayoutInflater.consumeChildElements(parser);
}
// 参数说明: // parser 解析布局的解析器 // context 当前加载布局的上下文对象 // parent 父容器 // attrs 属性集合(XML该节点的属性集合) private void parseInclude(XmlPullParser parser, Context context, View parent, AttributeSet attrs) throws XmlPullParserException, IOException { int type; // 判断 Include标签是否在 ViewGroup容器之内,因为 include 标签只能存在于 ViewGroup 容器之内。 if (parent instanceof ViewGroup) { //------------------<第一部分>-------------------// //当开发者设置 include 主题属性时,可以覆盖被 include 包裹View的主题属性。 //但是这种操作很少会使用。 //所以如果被包裹 View 设置主题属性,我们在设置就会出现覆盖效果。 //以 include 标签的主题属性为最终的主题属性 //提取出 include 的 thme 属性,如果设置了 them 属性,那么include 包裹的View 设置的 theme 将会无效 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 的资源标识符 //先获取 layout 属性(资源 id)是否设置 int layout = attrs.getAttributeResourceValue(null, ATTR_LAYOUT, 0); if (layout == 0) { //如果没直接设置布局的资源 id,那么就检索?attr/name这一类的 layout 属性 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: "); } //从 ?attr/name 这一类的属性中,获取布局属性 layout = context.getResources().getIdentifier(value.substring(1), null, null); } //这个布局资源也许存在主题属性中,所以需要去主题属性中解析 if (mTempValue == null) { mTempValue = new TypedValue(); } if (layout != 0 && context.getTheme().resolveAttribute(layout, mTempValue, true)) { layout = mTempValue.resourceId; } //------------------<第三部分>-------------------// 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 { 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(); if (TAG_MERGE.equals(childName)) { //解析 Meger 标签 rInflate(childParser, parent, context, childAttrs, false); } else { //根据 name名称来创建View final View view = createViewFromTag(parent, childName, context, childAttrs, hasThemeOverride); final ViewGroup group = (ViewGroup) parent; //获取 View 的 id 和其 Visiable 属性 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(); //需要将 Parent中的 LayoutParams 设置为其 Params 属性。 //如果 Parent 没有通用的 Params,那么就会抛出Runtime 异常 //然后会为其设置 include 包裹内容的通用 Params, ViewGroup.LayoutParams params = null; try { params = group.generateLayoutParams(attrs); } catch (RuntimeException e) { // Ignore, just fail over to child attrs. } if (params == null) { params = group.generateLayoutParams(childAttrs); } view.setLayoutParams(params); // 解析子标签 rInflateChildren(childParser, view, childAttrs, true); if (id != View.NO_ID) { view.setId(id); } // 加载include内容时,需要直接设置其 可见性 switch (visibility) { case 0: view.setVisibility(View.VISIBLE); break; case 1: view.setVisibility(View.INVISIBLE); break; case 2: view.setVisibility(View.GONE); break; } //添加至父容器中 group.addView(view); } } finally { childParser.close(); } } } else { throw new InflateException(" can only be used inside of a ViewGroup"); } LayoutInflater.consumeChildElements(parser); }
// 参数说明:
// parser      解析布局的解析器
// context     当前加载布局的上下文对象
// parent      父容器
// attrs       属性集合(XML该节点的属性集合)
private void parseInclude(XmlPullParser parser, Context context, View parent,
           AttributeSet attrs) throws XmlPullParserException, IOException {
       int type;

       // 判断 Include标签是否在 ViewGroup容器之内,因为 include 标签只能存在于 ViewGroup 容器之内。

       if (parent instanceof ViewGroup) {

           //------------------<第一部分>-------------------//

           //当开发者设置 include 主题属性时,可以覆盖被 include 包裹View的主题属性。
           //但是这种操作很少会使用。
           //所以如果被包裹 View 设置主题属性,我们在设置就会出现覆盖效果。
           //以 include 标签的主题属性为最终的主题属性

           //提取出 include 的 thme 属性,如果设置了 them 属性,那么include 包裹的View 设置的 theme 将会无效
           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 的资源标识符
           //先获取 layout 属性(资源 id)是否设置
           int layout = attrs.getAttributeResourceValue(null, ATTR_LAYOUT, 0);
           if (layout == 0) {
           //如果没直接设置布局的资源 id,那么就检索?attr/name这一类的 layout 属性
               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: ");
               }

               //从  ?attr/name 这一类的属性中,获取布局属性  
               layout = context.getResources().getIdentifier(value.substring(1), null, null);
           }

           //这个布局资源也许存在主题属性中,所以需要去主题属性中解析
           if (mTempValue == null) {
               mTempValue = new TypedValue();
           }
           if (layout != 0 && context.getTheme().resolveAttribute(layout, mTempValue, true)) {
               layout = mTempValue.resourceId;
           }


           //------------------<第三部分>-------------------//

           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 {
               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();

                   if (TAG_MERGE.equals(childName)) {
                       //解析 Meger 标签
                       rInflate(childParser, parent, context, childAttrs, false);
                   } else {
                       //根据 name名称来创建View
                       final View view = createViewFromTag(parent, childName,
                               context, childAttrs, hasThemeOverride);
                       final ViewGroup group = (ViewGroup) parent;


                       //获取 View 的 id 和其 Visiable 属性
                       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();

                       //需要将 Parent中的 LayoutParams 设置为其 Params 属性。
                       //如果 Parent 没有通用的 Params,那么就会抛出Runtime 异常

                       //然后会为其设置 include 包裹内容的通用 Params,

                       ViewGroup.LayoutParams params = null;
                       try {
                           params = group.generateLayoutParams(attrs);
                       } catch (RuntimeException e) {
                           // Ignore, just fail over to child attrs.
                       }
                       if (params == null) {
                           params = group.generateLayoutParams(childAttrs);
                       }
                       view.setLayoutParams(params);

                       // 解析子标签
                       rInflateChildren(childParser, view, childAttrs, true);

                       if (id != View.NO_ID) {
                           view.setId(id);
                       }

                       // 加载include内容时,需要直接设置其 可见性
                       switch (visibility) {
                           case 0:
                               view.setVisibility(View.VISIBLE);
                               break;
                           case 1:
                               view.setVisibility(View.INVISIBLE);
                               break;
                           case 2:
                               view.setVisibility(View.GONE);
                               break;
                       }
                       //添加至父容器中
                       group.addView(view);
                   }
               } finally {
                   childParser.close();
               }
           }
       } else {
           throw new InflateException(" can only be used inside of a ViewGroup");
       }

       LayoutInflater.consumeChildElements(parser);
   }

 

 >>



© 2009-2024 MOSANG.NET DESIGNED BY HEIRY