부모의 크기를 기준으로 Android보기의 크기를 조정하는 방법


104

상위 레이아웃의 크기를 기준으로보기의 크기를 조정하려면 어떻게해야합니까? 예를 들어 RelativeLayout전체 화면을 채우는가 있고 ImageView, 전체 높이를 차지하고 너비의 1/2을 차지하는 하위보기 (예 :)를 원합니까?

나는 모든을 무시하려고했습니다 onMeasure, onLayout, onSizeChanged... 등 내가 작업에 가져올 수 없습니다


: 그것은 ConstraintLayout을 사용하여 해당 작업을 수행 할 수 있으며,이 확인 stackoverflow.com/questions/37318228/...
알리 별점

답변:


124

누군가가 여전히이 스레드를 읽고 있는지 여부는 알 수 없지만 Jeff의 솔루션은 (말 그대로) 절반 정도만 얻을 수 있습니다. 그의 onMeasure는 부모의 절반에 이미지의 절반을 표시합니다. 문제는 이전에 super.onMeasure를 호출 setMeasuredDimension하면 원래 크기를 기준으로 뷰의 모든 하위 항목을 측정 한 다음 setMeasuredDimension크기를 조정할 때 뷰를 반으로 자르는 것입니다.

대신 호출 할 필요 setMeasuredDimension(AN 된 onMeasure 재정에 필요한) 새로운를 제공 LayoutParams,보기에 대한 다음 호출 super.onMeasure. 당신의 기억 LayoutParams보기의 부모 유형,하지 뷰의 유형에서 파생됩니다.

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
   int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
   int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
   this.setMeasuredDimension(parentWidth/2, parentHeight);
   this.setLayoutParams(new *ParentLayoutType*.LayoutParams(parentWidth/2,parentHeight));
   super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

부모에게 문제가 생길 수있는 유일한 LayoutParams경우는 부모가 AbsoluteLayout(더 이상 사용되지 않지만 때로는 유용함) 경우입니다.


12
내 경험상 거의 작동하지 않습니다. fill / match_parent 또는 가중치가 호출 될 때. setMeasuredDimension 후에 measureChildren을 더 잘 호출합니다 (예 : MeasureSpec.makeMeasureSpec (newWidth, MeasureSpec.AT_MOST) 사용).
M. Schenk

1
않습니다 MeasureSpec.getSize(widthMeasureSpec)정말 올바른 parent's는 폭주는? 나를 위해 그것은 실제 너비에 매우 가깝지만 정확하지는 않은 임의의 너비를 반환합니다.
Konsumierer

1
@ M.Schenk가 있습니다. 가중치가 적용된 레이아웃 안에 VideoView가 있습니다. 너비가 화면 크기의 백분율이되고 가로 세로 비율을 유지해야합니다. 이것은 비디오를 늘이기 때문에 그렇게 wrap_content하지 않을 것입니다. Vic의 대답은이 시나리오에서 작동하지 않지만 @ M.Schenk의 의견은 작동합니다. 또한 추가 레이아웃 패스를 저장합니다. 가시성을위한 답변으로도 게시해야합니다.
dokkaebi

7
호출하지 것이다 super.onMeasure()단순히 오버라이드 (override)에 대한 이전 호출의 효과를 무효화 this.setMeasuredDimension()?
Spinner

1
@Spinner가 언급했듯이에 대한 호출 super.onMeasure()이 이전 계산을 재정의하지 않는 이유도 궁금 합니다.
jwir3

39

사용자 정의보기를 만들고 onMeasure () 메서드를 재정 의하여이 문제를 해결할 수 있습니다. xml의 ​​layout_width에 항상 "fill_parent"를 사용하는 경우 onMeasusre () 메서드에 전달되는 widthMeasureSpec 매개 변수에 부모의 너비가 포함되어야합니다.

public class MyCustomView extends TextView {

    public MyCustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
        this.setMeasuredDimension(parentWidth / 2, parentHeight);
    }
}   

XML은 다음과 같습니다.

<LinearLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <view
        class="com.company.MyCustomView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

2
@jeff => 왜 parentWidth / 2 ??
Saeed-rz 2013 년

6
@Leon_SFS : "폭을 전체 높이, 1/2": 문제는 그 요청
EdgarT

28

측정 치수를 직접 설정하지 않는 것이 가장 좋습니다. 실제로 부모와 자식보기간에 진행되는 약간의 협상이 있으며 모든 코드 를 다시 작성하고 싶지는 않습니다 .

하지만 할 수있는 일은 measureSpecs를 수정 한 다음 super를 호출하는 것입니다. 당신의 뷰는 그것이 부모로부터 수정 된 메시지를 받고 있다는 것을 결코 알지 못할 것이며 당신을 위해 모든 것을 처리 할 것입니다.

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
    int myWidth = (int) (parentHeight * 0.5);
    super.onMeasure(MeasureSpec.makeMeasureSpec(myWidth, MeasureSpec.EXACTLY), heightMeasureSpec);
}

16

XML에서 레이아웃과보기를 정의 할 때보기의 레이아웃 너비와 높이를 줄 바꿈 콘텐츠로 지정하거나 상위 항목을 채울 수 있습니다. 영역의 절반을 차지하는 것은 조금 더 어렵지만, 다른 절반에 원하는 것이 있다면 다음과 같이 할 수 있습니다.

   <LinearLayout android:layout_width="fill_parent"
                android:layout_height="fill_parent">
        <ImageView android:layout_height="fill_parent"
                 android:layout_width="0dp"
                 android:layout_weight="1"/>
        <ImageView android:layout_height="fill_parent"
                 android:layout_width="0dp"
                 android:layout_weight="1"/>
   </LinearLayout>

두 가지에 같은 무게를 주면 화면의 같은 비율을 차지하도록 늘어납니다. 레이아웃에 대한 자세한 내용 은 개발 문서를 참조하세요 .


나는 이것을 권장하지 않지만 ... 해킹으로 위의 접근 방식을 사용하는 경우 해당 뷰 중 하나를 "더미"로 만들고 android : visibility = "invisible"을 설정하여 영역의 절반을 채울 수 있습니다.
RickNotFred

면적의 절반 만 사용하는 목적은 무엇입니까? 나머지 절반에 아무것도 표시 할 계획입니까? 나머지 영역에서 수행하는 작업은 최상의 접근 방식을 알려줍니다
RickNotFred

이것은 확실히 # 1이어야합니다-XML에서 할 수 있다면 왜 자바에서할까요?
fandang

9

저는 Mayras XML 접근 방식 이 깔끔하게 올 수 있다고 믿습니다 . 그러나 weightSum을 설정하는 것만으로 하나의 뷰로 더 정확하게 만들 수 있습니다. 나는 이것을 더 이상 해킹이라고 부르지 않지만 내 의견으로는 가장 간단한 접근 방식입니다.

<LinearLayout android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:weightSum="1">
    <ImageView android:layout_height="fill_parent"
               android:layout_width="0dp"
               android:layout_weight="0.5"/>
</LinearLayout>

이와 같이 모든 가중치를 사용할 수 있습니다. 예를 들어 0.6은 버튼에 사용하는 가중치입니다.


3

이 시도

int parentWidth = ((parentViewType)childView.getParent()).getWidth();
int parentHeight = ((parentViewType)childView.getParent()).getHeight();

그런 다음 chileView의 매개 변수를 설정하기 위해 LinearLayout.LayoutParams를 사용할 수 있습니다.

LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(childWidth,childLength);
childView.setLayoutParams(params);

2

이제 PercentRelativeLayout을 사용할 수 있습니다. 팔! 문제 해결됨.


2
PercentRelativeLayout은 API 레벨 26.0.0-beta1에서 더 이상 사용되지 않습니다.
dzikovskyy

"API 수준"이란 무엇을 의미합니까? 라이브러리 버전 번호를 의미합니까? PRL은 지원 라이브러리에 있으며 API 수준이 없습니다.
androidguy jul.

API 수준이란 Android 버전을 의미합니다. 여기에서 정보 developer.android.com/reference/android/support/percent/… . API 수준에 대한 자세한 정보는 여기 developer.android.com/guide/topics/manifest/...
dzikovskyy

어떤 이유로 버전 26.0.0 이상이 필요한 경우가 아니면이 클래스를 계속 사용할 수 있습니다.
androidguy

1

Roman, Java 코드 (ViewGroup 하위 항목)로 레이아웃을 수행하려는 경우 가능합니다. 트릭은 onMeasure 및 onLayout 메서드를 모두 구현해야한다는 것입니다. onMeasure가 먼저 호출되고 거기에서 하위 뷰를 "측정"해야합니다 (효과적으로 원하는 값으로 크기 조정). onLayout 호출에서 크기를 다시 조정해야합니다. 이 시퀀스를 수행하지 않거나 onMeasure 코드 끝에서 setMeasuredDimension () 호출에 실패하면 결과를 얻을 수 없습니다. 왜 이것이 그렇게 복잡하고 깨지기 쉬운 방식으로 설계 되었는가?


1

다른 쪽이 비어있는 경우. 가장 간단한 방법은 빈 뷰 (예 : 선형 레이아웃)를 추가 한 다음 두 뷰의 너비를 fill_parent로 설정하고 두 뷰의 가중치를 모두 1로 설정하는 것입니다.

이것은 LinearLayout에서 작동합니다 ...


0

다음과 같습니다.

<RelativeLayout 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="com.company.myapp.ActivityOrFragment"
    android:id="@+id/activity_or_fragment">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/linearLayoutFirst"
    android:weightSum="100">   <!-- Overall weights sum of children elements -->

    <Spinner
        android:layout_width="0dp"   <!-- It's 0dp because is determined by android:layout_weight -->
        android:layout_weight="50"
        android:layout_height="wrap_content"
        android:id="@+id/spinner" />

</LinearLayout>


<LinearLayout
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:layout_below="@+id/linearLayoutFirst"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:id="@+id/linearLayoutSecond">

    <EditText
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:layout_weight="75"
        android:inputType="numberDecimal"
        android:id="@+id/input" />

    <TextView
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        android:layout_weight="25"
        android:id="@+id/result"/>

</LinearLayout>
</RelativeLayout>

-1

나는 오랫동안이 질문에 어려움을 겪어 왔으며 부모의 두 번째 자식 인 DrawerLayout의 서랍 너비를 변경하고 싶습니다. 최근에 알아 냈지만 더 좋은 아이디어가 있는지 모르겠습니다.

override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
    super.onLayout(changed, l, t, r, b)
    (getChildAt(1).layoutParams as LayoutParams).width = measuredWidth/2
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.