LayoutInflater가 지정한 layout_width 및 layout_height 레이아웃 매개 변수를 무시하는 이유는 무엇입니까?


168

LayoutInflater가 예상대로 작동하는 데 심각한 문제가 있었고 다른 사람들도 마찬가지였습니다. 런타임에 layoutinflator를 사용하여 뷰를 추가하는 방법은 무엇입니까? .

LayoutInflater가 지정한 레이아웃 매개 변수를 무시하는 이유는 무엇입니까? 예를 들어 내 리소스 XML 의 layout_widthlayout_height값이 존중되지 않는 이유는 무엇입니까?


사실 그게 아프거나 틀린 곳을 골랐나요? 내 결과를 공유한다고 생각했습니다. 자주 묻는 질문 (FAQ) 페이지에서 자습서를 언급하지 않아야합니다.
andig

3
FAQ에서 첫 번째 질문의 마지막 단락을 참조하십시오. 질문으로 게시 한 다음 튜토리얼을 답변으로 게시하십시오. 물론이 질문을 잘라 내고 답변에 자습서를 붙여 넣을 수 있습니다. 이 문제를 해결하면 투표하겠습니다.
bigstones

답변:


381

LayoutInflater 문서를 참조 하고 작은 샘플 데모 프로젝트를 설정 하여이 문제를 조사했습니다 . 다음 자습서는를 사용하여 레이아웃을 동적으로 채우는 방법을 보여줍니다 LayoutInflater.

시작하기 전에 어떤 LayoutInflater.inflate()매개 변수가 다음과 같은지 확인하십시오 .

  • 자원 : 부하에 대한 XML 레이아웃 리소스 ID (예 R.layout.main_page)
  • 루트 : 옵션보기 (경우에 생성 된 계층 구조의 부모가 될 attachToRoot것입니다 true다른 사람), 또는 단순히 세트 제공하는 객체 LayoutParams반환 된 계층 구조의 루트 값을 (경우 attachToRoot입니다 false.)
  • attachToRoot : 팽창 된 계층을 루트 매개 변수에 첨부 해야하는지 여부 false 인 경우 root는 LayoutParamsXML에서 루트 뷰에 대한 올바른 서브 클래스를 작성하는 데만 사용됩니다 .

  • 반환 : 팽창 된 계층의 루트 뷰. 루트가 공급 된 경우 attachToRoot이며 true,이 루트입니다; 그렇지 않으면 팽창 된 XML 파일의 루트입니다.

이제 샘플 레이아웃과 코드를 살펴 보겠습니다.

메인 레이아웃 ( main.xml) :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</LinearLayout>

이 컨테이너에 추가 된 TextView는 XML ( red.xml) 에서 레이아웃 매개 변수가 성공적으로 적용된 경우 작은 빨간색 사각형으로 표시됩니다 .

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="25dp"
    android:layout_height="25dp"
    android:background="#ff0000"
    android:text="red" />

이제는 LayoutInflater다양한 통화 매개 변수와 함께 사용됩니다.

public class InflaterTest extends Activity {

    private View view;

    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      setContentView(R.layout.main);
      ViewGroup parent = (ViewGroup) findViewById(R.id.container);

      // result: layout_height=wrap_content layout_width=match_parent
      view = LayoutInflater.from(this).inflate(R.layout.red, null);
      parent.addView(view);

      // result: layout_height=100 layout_width=100
      view = LayoutInflater.from(this).inflate(R.layout.red, null);
      parent.addView(view, 100, 100);

      // result: layout_height=25dp layout_width=25dp
      // view=textView due to attachRoot=false
      view = LayoutInflater.from(this).inflate(R.layout.red, parent, false);
      parent.addView(view);

      // result: layout_height=25dp layout_width=25dp 
      // parent.addView not necessary as this is already done by attachRoot=true
      // view=root due to parent supplied as hierarchy root and attachRoot=true
      view = LayoutInflater.from(this).inflate(R.layout.red, parent, true);
    }
}

매개 변수 변형의 실제 결과는 코드에 문서화되어 있습니다.

시놉시스 :LayoutInflater 루트를 지정하지 않고 호출 하면 XML의 레이아웃 매개 변수를 무시하고 호출이 팽창합니다. 루트 동일하지와 부풀려를 호출 null하고하는 것은 attachRoot=true레이아웃 매개 변수를로드 않지만, 반환 (당신이 그것을 사용 발견 할 수있는 경우를 제외하고는로드 된 객체에 추가 레이아웃 변경을 방지 다시 루트 객체 findViewById()). 따라서 가장 많이 사용하려는 호출 규칙은 다음과 같습니다.

loadedView = LayoutInflater.from(context)
                .inflate(R.layout.layout_to_load, parent, false);

레이아웃 문제를 해결하려면 Layout Inspector 를 적극 권장합니다.


20
훌륭한 답변입니다. 3 년 동안 Android에서 일하고 세면서도 여전히 배울 점이 있습니다.
Reuben Scratton

안녕하세요 R.layout으로 팽창시키는 대신 Java 코드와 동일한 작업을 수행 할 수있는 방법이 있습니다. 레이아웃이 없기 때문에. Java 코드로 뷰를 만들었으며 동일한 뷰를 300 번 추가하고 싶습니다.
Raj

1
@andig : Activity은 서브 클래스이며 Context대답의 예는 범위에 있으므로이 대답 Activity을 위해 대신 getBaseContext()하는 this것으로 대체하는 것이 더 간단 합니다.
Marcin Orlowski

5
컨테이너의 layout_width 및 layout_height가 "match_parent"로 설정되어 있습니다. 그런 다음 주석에 "// result : layout_height = wrap_content layout_width = match_parent"라고 표시됩니다. sth가 누락 되었습니까?
Marian Paździoch

1
연구하고 결과를 공유해 주셔서 감사합니다! 또한, 나는 두 번째 Marian의 질문입니다.
LarsH

5

andig는 layout_params를 무시하는 LayoutInflater의 일반적인 이유는 루트가 지정되어 있지 않기 때문입니다. 많은 사람들은 루트로 널을 전달할 수 있다고 생각합니다. 이는 생성시 루트에 액세스 할 수없는 대화 상자와 같은 몇 가지 시나리오에서 허용됩니다. 그러나 좋은 규칙은 루트가 있으면 LayoutInflater에 제공하는 것입니다.

여기에서 확인할 수있는 자세한 블로그 게시물을 작성했습니다.

https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/


1
This is acceptable for a few scenarios such as a dialog그게 내가 필요한 전부
였어

0

위의 주요 답변에 추가하고 싶습니다.
하지만 그것을 시도했지만 recyclerView는
목표에 도달하기 위해 팽창 한 후 다음 줄을 추가 해야하는 화면에 모든 항목을 늘리기 시작했습니다.

itemLayoutView.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT));

나는 이미이 매개 변수를 xml로 추가했지만 제대로 작동하지 않았 으며이
줄로 모두 괜찮습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.