Butterknife: How to bind click event onto a view in a <include/> layout

Created on 15 Oct 2015  路  9Comments  路  Source: JakeWharton/butterknife

As we all know,if we want to use Butterknife to bind click event onto a normal view,we just need to declare the below method:

@onClick(R.id.yourview)
public void submit(){
     // do your things
}

But,how can I bind click event onto a view in a layout. and i have more than one some layout, so there are duplicated id

Most helpful comment

@humazed,

It's worked for me:

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.
        ButerKnife.bind( includedLayout_1, layout_1 );
        ButerKnife.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 MainAcitvity:

[...]

<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!

When i ran it, although the id was the same, because I reused it, the text in the TextView was different.

All 9 comments

Sorry for my previous comment. Miss understood the question.

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).

Finally, see #394 for a proposal to support this natively.

Thanks a lot.

can you please provide example.

@humazed,

It's worked for me:

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.
        ButerKnife.bind( includedLayout_1, layout_1 );
        ButerKnife.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 MainAcitvity:

[...]

<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!

When i ran it, although the id was the same, because I reused it, the text in the TextView was different.

Simpler method would be:

@BindView(R.id.layout1) View layout1;
@BindView(R.id.layout2) View layout2;

Then

TextView displayedText1 = ButterKnife.findById(layout1, R.id.display_text); TextView displayedText2 = ButterKnife.findById(layout1, R.id.display_text);

Src : http://jakewharton.github.io/butterknife/

@OnClick({ R.id.door1, R.id.door2, R.id.door3 })
public void pickDoor(DoorView door) {
if (door.hasPrizeBehind()) {
Toast.makeText(this, "You win!", LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Try again", LENGTH_SHORT).show();
}
}

Then How should do in fragment because am getting this issue "Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference"

i have done in my fragment page like this below

    mUnbinder = ButterKnife.bind(this, view);

     IncludedLayout includedLayout_1 = new IncludedLayout();
    IncludedLayout includedLayout_2 = new IncludedLayout();

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

navigation_activity.xml i put another xml file using include tag but i can not perform click event on that layout ui.

app:layout_width="match_parent"
app:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <FrameLayout
            app:id="@+id/main_container"
            app:layout_width="match_parent"
            app:layout_height="match_parent"
            app:layout_above="@+id/bottom_view" />

        <include
            app:id="@+id/bottom_view"
            layout="@layout/view_bottom_bar" />
    </RelativeLayout>

bottom.xml

LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#a0db"
android:baselineAligned="false"
android:orientation="vertical">

<ImageView
    android:id="@+id/filter_top_shadow"
    android:layout_width="match_parent"
    android:layout_height="2dp"
    android:background="@drawable/icon_top_shadow"
    android:contentDescription="@string/todo" />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:baselineAligned="false"
    android:orientation="horizontal">

    <RelativeLayout
        android:id="@+id/dashboard_layout_view"
        android:layout_width="1dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/layout_margin_quarter"
        android:layout_marginRight="@dimen/layout_margin_quarter"
        android:layout_weight="1.0"
        android:paddingBottom="@dimen/layout_margin_quarter"
        android:paddingTop="@dimen/layout_margin_quarter">

        <ImageView
            android:id="@+id/icon_dashboard"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_centerHorizontal="true"
            android:padding="2dp"
            android:src="@drawable/ic_dashboard"
            android:tint="@color/dark_gray_secondary"
            android:contentDescription="@string/todo" />

        <TextView
            android:id="@+id/dashboard"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/icon_dashboard"
            android:layout_centerHorizontal="true"
            android:gravity="center"
            android:text="@string/dashboard" />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/party_layout"
        android:layout_width="1dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/layout_margin_quarter"
        android:layout_marginRight="@dimen/layout_margin_quarter"
        android:layout_weight="1.0"
        android:paddingBottom="@dimen/layout_margin_quarter"
        android:paddingTop="@dimen/layout_margin_quarter">

        <ImageView
            android:id="@+id/icon_party"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_centerHorizontal="true"
            android:padding="2dp"
            android:src="@drawable/ic_customer_report"
            android:tint="@color/dark_gray_secondary"
            android:contentDescription="@string/todo" />

        <TextView
            android:id="@+id/party"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/icon_party"
            android:layout_centerHorizontal="true"
            android:gravity="center"
            android:text="@string/party" />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/item_layout"
        android:layout_width="1dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/layout_margin_quarter"
        android:layout_marginRight="@dimen/layout_margin_quarter"
        android:layout_weight="1.0"
        android:paddingBottom="@dimen/layout_margin_quarter"
        android:paddingTop="@dimen/layout_margin_quarter">

        <ImageView
            android:id="@+id/icon_items"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_centerHorizontal="true"
            android:padding="2dp"
            android:src="@drawable/ic_item_report"
            android:tint="@color/dark_gray_secondary"
            android:contentDescription="@string/todo" />

        <TextView
            android:id="@+id/items"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/icon_items"
            android:layout_centerHorizontal="true"
            android:gravity="center"
            android:text="@string/item" />
    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/report_layout"
        android:layout_width="1dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/layout_margin_quarter"
        android:layout_marginRight="@dimen/layout_margin_quarter"
        android:layout_weight="1.0"
        android:paddingBottom="@dimen/layout_margin_quarter"
        android:paddingTop="@dimen/layout_margin_quarter">

        <ImageView
            android:id="@+id/icon_report"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_centerHorizontal="true"
            android:padding="2dp"
            android:src="@drawable/ic_report_bottom"
            android:tint="@color/dark_gray_secondary"
            android:contentDescription="@string/todos" />

        <TextView
            android:id="@+id/report"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/icon_report"
            android:layout_centerHorizontal="true"
            android:gravity="center"
            android:text="@string/reports" />
    </RelativeLayout>
</LinearLayout>

navigation_activity.xml


xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">

<android.support.design.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <include layout="@layout/toolbar_main"/>
    <RelativeLayout
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    <FrameLayout
        android:id="@+id/main_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/bottom_view"
        />
    <include
        layout="@layout/bottombar"
        android:id="@+id/bottom_view"
        />
    </RelativeLayout>
</android.support.design.widget.CoordinatorLayout>

<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerview"
    android:paddingTop="50dp"
    android:layout_marginTop="60dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

</android.support.v7.widget.RecyclerView>

<android.support.design.widget.NavigationView
     android:id="@+id/nav_view"
     android:layout_width="wrap_content"
     android:layout_height="match_parent"
     android:layout_gravity="start"
     android:fitsSystemWindows="true"
     app:headerLayout="@layout/nav_header_navigation"
     app:menu="@menu/activity_navigation_drawer" />

NavigationActivity.java

public class NavigationActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{

ArrayList<Data> list;
CompanyAdapter adapter;
RecyclerView recyclerView;
FrameLayout mainContainer;
FragmentManager fragmentManager;
FragmentTransaction fragmentTransaction;
NavigationView navigationView;
DrawerLayout drawer;
// dashboard view id
ImageView imageView_dashboard;
ImageView imageView_party;
ImageView imageView_items;
ImageView imageView_report;
RelativeLayout dashBoardLayoutView;
@BindView( R.id.bottom_view ) View layout_1;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_navigation);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    toolbar.setTitle("Orizer");
    setSupportActionBar(toolbar);
    mainContainer = (FrameLayout)findViewById(R.id.main_container);
    imageView_report = (ImageView)findViewById(R.id.icon_party);
    drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.addDrawerListener(toggle);
    toggle.syncState();



    navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);


    loadData();


}

public void loadData()
{
    //recyclerview define here
    recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
    recyclerView.setHasFixedSize(true);

    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.addItemDecoration(new DividerItemDecoration(getApplicationContext(),
            DividerItemDecoration.VERTICAL));
    //BottomNavigationView bottomNavigationView = (BottomNavigationView)findViewById(R.id.botton_navigation);


    list = new ArrayList<>();

    list.add(
            new Data(
                    "60,55,8000", "Sales-Credit Note (Gross)", R.drawable.ic_sales));

    list.add(
            new Data(
                    "20,21,3000", "Purchase- Debit Note(Gross)", R.drawable.ic_purchase

            ));
    list.add(
            new Data(
                    "50,41,6000", "Receipt", R.drawable.ic_receipt
            ));

    list.add(
            new Data(
                    "60,88,1000", "Payment", R.drawable.ic_payment
            ));
    list.add(
            new Data(
                    "55,21,2000", "Receivable", R.drawable.ic_debtors
            ));
    list.add(
            new Data(
                    "44,41,6000", "Payable", R.drawable.ic_creditors
            ));
    list.add(
            new Data(
                    "82,41,7000", "Cash Bank Balance ", R.drawable.ic_account_balance
            ));
    list.add(
            new Data(
                    "50,41,6000", "Sales Order", R.drawable.ic_sales_order
            ));
    list.add(
            new Data(
                    "78,11,9000", "Delivery Note", R.drawable.ic_delivery_note
            ));
    list.add(
            new Data(
                    "60,88,1000", "Receipt", R.drawable.ic_receipt_note));

    //creating recyclerview adapter
    adapter = new CompanyAdapter(list, this);

    //setting adapter to recyclerview
    recyclerView.setAdapter(adapter);

  initDash();

}


public View initDash(){


    navigationView.removeHeaderView(navigationView.getHeaderView(0));
    View view = LayoutInflater.from(this).inflate(R.layout.bottombar,null);
    imageView_report =(ImageView)view.findViewById(R.id.icon_report);
    imageView_party = (ImageView)view.findViewById(R.id.icon_party);
    imageView_items = (ImageView) view.findViewById(R.id.icon_items);
    imageView_dashboard = (ImageView)view.findViewById(R.id.icon_dashboard);

    imageView_items.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            FragmentManager manager = getSupportFragmentManager();
            FragmentTransaction transaction = manager.beginTransaction();
            transaction.replace(R.id.main_container,new SampleFragment());
            navigationView.removeHeaderView(null);
        }
    });
 return view;

}


@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
        finish();
    }
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();

    if (id == R.id.nav_companies)
    {
        startActivity(new Intent(getApplicationContext(),com.bizanalyst.activities.SampleActivity.class));
    }
    else if (id == R.id.nav_users)
    {

        startActivity(new Intent(getApplicationContext(),com.bizanalyst.activities.SampleActivity.class));

    }
    else if (id == R.id.nav_setting)
    {
        startActivity(new Intent(getApplicationContext(),com.bizanalyst.activities.SampleActivity.class));

    }
    else if (id == R.id.nav_purchase_subscrip)
    {
        startActivity(new Intent(getApplicationContext(),com.bizanalyst.activities.SampleActivity.class));

    }
    else if (id == R.id.nav_pending_invoices)
    {
        startActivity(new Intent(getApplicationContext(),com.bizanalyst.activities.SampleActivity.class));

    }
    else if (id == R.id.nav_setpassword)
    {
        startActivity(new Intent(getApplicationContext(),com.bizanalyst.activities.SampleActivity.class));

    }
    else if (id == R.id.nav_forget_password)
    {
        startActivity(new Intent(getApplicationContext(),com.bizanalyst.activities.SampleActivity.class));

    }
    else  if (id == R.id.nav_help)
    {
        startActivity(new Intent(getApplicationContext(),com.bizanalyst.activities.SampleActivity.class));

    }
    else if (id == R.id.nav_shares)
    {
        startActivity(new Intent(getApplicationContext(),com.bizanalyst.activities.SampleActivity.class));

    }
    else if (id == R.id.nav_FAQs)
    {
        startActivity(new Intent(getApplicationContext(),com.bizanalyst.activities.SampleActivity.class));

    }
    else if (id == R.id.nav_contact_us)
    {
        startActivity(new Intent(getApplicationContext(),com.bizanalyst.activities.SampleActivity.class));

    }
    else if (id == R.id.nav_about)
    {
        startActivity(new Intent(getApplicationContext(),com.bizanalyst.activities.SampleActivity.class));

    }
    else if (id == R.id.nav_logout)
    {
        // Set LoggedIn status to false
        SaveSharedPreference.setLoggedIn(getApplicationContext(), false);

        // Logout
        logout();

    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}
private void logout() {

    Intent intent = new Intent(getApplicationContext(),LoginActivity.class);
    startActivity(intent);
    finish();
}

}

how to perform click event on layout file which include into NavigationActivity.java and change to fragment
plz help me i am stuck ???

Was this page helpful?
0 / 5 - 0 ratings