Android-사용자 정의 (복합) 구성 요소 작성


132

현재 개발중인 Android 앱에는 주요 활동이 상당히 커졌습니다. 주로 TabWidget3 개의 탭이 포함되어 있기 때문 입니다. 각 탭에는 몇 가지 구성 요소가 있습니다. 활동은 모든 구성 요소를 한 번에 제어해야합니다. 이 액티비티에 20 개의 필드 (거의 모든 구성 요소에 대한 필드)가 있다고 상상할 수 있습니다. 또한 많은 로직 (클릭 리스너, 목록을 채우는 로직 등)이 포함되어 있습니다.

구성 요소 기반 프레임 워크에서 일반적으로하는 일은 모든 것을 사용자 지정 구성 요소로 나누는 것입니다. 그러면 각 사용자 지정 구성 요소에 명확한 책임이 있습니다. 자체 구성 요소 집합과 해당 구성 요소와 관련된 다른 모든 논리를 포함합니다.

나는 이것을 어떻게 할 수 있는지 알아 내려고 노력했고, 안드로이드 문서에서 그들이 "복합 제어"라고 부르는 것을 발견했다. ( http://developer.android.com/guide/topics/ui/custom-components.html#compound를 참조 하고 "Compound Controls"섹션으로 스크롤하십시오.) 뷰 구조.

설명서에서 다음과 같이 말합니다.

액티비티와 마찬가지로 선언적 (XML 기반) 접근 방식을 사용하여 포함 된 구성 요소를 만들거나 코드에서 프로그래밍 방식으로 중첩 할 수 있습니다.

좋은 소식입니다! XML 기반 접근 방식은 내가 원하는 것입니다! 그러나 "액티비티와 같은 것"을 제외하고는 어떻게 해야하는지 말하지 않습니다. 그러나 액티비티에서 내가하는 일은 setContentView(...)XML에서 뷰를 부풀려 야한다는 것입니다. 서브 클래스와 같은 경우에는이 메소드를 사용할 수 없습니다 LinearLayout.

그래서 다음과 같이 XML을 수동으로 부풀 리려고했습니다.

public class MyCompoundComponent extends LinearLayout {

    public MyCompoundComponent(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.my_layout, this);
    }
}

내가로드하는 XML LinearLayout이 루트 요소로 선언 되었다는 사실을 제외하고는 작동합니다 . 이로 인해 팽창 된 LinearLayout어린이가 MyCompoundComponent이미 그 자체입니다 LinearLayout! 이제 우리는 MyCompoundComponent실제로 필요한 뷰와 뷰 사이에 여분의 LinearLayout을 갖습니다 .

누군가 중복 된 LinearLayout인스턴스화를 피하면서 더 나은 방법으로 접근 할 수 있습니까 ?


14
나는 무언가를 배우는 질문을 좋아합니다. 감사.
Jeremy Logan

5
나는 최근에 이것에 대해 블로그 항목을 썼습니다 : blog.jteam.nl/2009/10/08/exploring-the-world-of-android-part-3
톰 반 Zummeren

답변:


101

사용 병합 하여 XML 루트로 태그를

<merge xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Your Layout -->
</merge>

이 기사를 확인하십시오.


10
대단히 감사합니다! 바로 내가 찾던 것입니다. 그러한 긴 질문이 어떻게 짧은 대답을 가질 수 있는지 놀랍습니다. 우수한!
Tom van Zummeren

이 병합 레이아웃을 가로로 포함시키는 것은 어떻습니까?
Kostadin

2
@Timmmm hahahaha 비주얼 에디터가 존재하기 훨씬 전에이 질문을했습니다 :)
Tom van Zummeren

0

나는 당신이해야 할 방식으로 클래스 이름을 XML 루트 요소로 사용한다고 생각합니다.

<com.example.views.MyView xmlns:....
       android:orientation="vertical" etc.>
    <TextView android:id="@+id/text" ... />
</com.example.views.MyView>

그런 다음 클래스를 사용하려는 레이아웃에서 파생시킵니다. 이 방법을 사용하는 경우 레이아웃 팽창기를 사용 하지 않습니다 .

public class MyView extends LinearLayout
{
    public ConversationListItem(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }
    public ConversationListItem(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }


    public void setData(String text)
    {
        mTextView.setText(text);
    }

    private TextView mTextView;

    @Override
    protected void onFinishInflate()
    {
        super.onFinishInflate();

        mTextView = (TextView)findViewById(R.id.text);
    }
}

그런 다음 정상적으로 XML 레이아웃에서 뷰를 사용할 수 있습니다. 프로그래밍 방식으로 뷰를 만들려면 직접 팽창시켜야합니다.

MyView v = (MyView)inflater.inflate(R.layout.my_view, parent, false);

불행히도 v = new MyView(context)중첩 된 레이아웃 문제를 해결할 수있는 방법 이 없기 때문에이 작업을 수행 할 수 없으므로 실제로 완전한 솔루션은 아닙니다. MyView조금 더 멋지게 만들기 위해 다음 과 같은 방법을 추가 할 수 있습니다 .

public static MyView create(Context context)
{
    return (MyView)LayoutInflater.fromContext(context).inflate(R.layout.my_view, null, false);
}

면책 조항 : 나는 완전한 볼록을 이야기 할 수 있습니다.


감사! 나는이 답변도 옳다고 생각합니다.) 그러나 3 년 전에이 질문을했을 때 "병합"도 속임수를 사용했습니다!
Tom van Zummeren

8
그리고 누군가가 나타나서 시도 단지와 레이아웃 곳에서 사용자 정의보기를 사용하는 <com.example.views.MyView />당신 setDataonFinishInflate통화 NPEs을 던지기 시작하고, 그 이유를 모르겠어요.
크리스토퍼 페리

여기서 트릭은 사용자 정의보기를 사용하고 생성자에서 병합 태그를 루트로 사용하는 레이아웃을 팽창시키는 것입니다. 이제 XML로 사용하거나 새로 업데이트하여 사용할 수 있습니다. 모든 기반이 다루어지며, 이는 질문 / 허용 된 답변이 함께하는 것입니다. 그러나 당신이 할 수없는 것은 더 이상 레이아웃을 직접 참조하는 것입니다. 이제는 커스텀 컨트롤이 '소유'했으며 생성자에서만 사용해야합니다. 그러나이 접근 방식을 사용하는 경우 어쨌든 다른 곳에서 사용해야하는 이유는 무엇입니까? 당신은하지 않을 것입니다.
Mark A. Donohoe
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.