2

RelativeLayout を継承する他の複合コントロール (BaseControl) のベースとして機能するカスタム コントロールがあります。この BaseControl は、各コントロールの XML の拡張を簡素化し、その後それらを初期化することを目的としています。すべてはコンストラクターで行われます。

abstract class BaseControl extends RelativeLayout {

    public BaseControl(Context context) {
        super(context);
        this.baseInitializeControl(context, null);
    }

    public BaseControl(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.baseInitializeControl(context, attrs);
    }

    public BaseControl(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.baseInitializeControl(context, attrs);
    }

    private void baseInitializeControl(Context context, AttributeSet attrs) {
        int layoutId = this.getControlLayoutId();
        if(layoutId != 0) {
            LayoutInflater inflater = LayoutInflater.from(getContext());
            inflater.inflate(layoutId, this);
        }

        this.initializeControl(context, attrs);
    }

    protected abstract int getControlLayoutId();
    protected abstract void initializeControl(Context context, AttributeSet attrs);
}

実際の問題は、OnItemClickedListener をコントロールの内部 ListView に設定したのに、どのクリックにも応答しないことです。この問題は、BaseControl クラスを抽象化する前にはありませんでした。onFinishInflate で ListView の setOnItemClickedListener メソッドを呼び出して、この問題を解決しました。

したがって、CustomList1 と CustomList2 があり、どちらも BaseControl を継承しています。CustomList1 には次のものがあります。

@Override
protected int getControlLayoutId() {
    return R.layout.custom_list_1;
}

@Override
protected void initializeControl(Context context, AttributeSet attrs) {
    this.mListView = this.findTypedViewById(R.id.listView);

    CustomAdapter adapter = new CustomAdapter(getContext());
    this.mListView.setAdapter(adapter);
}

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

    this.mListView.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parentView, View childView, int position, long id) {
            HistoryGroupList.this.onListItemClicked(parentView, childView, position, id);
        }
    });
}

private void onListItemClicked(AdapterView<?> parentView, View childView, int position, long id) {
    CustomAdapter adapter = (CustomAdapter) this.mListView.getAdapter();
    CustomData data = adapter.getItem(position);

    CustomList2 list = new CustomList2(getContext(), data); // CustomList2 should query more data here.

    this.addView(list); // The new View is added in front of the current one
}

これまでのところ、最初の CustomList はクリックされた項目に応答し、新しいコントロール (2 つ目のリスト ビューを含む) を作成して前面に表示します。

2 番目のコントロール (CustomList2) はほぼ同じコードで、getControlLayoutId() で異なる ID を返すだけで、onListItemClicked(...) で Toast を表示し、コンストラクターの 2 番目のパラメーターを使用して別のアダプターを作成します。問題は、この 2 番目のコントロールが onFinishInflate() イベントを実行していないことですが、BaseControl で xml をインフレートしています。このコントロールを XML タグとして別のレイアウトに追加すると、onFinishInflate() メソッドが正常に実行されます。

このメソッドが実行されていない理由を知っていますか? あるいは、setOnItemClickedListener メソッドで問題を解決するための回避策かもしれません。

ありがとう!マイク

4

2 に答える 2

0

リスナーを作成した後、super.onFinishInflate() を呼び出してみてください。奇妙に思えますが、過去の経験から気付いたのですが、スーパーコールの後にメソッドが終了することがあります。

@Override
protected void onFinishInflate() {
    this.mListView.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parentView, View childView, int position, long id) {
            HistoryGroupList.this.onListItemClicked(parentView, childView, position, id);
        }
    });

    super.onFinishInflate();    
}
于 2012-08-08T18:44:30.960 に答える