Android ButterKnife library is a view injection library that injects views into android activity / fragments using annotations. For example, @BindView annotation avoids using findViewById() method by automatically type casting the view element.
Not just view binding, butterknife provides lot of other useful options like binding strings, dimens, drawables, click events and lot more. We’ll see brief about every component offered in this article.
1. Adding ButterKnife Dependency
First thing you have to do is, add ButterKnife in your project by adding the below dependencies in your project’s app/build.gradle file. Once added, sync your project, you are good to go.
dependencies { ... // butter knife compile 'com.jakewharton:butterknife:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' }
2. Basic Usage
Once the dependency is added, all the butterknife annotations will be available to import. To begin with, we’ll see how to use @BindView and @OnClick annotations.
Let’s say you have the below layout for your activity that has a TextView and a Button.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical"> <TextView android:id="@+id/lbl_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Enter your email" android:textAllCaps="true" /> <EditText android:id="@+id/input_name" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/btn_enter" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/dimen_20" android:text="@string/enter" /> </LinearLayout>
To make the views available in the activity, we need to follow the below steps.
1. Use @BindView along with the id (R.id.lbl_title) of the view while declaring the view variable.
2. Call ButterKnife.bind(this) in onCreate() method after setContentView() is called.
That’s all, the view injection happens and no need to typecast the view variable using findViewById() method anymore. Also you can see, the click event is attached just by adding @OnClick annotation before the method.
public class MainActivity extends AppCompatActivity { @BindView(R.id.lbl_title) TextView lblTitle; @BindView(R.id.input_name) EditText inputName; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // bind the view using butterknife ButterKnife.bind(this); } @OnClick(R.id.btn_enter) public void onButtonClick(View view) { Toast.makeText(getApplicationContext(), "You have entered: " + inputName.getText().toString(), Toast.LENGTH_SHORT).show(); } }
3. Using in Fragments
Using view injection in Fragment is same as Activity except the ButterKnife.bind() method changes. In addition to target parameter, we need to pass inflated view as param.
You will also have to use Unbinder to unbind the view in onDestroyView() because of the Life cycle methods of Fragment.
Below is the example usage of ButterKnife in Fragment.
public class MyFragment extends Fragment { Unbinder unbinder; @BindView(R.id.lbl_name) TextView lblName; @BindView(R.id.btn_enter) Button btnEnter; @BindView(R.id.input_name) EditText inputName; public MyFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_my, container, false); // bind view using butter knife unbinder = ButterKnife.bind(this, view); return view; } @Override public void onDestroyView() { super.onDestroyView(); // unbind the view to free some memory unbinder.unbind(); } }
4. Using in List Adapter
ButterKnife also can be used in list adapters too. Below is the example of @BindView in recyclerview’s adapter class.
public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.MyViewHolder> { private List<Contact> contacts; public class MyViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.name) TextView name; @BindView(R.id.mobile) TextView mobile; public MyViewHolder(View view) { super(view); // binding view ButterKnife.bind(this, view); } } public ContactsAdapter(List<Contact> contacts) { this.contacts = contacts; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.contact_list_row, parent, false); return new MyViewHolder(itemView); } @Override public void onBindViewHolder(MyViewHolder holder, int position) { Contact contact = contacts.get(position); holder.name.setText(contact.getName()); holder.mobile.setText(contact.getMobile()); } @Override public int getItemCount() { return contacts.size(); } }
5. Using with Resources – Strings, Colors, Dimens, Drawables etc.,
In addition to binding view elements, you can also bind other resources like strings (@BindString), colors (@BindColor), dimensions (@BindDimen) and drawables (@BindDrawable).
Below example demonstrates multiple annotations and their usage.
public class MainActivity extends AppCompatActivity { @BindView(R.id.logo) ImageView imgLogo; @BindView(R.id.lbl_title) TextView lblTitle; @BindDrawable(R.mipmap.ic_launcher) Drawable drawableLogo; @BindColor(R.color.colorPrimaryDark) int colorTitle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // bind the view using butterknife ButterKnife.bind(this); // setting label color lblTitle.setTextColor(colorTitle); // displaying logo using drawable imgLogo.setImageDrawable(drawableLogo); } }
6. Adding Click Listener (Listener Binding)
We have already seen the example of @OnClick annotation, but below are variants of function params.
// click event with source view params @OnClick(R.id.btn_enter) public void onButtonClick(View view) { Toast.makeText(getApplicationContext(), "You have entered: " + inputName.getText().toString(), Toast.LENGTH_SHORT).show(); } // click event without params @OnClick(R.id.btn_enter) public void onButtonClick() { Toast.makeText(getApplicationContext(), "You have entered: " + inputName.getText().toString(), Toast.LENGTH_SHORT).show(); } // click event with specific type param @OnClick(R.id.btn_enter) public void onButtonClick(Button button) { Toast.makeText(getApplicationContext(), "You have entered: " + inputName.getText().toString(), Toast.LENGTH_SHORT).show(); }
7. Grouping Multiple Views into List & applying action
There might be scenarios where in you want to apply some action on to group of views, like applying color, setting text or selecting all CheckBoxes at once. This can be done very easily using ButterKnife.
All you have to do is, use @BindViews annotation to store all the views into a List and using ButterKnife.Action() method to apply some operations on to all views.
In the below example, two actions are applied to group of TextViews. First, the text is set from an array of strings. Second, a color is applied to all the TextViews in the list.
public class MainActivity extends AppCompatActivity { @BindColor(R.color.colorPrimaryDark) int colorTitle; @BindViews({R.id.lbl1, R.id.lbl2, R.id.lbl3}) List<TextView> lblArray; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // bind the view using butterknife ButterKnife.bind(this); final String[] lblText = new String[]{"Cat", "Dog", "Rat"}; ButterKnife.Action<TextView> APPLY_TEXT = new ButterKnife.Action<TextView>() { @Override public void apply(TextView view, int index) { view.setText(lblText[index]); } }; // setting text to array of labels ButterKnife.apply(lblArray, APPLY_TEXT); // Applying color to group of labels ButterKnife.Action<TextView> APPLY_COLOR = new ButterKnife.Action<TextView>() { @Override public void apply(@NonNull TextView view, int index) { view.setTextColor(colorTitle); } }; ButterKnife.apply(lblArray, APPLY_COLOR); } }
8. Annotations
Below are the list of annotations provided by ButterKnife and their usage.
Annotation | Description |
---|---|
@BindView | Binds view object. TextView, Button, Spinner or any view object
@BindView(R.id.logo) ImageView imgLogo; |
@BindViews | Binds array of views into List
@BindViews({R.id.lbl_name, R.id.lbl_email, R.id.lbl_address}) List<TextView> lblArray; |
@BindDrawable | Binds drawable element. Loads the drawable image from res folder
@BindDrawable(R.mipmap.ic_launcher) Drawable drawableLogo; |
@BindString | Binds string resource
@BindString(R.string.app_name) String appName; |
@BindColor | Binds color resource
@BindColor(R.color.colorPrimaryDark) int colorTitle; |
@BindDimen | Binds dimen resource
@BindDimen(R.id.padding_hori) float paddingHorizontal; |
@BindAnim | Binds animation from anim resource
@BindAnim(R.anim.move_up) Animation animMoveUp; |
@BindBitmap | Binds bitmap object.
@BindBitmap(R.mipmap.ic_launcher) Bitmap logo; |
@BindFont | Binds font resource
@BindViews({R.id.lbl_name, R.id.lbl_email, R.id.lbl_address}) List<TextView> lblArray; |
@BindFloat | Binds float value
@BindFloat(R.dimen.radius) float radius; |
@BindInt | Binds int resource
@BindInt(R.integer.distance) int distance; |
I hope we have covered most of the ButterKnife features. If you think anything more needs to be added, let’s discuss in the comments section below.
Hi there! I am Founder at androidhive and programming enthusiast. My skills includes Android, iOS, PHP, Ruby on Rails and lot more. If you have any idea that you would want me to develop? Let’s talk: ravi@androidhive.info
Sir, kindly write tutorial on Room library of Android.
Yes, I’ll write one.
Awesome work sir. Keep going. 🙂
Thank you Jatin 🙂
when I hit the enter button why did not anything happen?
@OnClick(R.id.btn_enter)
public void onButtonClick(View view) {
Toast.makeText(getApplicationContext(), “You have entered: ” + inputName.getText().toString(),
Toast.LENGTH_SHORT).show();
}
Check if you did call ButterKnife.bind(); after setContetnview();
i want to know how to use listview inside expandablelistView (Child View) can you help me. because I don’t know how to set an Adapter in adapter class.
Do you want to try these?
https://github.com/lisawray/groupie
https://github.com/thoughtbot/expandable-recycler-view
This is older article about expandable listview
https://www.androidhive.info/2013/07/android-expandable-list-view-tutorial/
I hope we will se soon tutorial about MVP pattern and daggger 2
please individual tutorial on MVP, MVVM,DAGER2, RX2JAVA
Please share API Security related example.
This is Very Helpful…. Awesome work ….. I Really like it…. Thanks Sir 🙂
You are welcome 🙂
This is really useful lesson .. what’s your take on using butterknife vs rxbinding for view binding.. advantages and disadvantages alike.
This should be less used. Data binding is the replacement.
How to use static textview using butterknife?
@Ravi Tamada:disqus Can you please do a tutorial on dagger 2 dependency injection library and rx java 2?
Will post soon.
@@Ravi Tamada:disqus can you do post on Espresso for some basic and advanced tests ?
This shows me error that this Gradle plugin requires Studio 3.0 minimum.
plz help me out.
thank you
You need to use Android Studio 3.0
https://developer.android.com/studio/preview/index.html
how to search realtime firebase data in android..????
Can anyone tell me what in binding exactly?And what will happen if we dont write ButterKnife.bind(this) ?
if u dont write ButterKnife.bind(this)
ur app will be force close, because your view/component reference null.
Hi Ravi,
What about the memory footprint of using these kind of DI libraries? For instance in an Activity or Fragment I need to keep a global variable of a TextView or Button but do we obliged to keep that as global variables if we use ButterKnife?
Do you have any tutorial on Dagger 2, RxAndroid, MVVM architecture of Android projects?
Ne peru choosi nu telugu anukuntunna annayya. Nenu chese job ki kaaranam mathram ne valle. Thanka a lot.
🙂
what about longClick with butterknife ? cause i tried that in a project and it failed.
Try @OnLongClick
You can see other binding here
https://github.com/JakeWharton/butterknife/tree/master/butterknife-annotations/src/main/java/butterknife
sir, on generate option,i cant have have any ” Generate injection Butterknife ” Option…….
how can solve this….
install butterknife plugin from Settings -> plugins -> browse repositories -> butter knife…
then restart studio and apply butterknife gradil then choose generate option…..
in Annotations section, @BindFont Is wrong!
What about local variables. Can we bind that too?
ButterKnife.bind(this);
This is used for onCreate
What is the alternative ways to write this ButterKnife.bind(this) in simple way without using butterknife