2013-12-18 4 views
1

Я хочу написать настраиваемое представление, для которого требуется некоторая кнопка с конкретным идентификатором (чтобы быть найденным по id), как в ListActivity android.R.id.list должен присутствовать, как я могу сделать то же самое с собственным собственным идентификатором?Как запросить представление с указанным идентификатором

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

+1

Я подозреваю, что вам нужно [написать обычное правило lint для этого] (http://tools.android.com/tips/lint-custom-rules). Пример на сайте, похоже, делает именно то, что вы хотите. – Ali

ответ

2

Просто сделайте то, что делает ListActivity.

Проверьте идентификатор в своем пользовательском представлении и выдайте исключение, если оно не существует в макете.

Отрывок из ListActivity Источник:

@Override 
public void onContentChanged() { 
    super.onContentChanged(); 
    View emptyView = findViewById(com.android.internal.R.id.empty); 
    mList = (ListView)findViewById(com.android.internal.R.id.list); 
    if (mList == null) { 
     throw new RuntimeException(
       "Your content must have a ListView whose id attribute is " + 
       "'android.R.id.list'"); 
    } 
+0

но как? как findViewById (R.id.button)? но что, если у меня нет этого атрибута кнопки? будет ли он работать, если я сделаю это в каком-нибудь бесполезном файле макета? –

+0

В вашем пользовательском представлении используйте findviewbyid, чтобы проверить, включено ли представление с ожидаемым идентификатором в макет. Выбросьте исключение, если вы его не найдете. (Если findviewbyid возвращает null) – Kuffs

+0

, но что бы вы дали findViewById в качестве параметра? обратите внимание, что я не знаю точное целочисленное значение id, просто суффикс R.id. –

2

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

Заявляет, что ваш пользовательский взгляд стиль-состояние с помощью пользовательских атрибутов в файле attrs.xml, как это:

<resources> 
    <declare-styleable name="MyView"> 
     <attr name="required_view_id" format="integer" /> 
    </declare-styleable> 
</resources> 

Вы можете обратиться к атрибуту из файла макета, как показано ниже. Обратите особое внимание на заголовок, где определено пространство имен «приложение». Вы можете использовать любое имя для своего пространства имен пользовательских атрибутов, но вы должны объявить его использовать любые ваши пользовательские атрибуты при определении представлений позже. Обратите внимание на пользовательский атрибут в MyView.

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

    <View 
     android:id="@+id/the_id_of_the_required_view" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 

    <com.full.package.to.MyView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     app:required_view_id="@id/the_id_of_the_required_view" /> 

</LinearLayout> 

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

public class MyView extends View { 

    private int mRequiredId; 

    public MyView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     checkForRequiredViewAttr(context, attrs); 
    } 

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     checkForRequiredViewAttr(context, attrs); 
    } 

    // Verify that the required id attribute was set 
    private void checkForRequiredViewAttr(Context context, AttributeSet attrs) { 
     TypedArray a = context.obtainStyledAttributes(attrs, 
       R.styleable.MyView, 0, 0); 
     mRequiredId = a.getResourceId(R.styleable.MyView_required_view_id, -1); 
     a.recycle(); 
     if (mRequiredId == -1) { 
      throw new RuntimeException("No required view id attribute was set"); 
     } 
    } 

    // This allows the custom view to be programmatically instantiated, so long as 
    // the required id is manually set before adding it to a layout 
    public void setRequiredId(int id) { 
     mRequiredId = id; 
    } 

    // Check for the existence of a view with the required id 
    @Override 
    protected void onAttachedToWindow() { 
     View root = getRootView(); 
     View requiredView = root.findViewById(mRequiredId); 
     if (requiredView == null) { 
      throw new RuntimeException(
        String.format("Cannot find view in layout with id of %s", mRequiredId)); 
     } 
     super.onAttachedToWindow(); 
    } 
} 

Использование onAttachedToWindow для проверки требуемого зрения не может быть достаточно для ваших целей. Например, это не предотвратит удаление требуемого вида. Поиск представления в макете - это не дешевая операция, особенно для сложных макетов, поэтому вы не должны постоянно ее проверять.

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