2015-04-25 2 views
0

я следующие макеты настройки (я опустил нерелевантные теги):Присвоение уникальных идентификаторов для потомков, включенных макетов

main.xml: 
<include 
    android:id="@+id/test1" 
    layout="@layout/mylayout" 
    /> 

<include 
    android:id="@+id/test2" 
    layout="@layout/mylayout" 
    /> 

mylayout.xml: 
<LinearLayout 
    <EditText 
     android:id="@+id/myedittext" 
    /> 
</LinearLayout> 

Заметьте, что этот конкретный пример принципиально упрощенно, мой фактический mylayout.xml сложен и содержит много подуровней и подсмотров с большим количеством идентификаторов, и я бы действительно не хотел встраивать его в main.xml.

Итак, я хочу повторно использовать макет mylayout.xml несколько раз. Вы можете заметить, что два EditTexts будут иметь дубликаты идентификаторов. Это, похоже, не проблема, поскольку я использую только R.id.myedittext для инициализации активности, чтобы найти виды с макетами test1 или test2, являющимися корнями для findViewById, и после этого я обращаюсь к этим файлам EditTexts напрямую через объекты View. Я нахожу очень удобным нож для масла для этого код выглядит следующим образом:

class LayoutHolder { 
    @InjectView(R.id.myedittext) 
    EditText editText; 
    // ... 
    static LayoutHolder create(View root) { 
     LayoutHolder holder = new LayoutHolder(); 
     ButterKnife.inject(holder, root); 
     return holder; 
    } 
} 

Проблемы возникли, когда я попытался изменить ориентацию экрана: оба EditTexts восстановлены в том же состоянии в связи с этим неуникальными идентификаторами. Хорошо, я думал, мне просто нужно определить некоторые идентификаторы в каталоге values, а затем использовать метод View.setId в EditTexts. Однако есть некоторые проблемы с этим подходом: в частности, мне придется устанавливать эти идентификаторы вручную и программно для каждого представления с идентификатором в пределах mylayout.xml. Более того, даже если я это сделаю, я не смогу получить доступ к этим подвидениям в некотором единообразном виде, так как у них будут разные идентификаторы (в частности, я не смогу сделать эти хорошие инъекции Butterknife).

Я пришел к некоторым другим способам разрешения этого вопроса, но они еще более сложны и уродливы. Итак, есть ли хороший и общий способ удовлетворить мои потребности? Интересно, что я не мог найти что-либо в Интернете, потому что повторное использование макетов во избежание дублирования кода (фактически, как бы то ни было, дублирование xml, но все равно) кажется совершенно естественным.

ответ

0

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

public class Utils { 

    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); 
    /** 
    * Generate a value suitable for use in setId(int}. 
    * This value will not collide with ID values generated at build time by aapt for R.id. 
    * 
    * @return a generated ID value 
    */ 
    private static int generateViewId() { 
     for (; ;) { 
      final int result = sNextGeneratedId.get(); 
      // aapt-generated IDs have the high byte nonzero; clamp to the range under that. 
      int newValue = result + 1; 
      if (newValue > 0x00FFFFFF) { 
       newValue = 1; // Roll over to 1, not 0. 
      } 
      if (sNextGeneratedId.compareAndSet(result, newValue)) { 
       return result; 
      } 
     } 
    } 

    @SuppressLint("NewApi") 
    public static int generateId() { 
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { 

      return generateViewId(); 
     } 
     else { 

      return View.generateViewId(); 
     } 
    } 
} 
0

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

@InjectView(R.id.mylayout, R.id.myedittext) 
Смежные вопросы