该博文所用的demo结构图:

public class MainActivity extends Activity {
private int desiredWindowWidth;
private int desiredWindowHeight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取屏幕的宽高,单位为dp
desiredWindowWidth = Measurement.getScreenWidth(this);
desiredWindowHeight = Measurement.getScreenHeight(this);
Log.d("HWGT", "屏幕宽..=.." + desiredWindowWidth + "....屏幕高..=.." + desiredWindowHeight);
}
@Override
protected void onPause() {
super.onPause();
//获取状态栏的高度(标题栏+content区域的top坐标)
Rect frame = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = Measurement.px2dip(this, frame.top);
//获取 标题栏+content 区域的高度
int titleAndContentHeight = Measurement.px2dip(this, frame.height());
//获取content区域的top坐标
int tempContentTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
int contentTop = Measurement.px2dip(this, tempContentTop);
//标题栏的高度 = content区域的top坐标 - 状态栏的高度
int titleBarHeight = contentTop - statusBarHeight;
Log.d("HWGT", "titleBarHeight..=.."+titleBarHeight+
"....contentTop..=.."+contentTop+"....statusBarHeight..=.." + statusBarHeight );
}
}
activity_main.xml:
<com.hwgt.drawingprocessofview.ui.MyCustomLinearLayoutA
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.hwgt.drawingprocessofview.MainActivity" >
<com.hwgt.drawingprocessofview.ui.MyCustomTextViewA
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="13dp"
android:layout_gravity="center_horizontal"
android:text="@string/hello_world" />
<com.hwgt.drawingprocessofview.ui.MyCustomLinearLayoutB
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="13dp">
<com.hwgt.drawingprocessofview.ui.MyCustomButtonA
android:layout_width="111dp"
android:layout_height="wrap_content"
android:layout_marginLeft="31dp"
android:text="@string/ok"/>
</com.hwgt.drawingprocessofview.ui.MyCustomLinearLayoutB>
</com.hwgt.drawingprocessofview.ui.MyCustomLinearLayoutA>
Measurement.java:
public class Measurement {
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
public static int getScreenWidth(Context context) {
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(dm);
return px2dip(context, dm.widthPixels);
}
public static int getScreenHeight(Context context) {
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(dm);
return px2dip(context, dm.heightPixels);
}
}
MyCustomLinearLayoutA.java、MyCustomTextViewA.java、MyCustomLinearLayoutB.java 和 MyCustomButtonA.java类似,构造函数省略了,onMeasure()方法中的处理也一样:
public class MyCustomLinearLayoutA extends LinearLayout ... ...
public class MyCustomTextViewA extends TextView ... ...
public class MyCustomLinearLayoutB extends LinearLayout ... ...
public class MyCustomButtonA extends Button {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMeasureSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMeasureSpecSize = MeasureSpec.getSize(heightMeasureSpec);
Log.d("HWGT", "ButtonA: widthMeasureSpecSize..=.."+Measurement.px2dip(getContext(), widthMeasureSpecSize)
+ "....heightMeasureSpecSize..=.."+Measurement.px2dip(getContext(), heightMeasureSpecSize));
}
}
Activity 的 setContentView() 方法执行后会调用到PhoneWindow 的 setContentView()方法
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:fitsSystemWindows="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="?android:attr/windowTitleSize"
style="?android:attr/windowTitleBackgroundStyle">
<TextView
android:id="@android:id/title"
style="?android:attr/windowTitleStyle"
android:background="@null"
android:fadingEdge="horizontal"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
<FrameLayout
android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>
R.layout.screen_simple:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/content"
android:fitsSystemWindows="true"
android:foregroundInsidePadding="false"
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
这两个布局都包含一个id为content的FrameLayout布局,比如我们设置了requestWindowFeature(Window.FEATURE_NO_TITLE);或<item name="android:windowNoTitle">true</item>时,R.layout.screen_simple将被添加到mDecor中。






protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mOrientation == VERTICAL) {
measureVertical(widthMeasureSpec, heightMeasureSpec);
} else {
measureHorizontal(widthMeasureSpec, heightMeasureSpec);
}
}
根据LinearLayout的布局方向调用measureVertical或measureHorizontal,下面以本文demo中MyCustomLinearLayoutA为例分析竖直方向的measureVertical。