Android-написание пользовательского (составного) компонента

Android-приложение, которое я в настоящее время разрабатываю, имеет основную деятельность, которая выросла довольно большой. Это в основном потому, что он содержит TabWidget С 3 вкладками. Каждая вкладка имеет довольно много компонентов. Деятельность должна контролировать все эти компоненты одновременно. Так что я думаю вы можете себе представить, что эта деятельность, как 20 полей (поле почти для каждого компонента). Также он содержит много логики (нажмите прослушиватели, логику для заполнения списков и т. д.).

что я обычно делаю в компоненте фреймворки должны разделить все на пользовательские компоненты. Тогда каждый пользовательский компонент будет нести четкую ответственность. Он будет содержать собственный набор компонентов и всю другую логику, связанную с этим компонентом.

я попытался выяснить, как это можно сделать, и я нашел что-то в документации Android, что они любят называть "составной контроль". (См.http://developer.android.com/guide/topics/ui/custom-components.html#compound и прокрутите до Раздел "составные элементы управления") я хотел бы создать такой компонент на основе XML-файла, определяющего структуру представления.

в документации написано:

обратите внимание, что так же, как с деятельностью, можно использовать либо декларативный (На основе XML) подход к созданию содержащиеся компоненты, или вы можете вложить их программно из кода.

Ну, это хорошие новости! Подход на основе XML-это именно то, что я хочу! Но он не говорит, как это сделать, за исключением того, что это"как с деятельностью"... Но то, что я делаю в деятельности, - это call 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!! Итак, теперь у нас есть избыточный LinearLayout между MyCompoundComponent и представления, которые ему действительно нужны.

может кто-нибудь, пожалуйста, предоставить мне лучший способ подойти к этому, избегая избыточного LinearLayout инстанцируется?

2 ответов


использовать слияние тег как ваш XML root

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

проверьте эту статью.


Я думаю, как вы должны это сделать, это использовать имя класса в качестве корневого элемента 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);
}

отказ от ответственности: я могу говорить полную чушь.