web-dev-qa-db-ja.com

Android:既存のレイアウトのカスタムビュー用の複数ビューの子

Androidでより複雑なカスタムビューを作成する必要があります。最終的なレイアウトは次のようになります。

<RelativeLayout>
  <SomeView />
  <SomeOtherView />
  <!-- maybe more layout stuff here later -->
  <LinearLayout>
    <!-- the children -->
  </LinearLayout>
</RelativeLayout>

ただし、XMLファイルでは、これを定義したいだけです(SomeView、SomeOtherViewなどを定義せずに)。

<MyCustomView>
  <!-- the children -->
</MyCustomView>

これはAndroidで可能ですか?もしそうなら:それを行う最もクリーンな方法は何でしょうか?私の頭に浮かんだ考えられる解決策は、「addView()メソッドをオーバーライドする」と「すべてのビューを削除して後で再度追加する」でしたが、どちらに進むべきかわかりません...

よろしくお願いします! :)

28
mreichelt

カスタムコンテナビューを作成することは絶対に可能であり、推奨されています。これは、Androidが複合コントロールと呼ぶものです。したがって:

_public class MyCustomView extends RelativeLayout {
    private LinearLayout mContentView;

    public MyCustomView(Context context) {
        this(context, null);
    }

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

    public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        //Inflate and attach your child XML
        LayoutInflater.from(context).inflate(R.layout.custom_layout, this);
        //Get a reference to the layout where you want children to be placed
        mContentView = (LinearLayout) findViewById(R.id.content);

        //Do any more custom init you would like to access children and do setup
    }

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        if(mContentView == null){
            super.addView(child, index, params);
        } else {
            //Forward these calls to the content view
            mContentView.addView(child, index, params);
        }
    }
}
_

addView()のバージョンは、必要に応じていくつでもオーバーライドできますが、最終的には、サンプルに配置したバージョンにコールバックされます。このメソッドだけをオーバーライドすると、フレームワークはXMLタグ内で見つかったすべての子を特定の子コンテナーに渡します。

次に、XMLを次のように変更します。

res/layout/custom_layout.xml

_<merge>
  <SomeView />
  <SomeOtherView />
  <!-- maybe more layout stuff here later -->
  <LinearLayout
      Android:id="@+id/content" />
</merge>
_

_<merge>_を使用する理由は、階層を単純化するためです。すべての子ビューは、RelativeLayoutであるカスタムクラスにアタッチされます。 _<merge>_を使用しない場合、すべての子に接続された別のRelativeLayoutに接続されたRelativeLayoutになってしまい、問題が発生する可能性があります。

HTH

51
Devunwired