前言
在写这篇文章之前,自己写了有两篇关于编写Android Studio插件的文章,在写的同时,也了解到了ButterKnife,所以抽时间来了解它。
下面是我之前关于Android Studio插件的文章,有兴趣的可以去看一下:
本篇文章所使用的ButterKnife的版本为8.4.0
,ButterKnife采用注解的方式,去实现view的findViewById,view的监听,对代码的易用性,可读性都有很大的提升。
- 使用
@BindView
注解替换findViewById
。 - 使用List或者Array来包含多个View,并且可以使用
apply()
方法可以对List或者数组的View进行整体操作。 - 使用
@OnClick
或者其他方法注解,免去添加实现Listener代码。 - 使用
@BindString
等资源注解,可直接使用资源,免去资源查找。 - 支持在ViewHolder里面使用。
添加ButterKnife
- 引用ButterKnife,在Module(app)的gradle里面添加
dependencies {
compile 'com.jakewharton:butterknife:8.4.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
}
如果提示
将
annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
换成
apt 'com.jakewharton:butterknife-compiler:8.4.0'
- 添加
butterknife-gradle-plugin
,在Project的gradle里面添加
buildscript {
dependencies {
classpath 'com.jakewharton:butterknife-gradle-plugin:8.4.0'
}
}
- 添加apply,在在Module(app)的gradle里面添加
apply plugin: 'com.jakewharton.butterknife'
使用ButterKnife
绑定Activity
使用ButterKnife.bind(this)
来绑定Activity,写在setContentView()
后面,父类bind绑定后,子类不需要再bind
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
}
绑定Fragment
使用ButterKnife.bind(this, view)
来绑定Fragment,第二个参数是当前Fragment对应的View
public Unbinder unbinder;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fancy_fragment, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
同时在onDestroyView()
方法里面解除绑定
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
ViewHolder使用
static class ViewHolder {
@BindView(R.id.title)
TextView name;
@BindView(R.id.job_title)
TextView jobTitle;
public ViewHolder(View view) {
ButterKnife.bind(this, view);
}
}
绑定View
注意:
@BindView fields must not be private or static.
使用@BindView(R.id.id)
来绑定View
@BindView(R.id.title)
TextView title;
@BindView(R.id.subtitle)
TextView subtitle;
@BindView(R.id.footer)
TextView footer;
绑定多个View
- 使用
@BindViews(R.id.one, R.id.two)
来绑定多个相同类型的View
@BindViews({ R.id.first_name, R.id.middle_name, R.id.last_name })
List<EditText> nameViews;
@BindViews({ R.id.first_name, R.id.middle_name, R.id.last_name })
EditText[] nameViews;
- 使用
apply()
方法可以对List或者数组的View进行整体操作
ButterKnife.apply(nameViews, DISABLE);
ButterKnife.apply(nameViews, ENABLED, false);
- 实现
Action
和Setter
接口,可进行简单的操作,如设置是否可用。
static final ButterKnife.Action<View> DISABLE = new ButterKnife.Action<View>() {
@Override
public void apply(View view, int index) {
view.setEnabled(false);
}
};
static final ButterKnife.Setter<View, Boolean> ENABLED = new ButterKnife.Setter<View, Boolean>() {
@Override
public void set(View view, Boolean value, int index) {
view.setEnabled(value);
}
};
-
apply()
方法也可以直接设置Android自带的Property
(属性),如设置透明度ButterKnife.apply(nameViews, View.ALPHA, 0.0f);
绑定资源
绑定数组
支持类型String、int、CharSequence、TypedArray
使用@BindArray(R.array.array)
来绑定数组
@BindArray(R.array.countries)
String[] countries;
@BindArray(R.array.phones)
int[] phones;
@BindArray(R.array.options)
CharSequence[] options;
@BindArray(R.array.icons)
TypedArray icons;
绑定Bitmap
使用@BindBitmap(R.drawable.logo)
来绑定Bitmap
@BindBitmap(R.drawable.logo)
Bitmap logo;
绑定Bool(布尔类型)
使用@BindBool(R.bool.bool)
来绑定Bool(布尔类型)
@BindBool(R.bool.is_tablet)
boolean isTablet;
绑定Color
支持类型int、ColorStateList
使用@BindColor(R.color.blue)
来绑定Color
@BindColor(R.color.background_green)
int green;
@BindColor(R.color.background_green_selector)
ColorStateList greenSelector;
绑定Dimen
支持类型int、float
使用@BindDimen(R.dimen.horizontal_gap)
来绑定Dimen
@BindDimen(R.dimen.horizontal_gap)
int gapPx;
@BindDimen(R.dimen.horizontal_gap)
float gap;
绑定Drawable
BindDrawable
有两个参数,第二个tint
可选,将drawable染色
使用@BindDrawable(R.drawable.placeholder)
来绑定Drawable
@BindDrawable(R.drawable.placeholder)
Drawable placeholder;
@BindDrawable(value = R.drawable.placeholder, tint = R.attr.colorAccent)
Drawable tintedPlaceholder;
绑定Float
使用@BindFloat(R.dimen.image_ratio)
来绑定Float
@BindFloat(R.dimen.image_ratio)
float imageRatio;
绑定Int
使用@BindInt(R.int.columns)
来绑定Int
@BindInt(R.int.columns)
int columns;
绑定String
使用BindString(R.string.username)
来绑定String
BindString(R.string.username_error)
String usernameErrorText;
绑定Listener
注意:
Methods must not be private or static.
支持的Listener
OnCheckedChangeListener
OnClickListener
OnLongClickListener
OnFocusChangeListener
OnTouchListener
onPageStateChanged
OnItemSelectedListener
OnItemClickListener
OnItemLongClickListener
OnTextChanged
onEditorAction
- ...
单个方法
方法名同Listener方法
如使用@OnClick({R.id.submit, R.id.cancel})
绑定onClick
方法
@OnClick({R.id.submit, R.id.cancel})
public void onClick(View view) {
Toast.makeText(this, "Long clicked!", Toast.LENGTH_SHORT).show();
}
自定义方法名
@OnClick({R.id.submit, R.id.cancel})
public void submit(View view) {
Toast.makeText(this, "Long clicked!", Toast.LENGTH_SHORT).show();
}
方法参数都是可选的
@OnClick(R.id.submit)
public void submit() {
}
自定义方法参数
@OnClick(R.id.submit)
public void sayHi(Button button) {
button.setText("Hello!");
}
直接在自定义View
public class FancyButton extends Button {
@OnClick
public void onClick() {
// TODO do something!
}
}
多个方法
有些Listener有多个方法,如果只要使用其中一个,就必须要用到第二个参数callback
。
如OnItemSelectedListener
有两个方法,一个是onItemSelected()
,一个是onNothingSelected()
,
要用到onNothingSelected()
方法时,第二个参数写callback = NOTHING_SELECTED
@OnItemSelected(value = R.id.listview, callback = ITEM_SELECTED)
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long l) {
}
@OnItemSelected(value = R.id.listview, callback = NOTHING_SELECTED)
public void onNotingSelected(AdapterView<?> adapterView) {
}
绑定Optional
使用@Optional
来绑定方法,防止报空指针异常,同时可以用@Nullable
来绑定字段,防止报空指针异常
@Nullable
@BindView(R.id.might_not_be_there)
TextView mightNotBeThere;
@Optional
@OnClick(R.id.maybe_missing)
void onMaybeMissingClicked() {
}
支持直接findViewById
如果需要获取Dialog
等的布局控件,可直接调用ButterKnife的findById()
方法,替换FindViewById()
方法,并且会自动判断返回值的类型然后自动进行类型转换。
View view = LayoutInflater.from(context).inflate(R.layout.thing, null);
TextView firstName = ButterKnife.findById(view, R.id.first_name);
TextView lastName = ButterKnife.findById(view, R.id.last_name);
ImageView photo = ButterKnife.findById(view, R.id.photo);
代码混淆
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}