0

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를 사용하는 경우, 왜 시스템이 MyRelativeLayoutonMeasure 전에 두 번 각 자녀에 onMeasure를 호출 할 필요가 않습니다 단지 위의 두 예에서 사용

MeasureSpecMap (가) Map 다음 포함 전화 했어? MyLinearLayout을 사용하면 위의 로그 출력에서 ​​볼 수 있듯이 예제의 각 자식이 한 번 측정됩니다.

질문 2. 다음

이해가 안 the Double taxation section에서 뭔가 다른 :

을 당신이에 대한 당신 위치보기 개체 수있는 RelativeLayout의 컨테이너를 사용하는 경우는 기타 보기 개체의 위치에서 프레임 워크는 다음 작업을 수행합니다.

레이아웃 및 계수 패스를 실행하는 동안 f ramework 은 각 자식 개체의 위치와 크기를 각각의 자식 요청에 따라 계산합니다. 이 데이터 ()를 사용하여 개체 가중치를 계정으로 가져와 상관 된 뷰의 적절한 위치를 찾습니다.

이 데이터 ()를 사용하여 계정에 가중치를 부여하여 상관 된 뷰의 적절한 위치를 파악합니다.

하지만 ... 그들은 약 android:layout_weightLinearLayout의 특징 인 이야기 아닌가 기다려?


위의 코드는 GitHub의에로도 주문 가능합니다

The approach with MyLinearLayout

The approach with MyRelativeLayout

+1

질문 # 2에 대한 답변 : 설명서 버그 일 수 있습니다. – CommonsWare

답변

1

질문 1.

MyRelativeLayout를 사용하는 경우, 왜 시스템을 수행각 어린이에게 onMeasure을 두 번 두 번 호출해야합니다. onMeasureMyRelativeLayout이라면? MyLinearLayout을 사용하면 위의 로그 출력에서 ​​볼 수 있듯이 예제의 각 자식이 한 번 측정됩니다.

(지나치게) 단순한 용어로 한보기의 크기와 위치가 다른보기의 크기와 위치에 영향을 줄 수 있습니다.

text3을 고려하십시오. 폭은 보유하고있는 텍스트의 길이뿐만 아니라 너비도 text2입니다. text2이 화면의 80 %를 소비하는 경우 text3은 화면의 최대 20 %만을 차지합니다.

그래서 시스템은 뷰가 서로 배치 할 "제약 조건"을 파악하기위한 첫 번째 측정 값 패스를 수행 한 다음 두 번째 측정 값 패스를 사용하여 최종 값을 계산합니다.

로그 출력 (간결함을 위해 생략 텍스트)에서 살펴 보자 : 그 widthMeasureSpec 두 번째 시간 동안 모드 AT_MOST이며,

D/MyTextView: onMeasure, text2 widthMeasureSpec=AT_MOST heightMeasureSpec=AT_MOST 
D/MyTextView: onMeasure, text3 widthMeasureSpec=AT_MOST heightMeasureSpec=AT_MOST 
D/MyTextView: onMeasure, text1 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST 

D/MyTextView: onMeasure, text1 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST 
D/MyTextView: onMeasure, text3 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST 
D/MyTextView: onMeasure, text2 widthMeasureSpec=EXACTLY heightMeasureSpec=AT_MOST 

처음 text2을 측정하는 방법을 알아보십시오 그것을 모드가 EXACTLY입니까? 첫 번째 패스는 text2에 화면 너비의 최대 100 %를 소비 할 기회를 제공하지만 두 번째 패스는 실제 필요한 크기로 제한합니다.

반면에 수직 LinearLayout의 경우 시스템은 단일 측정 단계에서 알아야 할 모든 것을 얻을 수 있습니다. text1은 전체 창 높이까지 허용되며 text2은 전체 창 높이에서 text1의 높이를 뺀 값까지 허용됩니다.

질문 2.

...

그러나 약 android:layout_weightLinearLayout의 특징 인을 ... 이야기 아닌가 기다려?

이 부분도 이해할 수 없습니다. CommonsWare의 추측이 단지 문서 버그 일 뿐이라고 생각합니다.

관련 문제