Лучший способ сделать это гибким способом является использование пользовательского атрибута. Он позволяет любому 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 для проверки требуемого зрения не может быть достаточно для ваших целей. Например, это не предотвратит удаление требуемого вида. Поиск представления в макете - это не дешевая операция, особенно для сложных макетов, поэтому вы не должны постоянно ее проверять.
Я подозреваю, что вам нужно [написать обычное правило lint для этого] (http://tools.android.com/tips/lint-custom-rules). Пример на сайте, похоже, делает именно то, что вы хотите. – Ali