The best way to do this is in a flexible way is to use a custom attribute. It allows for any id to be the required id, but it also uses the dev tools to enforce that a valid id is used.
Declare that your custom view is style-able with a custom attribute in an attrs.xml file like this:
<resources>
<declare-styleable name="MyView">
<attr name="required_view_id" format="integer" />
</declare-styleable>
</resources>
You can then refer to the attribute from a layout file like below. Pay special attention to the header where the "app" namespace is defined. You can use any name you want for your custom attribute namespace, but you have to declare it to use any of your custom attributes when defining the views later. Note the custom attribute on 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>
Now you need to make sure this view is present in your custom view class. You can required that your custom attribute is set by overriding certain constructors. You'll also need to actually verify the presence of the required view at some point. Here's a rough idea:
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();
}
}
Using onAttachedToWindow to check for the required view may not be good enough for your purposes. It won't, for example, prevent the required view from being removed. Finding a view in a layout isn't a cheap operation, especially for complex layouts, so you shouldn't constantly check for it.