10

I have a CoordinatorLayout where I have my Button:

<android.support.design.widget.CoordinatorLayout
    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:layout_gravity="bottom|end">

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_marginBottom="16dp"
        android:layout_marginRight="16dp"
        android:src="@drawable/icon"
        app:fabSize="normal"/>

</android.support.design.widget.CoordinatorLayout>

And then I have the Activity xml where I include the Button:

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

    ...

        <include
            android:id="@+id/fabHere"
            layout="@layout/fab_here"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

</LinearLayout>

And here I have a fragment with Butterknife:

public class MyFragment extends Fragment {
....
@BindView(R.id.fab) FloatingActionButton fab;


    @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            view = inflater.inflate(R.layout.my_fragment, container, false);
            ButterKnife.bind(this, view);

            return view;
    }
...
 }

But if I start the App this appears:
java.lang.IllegalStateException: Required view 'fab' with ID 2131624072 for field 'fabHere' was not found. If this view is optional add '@Nullable' (fields) or '@Optional' (methods) annotation.

I tried to add the '@Nullable' and '@Optional' annotations, but it does not work

Sarah Pöhler
  • 550
  • 1
  • 7
  • 18

5 Answers5

16

Simply remove the id from the include tag and the binding will work, even for the fields in the included layout.

Michael
  • 430
  • 6
  • 20
  • Yes, I saw that somewhere too ! This is the right fix ! – Tobliug Mar 16 '18 at 11:23
  • It will solve your issue. Also, check if you wrote (pasted) correct layout. In my case, I copy-pasted from another activity and was wondering why does the Butterknife don't see my views :) – Kirill Karmazin Aug 23 '18 at 15:40
  • but if there are some views below the included view whose position is dependent on the id of included view, then what shall be done? – adi Sep 11 '19 at 12:26
  • If you have the option/ability I'd recommend switching to Kotlin, which would get rid of the need for Butterknife. Short of that, you could consider wrapping the include tag in another tag, that has an ID. – Michael Apr 20 '20 at 18:11
  • This issue was driving me nuts and such a simple fix. +1 – Panama Jack Dec 28 '22 at 05:13
5

The MainActivity,

public MainActivity extends AppCompatActivity {
    // 1. First, we declare the layout that was included as a View objects.
    @BindView( R.id.layout_1 ) View layout_1;
    @BindView( R.id.layout_2 ) View layout_2;

    @Override
    protected void onCreate( Bundle savedInstanceState ) {
        super.onCreate( savedInstanceState );
        setContentView( R.layout.activity_main );

        // 2. In here, we bind the included layouts
        ButterKnife.bind( this );

        // 4. Then, we create objects of the type of the IncludedLayout.
        //      In this example the layout reuse the same layout twice, so, there are two
        //      IncludedLayouts.
        IncludedLayout includedLayout_1 = new IncludedLayout();
        IncludedLayout includedLayout_2 = new IncludedLayout();

        // 5. We bind the elements of the included layouts.
        ButterKnife.bind( includedLayout_1, layout_1 );
        ButterKnife.bind( includedLayout_2, layout_2 );

        // 6. And, finally, we use them.
        includedLayout_1.displayed_text.setText(  "Hello" );
        includedLayout_2.displayed_text.setText(  "Hey!" );
    }

    // 3. We create a static class that will be an container of the elements
    //     of the included layout. In here we declare the components that
    //     hold this. In this example, there is only one TextView.
    static class IncludedLayout {
        @BindView( R.id.displayed_text ) TextView displayed_text;
    }
}

The XML of the MainActivity:

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <include android:id="@+id/layout_1" layout="@layout/included_layout" />
        <include android:id="@+id/layout_2" layout="@layout/included_layout" />
</LinearLayout>

The XML of the Included Layout:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/displayed_text"/>
</LinearLayout>

That's it!

Credit : Reference

Nishant Shah
  • 2,022
  • 22
  • 20
0

Please visit Butterknife issue

The author @JakeWharton says -

Put an ID on the <include> and bind it to an arbitrary View field for each one. 
Then create an object which binds the inner views

static class Something {
  @Bind(R.id.something) TextView somethingView;
}

You can then create multiple instances of that object
and call ButterKnife.bind(something1, include1) and 
ButterKnife.bind(something2, include2) and so on.

Consider also just making a custom view instead of using <include> which has 
proper APIs to get its children (or at least binds them to fields itself).
Neji
  • 6,591
  • 5
  • 43
  • 66
0

I Suggest you to use Data Binding Library provided by Google instead of Butterknife

GreenROBO
  • 4,725
  • 4
  • 23
  • 43
0

Since this question is quite old.

I am able to connect to my id in include tag nowadays (2019/Oct).

Try to do something like the original question before you go deeply.

@BindView(R.id.your_button_id_inside_include_tag) Button button;
Allen
  • 2,979
  • 1
  • 29
  • 34