View的加载
(1)LayoutInflater作用是将layout的xml(main)布局文件实例化为View类对象
LayoutInflater inflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);View layout = inflater.inflate(R.layout.main, null); LayoutInflater inflater = LayoutInflater.from(context); (该方法实质就是第一种方法,可参考源代码)View layout = inflater.inflate(R.layout.main, null); LayoutInflater inflater = getLayoutInflater();(在Activity中可以使用,实际上是View子类下window的一个函数)View layout = inflater.inflate(R.layout.main, null);
(2)加载layout的xml布局文件中的控间
<pre name="code" class="java">//如以下形式Button mButton = this.findViewById(R.id.Button);//或者如下(parent为父View)Button mButton = parent.findViewById(R.id.Button);
LayoutParams自定义Layout布局及其View信息
实际上每个不同的ViewGroup(基本所有的控件都是其子类)都有自己的LayoutParams内部类,可以看成是每个ViewGroup的属性,定义对应的宽高,在对于View的绘制过程中(详情可参考《andrid内核剖析》),子View的绘制其父View需要知道其宽高并加以绘制,而这些信息也要传递到父View。LayoutParams相当于一个Layout的信息包,假设在屏幕上一块区域是由一个Layout占领的,如果将一个View添加到一个Layout中,最好告诉Layout用户期望的布局方式,也就是将一个认可的layoutParams传递进去。
LayoutParams类也只是简单的描述了宽高,宽和高都可以设置成三种值:
(1)一个确定的值;
(2) FILL_PARENT,即填满(和父容器一样大小);
(3)WRAP_CONTENT,即包裹住组件就好。
(例子如下)
//创建一个线性布局private LinearLayout Layout;mLayout = (LinearLayout) findViewById(R.id.layout);TextView textView = new TextView(Activity01.this);textView.setText("Text View " );//第一个参数为宽的设置,第二个参数为高的设置。LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);//调用addView()方法增加一个TextView到线性布局中mLayout.addView(textView, p);//比较简单的一个例子上述例子事实上和下面代码的执行效果是一样的:
private LinearLayout mLayout;mLayout = (LinearLayout) findViewById(R.id.layout);//现在我要往mLayout里边添加一个TextView//你可能会想直接在布局文件里边配置不就O 了 那是 但是这里为了说明问题我们用代码实现TextView textView = new TextView(Activity01.this);textView.setText("Text View " ); LayoutParams p = (LayoutParams)mLayout.getLayoutParams();p.height=LinearLayout.LayoutParams.MATCH_PARENT;p.width = LinearLayout.LayoutParams.WRAP_CONTENT;;textView.setLayoutParams(p);mLayout.addView(textView);
值得一提的是:setLayoutParams()其实是子对父的表达的,也就是父布局下的子控件要设置这句话。
更要理解的是:如果某View被LinearLayout包含,则该View的setLayoutParams参数类型必须是LinearLayout.LayoutParams。原因在于LinearLayout(或其他继承自ViewGroup的layout,如:RelativeLayout)在进行递归布局的时候,LinearLayout会获取子View的LayoutParams,并强制转换成LinearLayout.LayoutParams。我们在xml布局里面设置控件的大小后显示出来就是在递归布局是采用上述做法。
总之,无论对特定控件(事实上也是View)通过其内部类对象来设置LayoutParams,其内部都是在绘制的过程中向其父View传递宽高的信息。于是可以下一个简单的结论:无论动态还是静态记载View来设置其宽高,都拿自己的LayoutParams信息告诉父View我要根据这样来打扮我自己,只不过动态就是自己亲口告诉父View要这样打扮,而静态就是父View来征求子View意见再打扮。
setContentView和inflate的区别
先看代码
public class MyInflate extends Activity{ private TextView tv; public void OnCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); //setContentView(R.layout.main); LayoutInflater inflate = LayoutInflater.from(this); View view = inflate.inflate(R.layout.main,null); setContentView(view); }}上述注释掉的代码和没有注释掉的代码两种情况是相同的。区别在于
setContentView()一旦调用, layout就会立刻显示UI;而inflate只会把Layout形成一个以view类实现成的对象,有需要时再用setContentView()显示出来。一般在activity中通过setContentView()将界面显示出来,但是如果在非activity中如何对控件布局设置操作了,这就需要LayoutInflater动态加载,调用inflate()从指定的XML资源文件中加载一个新的视图层次结构,具体解释如下
public View inflate(int Resourece,ViewGroup root)
reSource:View的layout的ID
root: 生成的层次结构的根视图
return 填充的层次结构的根视图。如果参数root提供了,那么root就是根视图;否则填充的XML文件的根就是根视图。
root: 生成的层次结构的根视图
return 填充的层次结构的根视图。如果参数root提供了,那么root就是根视图;否则填充的XML文件的根就是根视图。
图片资源的加载
sd卡下的图片
Bitmap imageBitmap = BitmapFactory.decodeFile(path)
res文件夹下的图片
//得到application对象ApplicationInfo appInfo = getApplicationInfo();//得到该图片的id(name 是该图片的名字,drawable 是该图片存放的目录,appInfo.packageName是应用程序的包)int resID = getResources().getIdentifier(name, drawable, appInfo.packageName);//代码如下public Bitmap getRes(String name){ ApplicationInfo appInfo = getApplicationInfo(); int resID = getResources().getIdentifier(name, drawable, appInfo.packageName); return BitmapFactory.decodeResource(getResources(), resID);}
src目录下的图片
String path = com/xiangmu/test.png; //图片存放的路径 InputStream is = getClassLoader().getResourceAsStream(path); //得到图片流
Assets目录下的文件(该目录只可以存放只读文件)
//方法1:AssetManager assetManager = this.getResources().getAsset();InputStream fis = assetManager.open("db.properties");//简写为:InputStream fis = getResources().getAssets().open("db.properties");//方法2:InputStream abpath = getClass().getResourceAsStream("/assets/文件名");