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

StackOverflow https://stackoverflow.com/questions/1476371

  •  16-09-2019
  •  | 
  •  

Вопрос

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

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

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

В документации сказано:

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

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

Это было полезно?

Решение

Использование слияние тег в качестве вашего XML-корня

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

Отказ от ответственности:Возможно, я несу полную чушь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top