Androiid 如何动态加载assets目录下的xml布局文件(包括Drawable xml)
来源:互联网 发布:网络改造设备 编辑:程序博客网 时间:2024/05/22 14:15
目录:
- Androiid 如何动态加载assets目录下的xml布局文件包括Drawable xml
- - 如何动态加载布局
- - 加载assets目录下的xml布局
- - 加载Drawable xml
- - 补充说明
Androiid 如何动态加载assets目录下的xml布局文件(包括Drawable xml)
博主是做sdk的,老大有个需求就是把一些资源文件都放到assets目录下一起打进jar包.查阅了一些相关博客,感觉都不全面,我就把我遇到的问题总结一下,希望朋友们以后遇到相同的问题能更好的处理.
- 如何动态加载布局
我们都用过LayoutInflater.infsater去添加一个布局方法如下:
LayoutInflater inflater = (LayoutInflater) mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = inflater.inflate(R.layout.number_auto_roll, null);
我们查看inflater的源码会发现(比较懒,就直接把源码粘出来了,想看源码分析的自己Google)
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) { synchronized (mConstructorArgs) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate"); final Context inflaterContext = mContext; final AttributeSet attrs = Xml.asAttributeSet(parser); Context lastContext = (Context) mConstructorArgs[0]; mConstructorArgs[0] = inflaterContext; View result = root; try { // Look for the root node. int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { // Empty } if (type != XmlPullParser.START_TAG) { throw new InflateException(parser.getPositionDescription() + ": No start tag found!"); } final String name = parser.getName(); if (DEBUG) { System.out.println("**************************"); System.out.println("Creating root view: " + name); System.out.println("**************************"); } if (TAG_MERGE.equals(name)) { if (root == null || !attachToRoot) { throw new InflateException("<merge /> can be used only with a valid " + "ViewGroup root and attachToRoot=true"); } rInflate(parser, root, inflaterContext, attrs, false); } else { // Temp is the root view that was found in the xml final View temp = createViewFromTag(root, name, inflaterContext, attrs); ViewGroup.LayoutParams params = null; if (root != null) { if (DEBUG) { System.out.println("Creating params from root: " + root); } // Create layout params that match root, if supplied params = root.generateLayoutParams(attrs); if (!attachToRoot) { // Set the layout params for temp if we are not // attaching. (If we are, we use addView, below) temp.setLayoutParams(params); } } if (DEBUG) { System.out.println("-----> start inflating children"); } // Inflate all children under temp against its context. rInflateChildren(parser, temp, attrs, true); if (DEBUG) { System.out.println("-----> done inflating children"); } // We are supposed to attach all the views we found (int temp) // to root. Do that now. if (root != null && attachToRoot) { root.addView(temp, params); } // Decide whether to return the root that was passed in or the // top view found in xml. if (root == null || !attachToRoot) { result = temp; } } } catch (XmlPullParserException e) { final InflateException ie = new InflateException(e.getMessage(), e); ie.setStackTrace(EMPTY_STACK_TRACE); throw ie; } catch (Exception e) { final InflateException ie = new InflateException(parser.getPositionDescription() + ": " + e.getMessage(), e); ie.setStackTrace(EMPTY_STACK_TRACE); throw ie; } finally { // Don't retain static reference on context. mConstructorArgs[0] = lastContext; mConstructorArgs[1] = null; Trace.traceEnd(Trace.TRACE_TAG_VIEW); } return result; }
inflater的4种重载的方法都是调用下面的方法来填充布局的.
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)
那么看到第一个参数是XmlPullParser,那么我们是不是可以从XmlPullParser入手呢,那么怎么获得XmlPullParser呢?请往下看…..
- 加载assets目录下的xml布局
这个大家一个都知道,网上一收一大堆,我就不赘述了直接上代码
第一种方法:
private XmlPullParser getLayoutXmlPullParser() throws IOException { XmlPullParser xmlPullParser = null; AssetManager assetManager = mContext.getAssets(); InputStream open = assetManager.open("assets/gif_test_view.xml"); xmlPullParser = Xml.newPullParser(); try { xmlPullParser.setInput(open,"UTF-8"); ........ 解析的代码 } catch (XmlPullParserException e) { e.printStackTrace(); } return xmlPullParser; }
这种方法是解析普通xml文件的方法,这个只是适合我们手动解析xml文件的方法,并不能用于inflate中.
第二种方法:
private XmlPullParser getLayoutXmlPullParser() { XmlPullParser xmlPullParser = null; AssetManager assetManager = mContext.getAssets(); try { xmlPullParser = assetManager.openXmlResourceParser("assets/gif_test_view.xml"); } catch (IOException e) { e.printStackTrace(); } return xmlPullParser; }
这才是正确的打开方式,但是这个方法读取的xml文件必须是编译后的,关于如何获取编译后的xml文件我们后面说
需要注意的是其中fileName必须包含assets/路径
下面就通过inflate方法得到我们想要的view布局了
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mContext = this; XmlPullParser paser = getLayoutXmlPullParser(); ViewGroup view = new LinearLayout(this); mView = LayoutInflater.from(this).inflate(paser, view); setContentView(view); }
我这里在在inflater的时候有传人一个ViewGroup,如果传人null会报错,我当时也没去深究.
- 加载Drawable xml
有的时候我们需要用xml布局去创建一个图片,比如shape,selector,我们是不是也可以放在assets目录下.当然可以.
我们有了上面的启发,我们先去看看Drawable是怎么创建的
是不是看到我们想要的东西了,而且看到了我们熟悉的身影xmlPullParser,话不多说看到代码
方法一:
得到xmlPullParser,创建Drawable.(这里的xml文件是编译后的)
private XmlPullParser getDrawableXmlPullParser() { XmlPullParser xmlPullParser = null; AssetManager assetManager = this.getAssets(); try { xmlPullParser = assetManager.openXmlResourceParser("assets/image.xml"); } catch (IOException e) { e.printStackTrace(); } return xmlPullParser; }
方法二:
得到InputStream创建Drawable(这里的xml可以是编译的也可以是不是编译的)
public InputStream getDrawableXmlInputStrem() { InputStream inputStream = null; AssetManager assetManager = this.getAssets(); try { inputStream = assetManager.open("assets/image1.xml"); } catch (IOException e) { e.printStackTrace(); } return inputStream; }
创建的代码:
XmlPullParser parser = getDrawableXmlPullParser(); InputStream is = getDrawableXmlInputStrem(); try { Drawable drawable = Drawable.createFromXml(getResources(),parser); Drawable drawable1 = Drawable.createFromStream(is,null); bt.setBackground(drawable); bt1.setBackground(drawable1); } catch (XmlPullParserException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
看到这里基本上都知道怎么动态加载assets目录下的资源文件了,但是还有些东西要和大家补充说明一下
- 补充说明
如何得到编译后的xml布局文件:
1.把写好的布局文件放到一个app工程的res/layout里
2.运行这个app,android studio会生成一个debug.apk
3.把这个apk改成zip格式解压,然后找到res/layout文件夹找到我们编译后的布局文件拷到assets目录下
这就是我得到编译后xml的方法,是不是很low,好吧,我承认我很low
加载后的布局文件怎么获取控件
上面我们完成加载布局的功能了,那么问题来了,我布局已经加载完成了,如果我布局里有个Button或者imageview,我怎么设置button的点击事件,有怎么去更改我们的imageview的图片呢?
你会发现你用findViewById是找不到的,因为你的res/layout里根本没有布局,更不会有这个ID.
然后我发现了这个
既然id找不到,那肯定还有别的东西能找到,然后就看到了findViewWithTag的使用.
1.在布局中使用id的地方用tag代替
2.这个tag属性只要我们自己知道就可以了,然后就可以在代码中调用了
final GifImageView gif1 = (GifImageView) mView.findViewWithTag("Gif1"); GifImageView gif2 = (GifImageView) mView.findViewWithTag("Gif2"); GifImageView gif3 = (GifImageView) mView.findViewWithTag("Gif3");
好了到这里一切都结束了,因为我是新手难免有错误,希望有错误的地方大家积极指出谢谢
另:本人是一个android开发的小学生,也是第一次写博客,有不足的地方希望大家多多指出,然后我也跟在大神的后面多多进步.
- Androiid 如何动态加载assets目录下的xml布局文件(包括Drawable xml)
- 如何解析assets目录下的xml文件,,并展示
- Android 加载Assets目录中Xml布局文件
- drawable目录下的xml
- Android 利用XmlParser解析assets目录下的xml文件
- android动态加载sd卡的xml布局文件
- DOM4J解析assets目录下的student.xml文档
- DexClassLoader自定义加载Assets目录下的dex、jar文件
- android学习笔记之说说drawable目录下的xml
- Android drawable目录下面自定义ui形状的XML文件
- 动态加载xml文件
- Unity3d 如何动态加载非Assets路径下的图片
- 如何获取指定目录下的xml文件
- 动态的修改xml中的drawable文件的solid颜色
- Res目录下资源如图片文件和xml文件资源如何被加载显示出来
- android 操作assets目录(图片 xml和布局)
- Xamarin.Android 如何使用Assets目录下的文件
- 如何解压assets目录下的压缩包文件
- FileProvider
- 操作系统简介
- Invalidate和UpdateWindow的区别
- 函数的图像怎么样画
- 巴别鸟App产品体验报告
- Androiid 如何动态加载assets目录下的xml布局文件(包括Drawable xml)
- 使用setAttribute()修改display属性的坑
- public class与public partial class
- Android Studio项目提交GitHub时的出错处理
- 数据结构是哈希表(hashTable)
- AngularJs 解决不能设置Content-Type的方法
- 与Kotlin的第一次接触(Kotlin一)
- <基础原理进阶>机器学习算法python实现【2】--ForwardPass&BackPropagation
- QWidget嵌入QML窗口中