web-dev-qa-db-ja.com

Android-カスタム(複合)コンポーネントの記述

Android私が現在開発中のアプリは、かなり大きくなった主なアクティビティを持っています。これは、主に3つのタブを持つTabWidgetが含まれているためです。各タブにはかなりの数がありますアクティビティは、これらすべてのコンポーネントを一度に制御する必要があるため、このアクティビティには20個のフィールド(ほぼすべてのコンポーネントのフィールド)があり、多くのロジック(クリックリスナー、入力するロジック)が含まれていると想像できます。リストなど)。

コンポーネントベースのフレームワークで私が通常行うことは、すべてをカスタムコンポーネントに分割することです。その場合、各カスタムコンポーネントには明確な責任があります。独自のコンポーネントセットと、そのコンポーネントに関連する他のすべてのロジックが含まれます。

私はこれがどのように行われるかを理解しようとしましたが、Androidドキュメントで「化合物コントロール」と呼ぶのが好きなものを見つけました。( http:// developer .Android.com/guide/topics/ui/custom-components.html#compound そして「Compound Controls」セクションまでスクロールします)ビュー構造を定義するXMLファイルに基づいてこのようなコンポーネントを作成したいと思います。

ドキュメントには次のように書かれています:

アクティビティの場合と同様に、宣言型(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がルート要素として宣言されているという事実を除いて機能します。これにより、膨張したLinearLayoutMyCompoundComponentの子になり、それ自体は既にLinearLayout !!です!したがって、MyCompoundComponentと実際に必要なビューの間に冗長なLinearLayoutがあります。

誰かが私にこれにアプローチするより良い方法を提供してください、冗長なLinearLayoutのインスタンス化を避けることができますか?

131

mergeタグをXMLルートとして使用します

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

この記事を確認してください。

100
bhatt4982

あなたがそれをするはずの方法は、クラス名をXMLルート要素として使用することだと思います:

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

そして、使用するレイアウトからクラスを派生させます。このメソッドを使用している場合は、ここでdo n'tレイアウトインフレータを使用することに注意してください。

_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);
}
_

免責事項:私は完全なブロックを話しているかもしれません。

0
Timmmm