2012-06-29 3 views
22

я делать сложную планировку, и я с помощью «включить» для моего пользовательского компонента, как этотВключить макет с пользовательскими атрибутами

<include layout="@layout/topbar"/> 

И topbar определен следующим образом:

<?xml version="1.0" encoding="utf-8"?> 
<my.package.TopBarLayout 
... a lot of code 

Теперь я хочу пройти мои настраиваемые атрибуты к «topbar», как это

<include layout="@layout/topbar" txt:trName="@string/contacts"/> 

Но у меня нет результата. Я понял из that page, что я не могу установить никаких атрибутов, но id, height и width.

Итак, как я могу передать свои настраиваемые атрибуты для включения, и как я могу заставить его работать?

+0

[Связывание данных не поддержка включает в себя как прямой дочерний элемент слияния.] (https://developer.android.com/topic/libraries/data-binding/index.html) – samosaris

ответ

31

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

Для начала вам необходимо включить Data Binding.

Затем добавить привязку данных к раскладке вы хотите включить:

<?xml version="1.0" encoding="utf-8"?> 
<layout xmlns:android="http://schemas.android.com/apk/res/android"> 
<data> 
    <variable name="title" type="java.lang.String"/> 
</data> 
<RelativeLayout xmlns:app="http://schemas.android.com/apk/res-auto" 
      android:id="@+id/screen_header" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_gravity="top" 
      android:gravity="center"> 

... 

<TextView 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_centerInParent="true" 
      android:textSize="20sp" 
      android:textStyle="bold" 
      android:text="@{title}"/> 

... 

</RelativeLayout> 
</layout> 

Наконец, передать переменную из основного макета к прилагаемому макет, как это:

... 
xmlns:app="http://schemas.android.com/apk/res-auto" 
... 
<include layout="@layout/included_layout" 
      android:id="@+id/title" 
      app:title="@{@string/title}"/> 
... 
+1

он работает? как вы можете связываться с xml? Когда я пытаюсь это, в тексте не было текста. – Andrzej

+0

@Andrzej Это работает для меня, поэтому вы должны что-то упускать, возможно, что-то, что я забыл добавить к моему ответу. Можете ли вы опубликовать свой код, чтобы я попытался выяснить, что случилось? –

+0

Это действительно работает, но действительно делает вас зависимым от привязки данных, что может быть сложнее отлаживать, чем подход пользовательского вида, описанный в другом ответе (который в большей степени зависит от проверки времени компиляции). – sapht

0

Вы должны включить в свой корневой элемент xml свое собственное пространство имен. Если имя пакета com.example.test ваш XML shold быть что-то вроде этого:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:txt="http://schemas.android.com/apk/res/com.example.test" /> 

Хороший учебник: http://blog.infidian.com/2008/05/02/android-tutorial-42-passing-custom-variables-via-xml-resource-files/

+3

Спасибо, но я это знаю, и пространство имен включено. Проблема - это атрибуты, не переданные компоненту –

5

К сожалению, единственное, что я могу внести свой вклад в том, что я не смог для установки пользовательских атрибутов в теге include и их перехода к включенному макету.

На данный момент это может быть невозможно.

9

Атрибуты, отличные от параметров макета, видимости или идентификатора в теге include, невозможно. Сюда входят пользовательские атрибуты.

Вы можете убедиться в этом, посмотрев на источник метода LayoutInflater.parseInclude, вокруг линии 705: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/view/LayoutInflater.java#640

инфлятор применяется только идентификатор и видимость атрибутов к прилагаемому макета.

0

У меня был такой же вопрос. После посещения этой теме, я закончил с использованием View «S setTag() методы прикрепить идентификационную информацию к каждому View во onCreate(), а затем getTag() методы, чтобы получить его позже.

1

Это не возможно использовать с пользовательскими атрибутами, или любые другие, чем те, указанных на странице API (через по крайней мере 5.0.0) атрибуты:

https://code.google.com/p/android/issues/detail?id=38023

http://grepcode.com/file/repo1.maven.org/maven2/org.robolectric/android-all/5.0.0_r2-robolectric-1/android/view/LayoutInflater.java

7

I столкнулся с этим вопросом сегодня. По какому-то стоит, я думаю, что есть прямолинейная работа вокруг. Вместо добавления атрибутов в тег include создайте собственное представление оболочки для включения и добавления атрибутов к этому. Затем сделайте включение из обертки. Попросите реализацию класса-оболочки извлечь атрибуты и передать их одному дочернему элементу, который является корневым представлением макета include.

Так, скажем, мы объявляем некоторые пользовательские атрибуты для обертки под названием SingleSettingWrapper, как это -

<declare-styleable name="SingleSettingWrapper"> 
    <attr name="labelText" format="string"/> 
</declare-styleable> 

Затем мы создаем два пользовательские просмотр классов - один для оболочки (SingleSettingWrapper) и один для ребенка (SingleSettingChild), которые будут включены в состав -

<!-- You will never end up including this wrapper - it will be pasted where ever you wanted to include. But since the bulk of the XML is in the child, that's ok --> 
<com.something.SingleSettingWrapper 
    android:id="@+id/wrapper" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    custom:labelText="@string/my_label_string"> 

    <!-- Include the child layout --> 
    <include layout="@layout/setting_single_item"/> 

</com.something.SingleSettingWrapper> 

Для ребенка мы можем поставить любую сложную планировку там, которую мы хотим. Я просто положить что-то основное, но на самом деле вы можете включить все, -

<com.something.SingleSettingItem 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="vertical"> 
    <RelativeLayout > 
     <!-- add whatever custom stuff here --> 
     <!-- in this example there would be a text view for the label and maybe a bunch of other stuff --> 
     <!-- blah blah blah --> 
    </RelativeLayout> 
</com.something.SingleSettingItem> 

Для обертки (это ключ), мы читаем все наши пользовательские атрибуты в конструкторе. Затем мы переопределяем onViewAdded() и передаем эти пользовательские атрибуты нашему дочернему элементу.

public class SingleSettingWrapper extends FrameLayout 
{ 
    private String mLabel; 

    public SingleSettingWrapper(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 

     TypedArray a = context.getTheme().obtainStyledAttributes(attrs, 
                  R.styleable.SingleSettingWrapper, 
                  0, 0); 

     mLabel = a.getString(R.styleable.SingleSettingWrapper_labelText); 
     a.recycle(); 
    } 

    public void onViewAdded(View child) 
    { 
     super.onViewAdded(child); 
     if (!(child instanceof SingleSettingItem)) 
      return; 

     ((TextView)child.findViewById(R.id.setting_single_label)).setText(mLabel); 
     /* 
     Or, alternatively, call a custom method on the child implementation - 
     ((SingleSettingItem)child)setLabel(mLabel); 
     */ 
    } 
} 

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

public class SingleSettingItem extends LinearLayout 
{ 
    public SingleSettingItem(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
    } 

    public void setLabel(String l) 
    { 
     // set the string into the resource here if desired, for example 
    } 
} 

В конце концов, каждый из файлов XML, где вы хотели <include> макет будет содержать около 7 строк XML для обертки + включает вместо одного включить, что вы хотели, но если включенное представление содержит сотни строк, которые вы по-прежнему лучше. Например,

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:custom="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="vertical" > 

    <!-- this is the beginning of your custom attribute include --> 
    <com.something.SingleSettingWrapper 
     android:id="@+id/my_wrapper" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     custom:labelText="@string/auto_lock_heading"> 
     <include layout="@layout/setting_single_item"/> 
    </com.something.SingleSettingWrapper> 
    <!-- this is the end of your custom attribute include --> 
</LinearLayout> 

На практике это работает очень хорошо и относительно просто настроить. Надеюсь, это поможет кому-то.

+0

Немного сложнее с обертыванием вида на просмотр –

Смежные вопросы