IT Share you

Custom ViewGroup 내에서 XML-Layout-File을 올바르게 팽창시키는 방법은 무엇입니까?

shareyou 2020. 12. 11. 20:55
반응형

Custom ViewGroup 내에서 XML-Layout-File을 올바르게 팽창시키는 방법은 무엇입니까?


사용자 정의 ViewGroup 클래스에서 XML-Layout-File을 팽창시키고 싶습니다. 문제는 빈 화면 만 생성한다는 것입니다. 활동 클래스에서 동일한 작업을 수행하면 정상적으로 작동합니다. 다음은 내 간단한 XML 레이아웃 파일입니다.

shownumberlayout.xml:

    <RelativeLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent"
        android:background="#FFFFFF" 
        android:id="@+id/layoutForNumber">

        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:id="@+id/tvNumber"
            android:layout_centerHorizontal="true" 
            android:textColor="#000000" 
            android:text="Test" 
            android:layout_centerVertical="true" 
            android:textSize="30dip">
        </TextView>

    </RelativeLayout>

다음 작업 버전은 팽창한다 shownumberlayout.xml활동에 ShowNumber:

ShowNumber.class

public class ShowNumber extends Activity {
    /** Called when the activity is first created. */

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        ViewGroup vg = (ViewGroup) inflater.inflate(R.layout.shownumberlayout, null);
        setContentView(vg);
    }
}

중앙에 검은 색 텍스트 "테스트"가있는 흰색 배경이 표시됩니다.

이제 Custom ViewGroup-Class 에서 xml을 확장하는 버전 :

ViewGroup.class
public class ViewNumber extends ViewGroup {

    private LayoutInflater inflater;

    public ViewNumber(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        initView(context);
    }

    public ViewNumber(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
        initView(context);
    }

    public ViewNumber(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub
        initView(context);
    }

    private void initView(Context context){
        inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.shownumberlayout, null);  
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // TODO Auto-generated method stub
    }

}

ShowNumber.class public class ShowNumber extends Activity {/ ** 활동이 처음 생성 될 때 호출됩니다. * /

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ViewGroup vg = new ViewNumber(this); 
    setContentView(vg);
}

}

나는 기본적 으로이 답변과 같이 설명했습니다. 이것은 단지 빈 검은 화면을 생성합니다. 내가 뭘 잘못하고 있니?

업데이트 1

@Konstantin 변경 사항을 적용했지만 여전히 빈 화면이 표시되며 자녀 수를 얻기위한 로그 출력도 만들었습니다. XML-Layout-File에 Textview를 하나 더 추가하더라도 항상 1로 유지됩니다. 변경 전에는 항상 0으로 유지됩니다.

public class ViewNumber extends RelativeLayout {
...
private void initView(Context context){
        //inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        //inflater.inflate(R.layout.shownumberlayout, null);
        View.inflate(context, R.layout.shownumberlayout,this); 
        Log.v("ViewNumber", "Number of Child: " + this.getChildCount());//output is 1,before it remains 0
    }
...
}

@Sankar Konstantin에서 변경 한 후 Logcat입니다.

12-16 09:24:23.606: DEBUG/AndroidRuntime(8951): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<
12-16 09:24:23.606: DEBUG/AndroidRuntime(8951): CheckJNI is OFF
12-16 09:24:23.606: DEBUG/dalvikvm(8951): creating instr width table
12-16 09:24:23.656: DEBUG/AndroidRuntime(8951): --- registering native functions ---
12-16 09:24:23.916: DEBUG/AndroidRuntime(8951): Shutting down VM
12-16 09:24:23.916: DEBUG/dalvikvm(8951): Debugger has detached; object registry had 1 entries
12-16 09:24:23.916: INFO/AndroidRuntime(8951): NOTE: attach of thread 'Binder Thread #3' failed
12-16 09:24:24.076: DEBUG/AndroidRuntime(8960): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<
12-16 09:24:24.076: DEBUG/AndroidRuntime(8960): CheckJNI is OFF
12-16 09:24:24.076: DEBUG/dalvikvm(8960): creating instr width table
12-16 09:24:24.126: DEBUG/AndroidRuntime(8960): --- registering native functions ---
12-16 09:24:24.376: INFO/ActivityManager(78): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=org.customview.harold/.ShowNumber }
12-16 09:24:24.426: DEBUG/AndroidRuntime(8960): Shutting down VM
12-16 09:24:24.426: DEBUG/jdwp(8960): Got wake-up signal, bailing out of select
12-16 09:24:24.426: DEBUG/dalvikvm(8960): Debugger has detached; object registry had 1 entries
12-16 09:24:24.456: INFO/AndroidRuntime(8960): NOTE: attach of thread 'Binder Thread #3' failed
12-16 09:24:24.456: VERBOSE/ViewNumber(8923): Number of Child: 1
12-16 09:24:24.496: VERBOSE/RenderScript_jni(164): surfaceDestroyed
12-16 09:24:24.526: INFO/ActivityManager(78): Displayed activity org.customview.harold/.ShowNumber: 104 ms (total 104 ms)
12-16 09:24:24.576: DEBUG/dalvikvm(158): GC_FOR_MALLOC freed 10631 objects / 526248 bytes in 52ms
12-16 09:24:34.606: DEBUG/dalvikvm(164): GC_EXPLICIT freed 1776 objects / 106960 bytes in 91ms

업데이트 2

콘텐츠가 마침내 올바르게 표시됩니다. 빠진 것은 RelativeLayout-Sublcass에서 Method onLayout( Franco 덕분에 ) 를 재정의하는 것이 었 습니다.

public class ViewNumber extends RelativeLayout {
...

    @Override
            protected void onLayout(boolean changed, int l, int t, int r, int b) {
                // TODO Auto-generated method stub
                for(int i = 0 ; i < getChildCount() ; i++){
                    getChildAt(i).layout(l, t, r, b);
                }
            }
...
}

참고 : 나중에 Method를 재정의해야 onMeasurement()하지만 현재 콘텐츠도 재정의하지 않고 올바르게 표시됩니다.

이제 방법에 대한 솔루션 initView에서 프랑코 센터에서 텍스트 뷰를 정렬되지 않지만, 상단에 둔다는 코너를 떠났다. Konstantin 의 솔루션 은 뷰의 중앙에 올바르게 배치합니다.

public class ViewNumber extends RelativeLayout {
...
private void initView(Context context){
        View.inflate(context, R.layout.shownumberlayout,this); 
    }
...
}

이거 해봤 어?

private void initView(Context context){
        inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        this.addView(inflater.inflate(R.layout.shownumberlayout, null));  
    }

편집 : 빠르게 응답합니다 ... ViewGroup은 레이아웃 방법에서 다음을 시도해보십시오.

        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            // TODO Auto-generated method stub
            for(int i = 0 ; i < getChildCount() ; i++){
                getChildAt(i).layout(l, t, r, b);
            }
        }

이 답변에서 무슨 일이 일어나고 있는지 모르겠습니다. onLayout수동으로 전화 하는 것이 약간 미친 것 같습니다.

The LayoutInflater.inflate function is rather straight forward. If you're using the one that accepts the 3rd boolean argument (attachToRoot) and it's true, it will add the views from your XML to your parent view (the 2nd argument). If you're using the one that accepts only 2 arguments, it will pass true to attachToRoot by default if you provide a parent that isn't null.

In any case, most of the mess you're experiencing is because the views from your XML are added to your custom view. Since your XML has a RelativeLayout root and your custom view is also a RelativeLayout - you're getting a relative layout inside a relative layout.

This is probably not what you want.

The answer given by Konstantin makes sense, but you're wasting a view because you're placing a RelativeLayout inside a FrameLayout. Since Android can't hold too many nested views, it's a good idea to optimize and not add this unnecessary FrameLayout.

I suggest keeping your custom view as RelativeLayout and changing your XML root to <merge>. Then use the inflate form which adds the XML views to your parent - like View.inflate(context,int,this)

The purpose of the <merge> tag is to skip the root node in the XML.. look it up.


Your layout is inflated nowhere.. make your ViewNumber extend FrameLayout and inflate into it:

public class ViewNumber extends FrameLayout {

    public ViewNumber(Context context) {
        super(context);
        initView(context);
    }

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

    public ViewNumber(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView(context);
    }

    private void initView(Context context){
        View.inflate(context, R.layout.shownumberlayout, this);  //correct way to inflate..
    }
}

UPD: Also you do not need to override onLayout method, that looks very incorrect.. at least call super.onLayout() on the very start:

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
}

Try this one:

 LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
 inflater.inflate( R.layout.login_view_layout, null );

Overriding onLayout is necessary.when you create a object of ViewNumber(ViewGroup vg = new ViewNumber(this)),it is like inflating xml below:

<ViewNumber
           I have no child :(
</ViewNumber>

so if you don't override onLayout,ViewNumber's onLayout can't find any child,then it will be blank.

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
}

after overriding,it will use the onLayout method of ViewNumber's parent, if your codes is:

public class ViewNumber extends RelativeLayout {
...
private void initView(Context context){
        View.inflate(context, R.layout.shownumberlayout,this); 
    }
...
}

then it's like inflating xml below

  <RelativeLayout
    <RelativeLayout 
            your xml file
                   />
  </RelativeLayout>

there is one more RelativeLayout.To sovle this,you may write:

public class ViewNumber extends RelativeLayout {
...
private void initView(Context context){
        inflater.inflate( R.layout.login_view_layout, null );
              //change (..,this) to (..,null)
    }
...
}

However, something unexpected will happen.android:layout_xxx=".."of your xml file may change(this is why your text is put in the top left corner). To learn more and a better solution,you can see talkol' answer and fgeorgiew's comment under it :)

참고URL : https://stackoverflow.com/questions/4448779/how-to-inflate-xml-layout-file-correctly-inside-custom-viewgroup

반응형