Android에서 Double Taxation을 이해하기 위해 다음 코드를 작성했습니다. 매우 간단합니다. RelativeLayout
에는 세 개의 TextView
이 있습니다.Android에서 RelativeLayout을 사용할 때 이중 과세
<?xml version="1.0" encoding="utf-8"?>
<ru.maksim.sample_app.MyRelativeLayout 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"
tools:context="ru.maksim.sample_app.MainActivity">
<ru.maksim.sample_app.MyTextView
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fca"
android:tag="text1"
android:text="Text 1" />
<ru.maksim.sample_app.MyTextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/text1"
android:background="#acf"
android:tag="text2"
android:text="Text 2" />
<ru.maksim.sample_app.MyTextView
android:id="@+id/text3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/text1"
android:layout_toRightOf="@id/text2"
android:background="#fac"
android:tag="text3"
android:text="text 3" />
</ru.maksim.sample_app.MyRelativeLayout>
MyTextView
public class MyTextView extends android.support.v7.widget.AppCompatTextView {
private static final String TAG = "MyTextView";
public MyTextView(Context context) {
super(context);
}
public MyTextView(Context context,
@Nullable AttributeSet attrs
) {
super(context, attrs);
}
public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = View.MeasureSpec.getMode(widthMeasureSpec);
int heightMode = View.MeasureSpec.getMode(heightMeasureSpec);
Log.d(TAG,
"onMeasure, "
+ getTag()
+ " widthMeasureSpec=" + MeasureSpecMap.getName(widthMode)
+ " heightMeasureSpec=" + MeasureSpecMap.getName(heightMode)
);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
Log.d(TAG, getTag() + " onLayout");
}
}
MyRelativeLayout
public class MyRelativeLayout extends RelativeLayout {
public static final String TAG = "MyRelativeLayout";
public MyRelativeLayout(Context context) {
super(context);
}
public MyRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = View.MeasureSpec.getMode(widthMeasureSpec);
int heightMode = View.MeasureSpec.getMode(heightMeasureSpec);
Log.d(TAG,
"onMeasure, "
+ getTag()
+ " widthMeasureSpec=" + MeasureSpecMap.getName(widthMode)
+ " heightMeasureSpec=" + MeasureSpecMap.getName(heightMode)
);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
Log.d(TAG, getTag() + " onLayout");
}
}
로그 캣 :
09-11 19:25:40.077 7732-7732/ru.maksim.sample_app D/MyTextView: onMeasure, text2 widthMeasureSpec=AT_MOST heightMeasureSpec=AT_MOST
09-11 19:25:40.078 7732-7732/ru.maksim.sample_app D/MyTextView: onMeasure, text3 widthMeasureSpec=AT_MOST heightMeasureSpec=AT_MOST
09-11 19:25:40.078 7732-7732/ru.maksim.sample_app D/MyTextView: onMeasure, text1 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST
09-11 19:25:40.078 7732-7732/ru.maksim.sample_app D/MyTextView: onMeasure, text1 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST
09-11 19:25:40.078 7732-7732/ru.maksim.sample_app D/MyTextView: onMeasure, text3 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST
09-11 19:25:40.078 7732-7732/ru.maksim.sample_app D/MyTextView: onMeasure, text2 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST
09-11 19:25:40.078 7732-7732/ru.maksim.sample_app D/MyRelativeLayout: onMeasure, null widthMeasureSpec=EXACTLY heightMeasureSpec=EXACTLY
[ 09-11 19:25:40.098 7732: 7748 D/ ]
HostConnection::get() New Host Connection established 0xa0a8fbc0, tid 7748
09-11 19:25:40.132 7732-7732/ru.maksim.sample_app D/MyTextView: onMeasure, text2 widthMeasureSpec=AT_MOST heightMeasureSpec=AT_MOST
09-11 19:25:40.132 7732-7732/ru.maksim.sample_app D/MyTextView: onMeasure, text3 widthMeasureSpec=AT_MOST heightMeasureSpec=AT_MOST
09-11 19:25:40.132 7732-7732/ru.maksim.sample_app D/MyTextView: onMeasure, text1 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST
09-11 19:25:40.132 7732-7732/ru.maksim.sample_app D/MyTextView: onMeasure, text1 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST
09-11 19:25:40.132 7732-7732/ru.maksim.sample_app D/MyTextView: onMeasure, text3 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST
09-11 19:25:40.132 7732-7732/ru.maksim.sample_app D/MyTextView: onMeasure, text2 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST
09-11 19:25:40.132 7732-7732/ru.maksim.sample_app D/MyRelativeLayout: onMeasure, null widthMeasureSpec=EXACTLY heightMeasureSpec=EXACTLY
09-11 19:25:40.132 7732-7732/ru.maksim.sample_app D/MyTextView: text1 onLayout
09-11 19:25:40.132 7732-7732/ru.maksim.sample_app D/MyTextView: text2 onLayout
09-11 19:25:40.132 7732-7732/ru.maksim.sample_app D/MyTextView: text3 onLayout
09-11 19:25:40.132 7732-7732/ru.maksim.sample_app D/MyRelativeLayout: null onLayout
01,235 16,
이제 MyLinearLayout
라고 LinearLayoiut
의 자식으로 MyRelativeLayout
을 교체하자
<?xml version="1.0" encoding="utf-8"?>
<ru.maksim.sample_app.MyLinearLayout 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="ru.maksim.sample_app.MainActivity">
<ru.maksim.sample_app.MyTextView
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fca"
android:tag="text1"
android:text="Text 1" />
<ru.maksim.sample_app.MyTextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#acf"
android:tag="text2"
android:text="Text 2" />
<ru.maksim.sample_app.MyTextView
android:id="@+id/text3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fac"
android:tag="text3"
android:text="text 3" />
</ru.maksim.sample_app.MyLinearLayout>
MyLinearLayout 여기
public class MyLinearLayout extends LinearLayout {
public static final String TAG = "MyLinearLayout";
public MyLinearLayout(Context context) {
super(context);
}
public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = View.MeasureSpec.getMode(widthMeasureSpec);
int heightMode = View.MeasureSpec.getMode(heightMeasureSpec);
Log.d(TAG,
"onMeasure, "
+ getTag()
+ " widthMeasureSpec=" + MeasureSpecMap.getName(widthMode)
+ " heightMeasureSpec=" + MeasureSpecMap.getName(heightMode)
);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
Log.d(TAG, getTag() + " onLayout");
}
}
것은 지금 로그 캣에서 볼 것입니다 :
09-11 19:50:57.974 2781-2781/? D/MyTextView: onMeasure, text1 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST
09-11 19:50:57.974 2781-2781/? D/MyTextView: onMeasure, text2 widthMeasureSpec=AT_MOST heightMeasureSpec=AT_MOST
09-11 19:50:57.974 2781-2781/? D/MyTextView: onMeasure, text3 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST
09-11 19:50:57.974 2781-2781/? D/MyLinearLayout: onMeasure, null widthMeasureSpec=EXACTLY heightMeasureSpec=EXACTLY
[ 09-11 19:50:58.004 2781: 2817 D/ ]
HostConnection::get() New Host Connection established 0xa5ec1940, tid 2817
09-11 19:50:58.017 2781-2781/? D/MyTextView: onMeasure, text1 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST
09-11 19:50:58.017 2781-2781/? D/MyTextView: onMeasure, text2 widthMeasureSpec=AT_MOST heightMeasureSpec=AT_MOST
09-11 19:50:58.017 2781-2781/? D/MyTextView: onMeasure, text3 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST
09-11 19:50:58.017 2781-2781/? D/MyLinearLayout: onMeasure, null widthMeasureSpec=EXACTLY heightMeasureSpec=EXACTLY
09-11 19:50:58.017 2781-2781/? D/MyTextView: text1 onLayout
09-11 19:50:58.017 2781-2781/? D/MyTextView: text2 onLayout
09-11 19:50:58.017 2781-2781/? D/MyTextView: text3 onLayout
09-11 19:50:58.017 2781-2781/? D/MyLinearLayout: null onLayout
public class MeasureSpecMap {
private static final Map<Integer, String> MAP = new HashMap<>();
static {
MAP.put(View.MeasureSpec.AT_MOST, "AT_MOST");
MAP.put(View.MeasureSpec.EXACTLY, "EXACTLY");
MAP.put(View.MeasureSpec.UNSPECIFIED, "UNSPECIFIED");
}
private MeasureSpecMap() {
}
public static String getName(int mode) {
return MAP.get(mode);
}
}
질문 1.
MyRelativeLayout
를 사용하는 경우, 왜 시스템이 MyRelativeLayout
의 onMeasure
전에 두 번 각 자녀에 onMeasure
를 호출 할 필요가 않습니다 단지 위의 두 예에서 사용
는 MeasureSpecMap
(가) Map
다음 포함 전화 했어? MyLinearLayout
을 사용하면 위의 로그 출력에서 볼 수 있듯이 예제의 각 자식이 한 번 측정됩니다.
질문 2. 다음
이해가 안 the Double taxation section에서 뭔가 다른 :
을 당신이에 대한 당신 위치보기 개체 수있는 RelativeLayout의 컨테이너를 사용하는 경우는 기타 보기 개체의 위치에서 프레임 워크는 다음 작업을 수행합니다.
레이아웃 및 계수 패스를 실행하는 동안 f ramework 은 각 자식 개체의 위치와 크기를 각각의 자식 요청에 따라 계산합니다. 이 데이터 ()를 사용하여 개체 가중치를 계정으로 가져와 상관 된 뷰의 적절한 위치를 찾습니다.
이 데이터 ()를 사용하여 계정에 가중치를 부여하여 상관 된 뷰의 적절한 위치를 파악합니다.
하지만 ... 그들은 약 android:layout_weight
LinearLayout
의 특징 인 이야기 아닌가 기다려?
위의 코드는 GitHub의에로도 주문 가능합니다
The approach with MyLinearLayout
The approach with MyRelativeLayout
질문 # 2에 대한 답변 : 설명서 버그 일 수 있습니다. – CommonsWare