关于几点说明
- Android中每个Activity包含一个Window对象,这个Window对象就是PhoneWindow
- PhoneWindow将DecorView设为根View
- 所有View的监听事件都是通过WindowManagerService来进行接收的
- 在显示上屏幕是分两部分的,TitleView和ContentView
- setContentView就是设置ContentView,requestWindowFeature(Window.FEAUTRE_NO_TITLE)就是来设置全屏
View的测量
- View的测量是通过MeasureSpec类,测量模式有三种:EXACTLY精准模式、AT_MOST最大模式(控件属性指定为wrap_content)、UNSPECIFIED默认模式想多大多大,一般自定义View时才使用
- View类默认的onMeasure()方法只支持EXACTLY模式,自定义控件如果不重写onMeasure()方法时,只能使用EXACTLY模式。指定具体值或match_parent属性,要View支持wrap_content属性就必须重写该方法
测量示例
1、当指定具体值或者match_parent属性时显示对应的大小,当指定wrap_content时不显示全屏,显示一个我们定义的大小
因为是在Android Studio中测试的,所以自定义View就变得相对比Eclipse中药简单些。
步骤:
- 在AS中新建一个自定义View,右键->UI Component->Custom View。
- 重写onMeasure方法,Code->Override Methods,输入onMeasure就可以了。
重写的内容:
public class MyView extends View {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(
measureWidth(widthMeasureSpec),
measureHeight(heightMeasureSpec));
}
private int measureWidth(int measureSpec){
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if(specMode == MeasureSpec.EXACTLY){
result = specSize;
}else {
result = 200;
if (specMode == MeasureSpec.AT_MOST) {
result =Math.min(result,specSize);
}
}
return result;
}
private int measureHeight(int measureSpec){
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if(specMode == MeasureSpec.EXACTLY){
result = specSize;
}else {
result = 200;
if (specMode == MeasureSpec.AT_MOST) {
result =Math.min(result,specSize);
}
}
return result;
}
}
content_main.xml文件内容(此处只写了wrap_content一种情况):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.example.yzx.mytest_book.MainActivity"
tools:showIn="@layout/activity_main">
<com.example.yzx.mytest_book.UI.MyView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ccc"
app:exampleColor="#33b5e5"
app:exampleDimension="12sp"
app:exampleString="Hello, MyView" />
</RelativeLayout>
说明:exampleColor、exampleDimension、exampleString是定义在values文件下的attrs.xml文件中的。
<resources>
<declare-styleable name="MyView">
<attr name="exampleString" format="string" />
<attr name="exampleDimension" format="dimension" />
<attr name="exampleColor" format="color" />
<attr name="exampleDrawable" format="color|reference" />
</declare-styleable>
</resources>
指定宽高值为300dp时:
宽高值为match_parent:
宽高值为wrap_content:
可以发现,当指定wrap_content属性时,View就获得了一个默认200px,而不是再填充父布局了。如果不重写onMeasure()方法,那么系统就不知道该使用默认多大的尺寸。因此,它就会默认填充整个父布局,所以重写onMeasure()方法的目的,就是为了给View一个wrap_content属性下的默认大小。