Android ButterKnife 库是一个视图注入库,它使用注解将视图注入 android activity/fragment。例如,@BindView
批注通过自动类型转换视图元素来替代使用 findViewById() 方法。
不仅仅是视图绑定,butterknife 还提供了许多其他有用的选项,比如绑定字符串、调光、绘图、单击事件等等。我们将简要介绍本文中提供的每个组件。
添加 ButterKnife 依赖
您要做的第一件事是,通过在项目的 app/build.gradle 文件中添加以下依赖项,在项目中添加 ButterKnife。添加完成后,同步你的项目,你就可以开始了。
1
2
3
4
5
6
7
| dependencies {
...
// butter knife
compile 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
}
|
基本用法
一旦添加了依赖项,所有 ButterKnife 注释都可以导入。首先,我们将看到如何使用 @BindView
和 @OnClick
注释。假设您的 Activity 有如下布局,其中有一个 TextView 和一个 Button。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| <?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>
|
为了使 视图 View 在 Activity 中可用,我们需要执行以下步骤。
第一步:在声明视图变量的同时(例如 TextView mTextView
) 使用 @BindView
注释,注意不要使用 private 修饰视图变量。
第二步:在 onCreate() 方法中的 setContentView() 后面调用 ButterKnife.bind(this)。
就这样,视图注入发生了,不再需要使用 findViewById() 方法对视图变量进行类型转换。您还可以看到,只需在方法之前添加 @OnClick
注释,就可以附加 click 事件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| 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();
}
}
|
在 Fragment 中使用
在 Fragment 中使用视图注入与 Activity 相同,只是 ButterKnife.bind() 方法改变了。除了目标参数之外,我们还需要注入视图对象作为参数传递。由于 Fragment 的生命周期方法,您还必须使用 Unbinder 解除onDestroyView() 中的视图绑定。
下面是在 Fragment 中使用 ButterKnife 的例子。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| 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();
}
}
|
在列表适配器中使用
ButterKnife 也可以用于列表适配器中。下面是 @BindView
在 recyclerview’s 的适配器类中的例子。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| 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();
}
}
|
与字符串、颜色、尺寸、图片资源等一起使用。
除了绑定视图元素之外,您还可以绑定其他资源,比如字符串(@BindString
)、颜色(@BindColor
)、尺寸(@BindDimen
)和可绘制资源(@BindDrawable
)。下面的示例演示了多种注释及其用法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| 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);
}
}
|
添加点击事件监听
我们已经看到了 @OnClick
注释的例子,但是下面是函数参数的几个变体。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| // 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();
}
|
多个视图放进集合批量操作
在某些情况下,您可能希望对视图组(一组视图)应用某些操作,例如应用颜色,设置文本或一次选择所有复选框。使用 ButterKnife 可以很容易地做到这一点。只需使用 @BindViews
注释将所有视图存储到一个 List 中,并使用 ButterKnife.Action() 方法对所有视图应用一些操作。
在下面的示例中,对 TextView 组应用了两个操作。首先,文本是从字符串数组中设置的。其次,对列表中的所有 TextView 应用一种颜色。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| 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);
}
}
|
需要注意的是上面的示例代码是基于 9.0.0
版本之前的代码,如果你使用的是 9.0.0
版本之后的库,需要使用 ViewCollections.run
和 ViewCollections.set
代替 ButterKnife.Action
例如:
1
2
3
4
5
6
7
8
9
10
| ViewCollections.run(mTypeAreas, new Action<LinearLayout>() {
@Override
public void apply(@NonNull LinearLayout view, int index) {
if(visibleArray[index]) {
view.setVisibility(View.VISIBLE);
}else{
view.setVisibility(View.GONE);
}
}
});
|
注解表
下面是 ButterKnife 提供的注释列表及其用法。
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 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 lblArray; |
@BindFloat | Binds float value
@BindFloat(R.dimen.radius) float radius; |
@BindInt | Binds int resource
@BindInt(R.integer.distance) int distance; |
我希望我们已经涵盖了 ButterKnife 的大部分功能。如果您认为还有什么需要添加的,让我们在下面的评论部分进行讨论。