今天来讲解一下注解框架ButterKnife,此框架由Android之神Jake Wharton开源的。
GitHub的链接地址:https://github.com/JakeWharton/butterknife
ButterKnife框架的优点:
dependencies {
compile 'com.jakewharton:butterknife:8.5.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
}
buildscript { repositories { mavenCentral() }
dependencies { classpath 'com.jakewharton:butterknife-gradle-plugin:8.5.1' }
}
apply plugin: 'com.android.library'
apply plugin: 'com.jakewharton.butterknife'
注意:在依赖Module中使用,声明注解时用R2替代R, 例如:
class MainActivity extends Activity {
@BindView(R2.id.user) EditText username;
@BindView(R2.id.pass) EditText password;
...
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定ButterKnife
ButterKnife.bind(this);
}
}
注意:Fragment的生命周期不同于activity,在onCreateView中绑定一个Fragment时,在onDestroyView中将视图设置为null。当你调用bind来为你绑定一个Fragment时,Butter Knife会返回一个Unbinder的实例。在适当的生命周期(onDestroyView)回调中调用它的unbind方法进行Fragment解绑。
public class FirstFragment extends Fragment {
private Unbinder unbinder;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_first, null);
//绑定
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
//解绑
unbinder.unbind();
}
}
static class ViewHolder {
@BindView(R.id.btnOne)
TextView btnOne;
@BindView(R.id.imgOne)
TextView imgOne;
public ViewHolder(View view) {
ButterKnife.bind(this, view);
}
}
名称 | 解析 |
---|---|
@BindView | 绑定一个view id为一个view 变量 |
@BindViews | 绑定多个view id为一个view的list变量 |
@BindArray | 绑定string里面array数组,@BindArray(R.array.city ) String[] citys ; |
@BindBitmap | 绑定图片资源为Bitmap,@BindBitmap( R.mipmap.wifi ) Bitmap bitmap; |
@BindBool | 绑定真假boolean |
@BindColor | 绑定color,@BindColor(R.color.colorAccent) int black; |
@BindDimen | 绑定Dimen,@BindDimen(R.dimen.borth_width) int mBorderWidth; |
@BindDrawable | 绑定Drawable,@BindDrawable(R.drawable.test_pic) Drawable mTestPic; |
@BindFloat | 绑定float |
@BindInt | 绑定int |
@BindString | 绑定一个String id为一个String变量,@BindString( R.string.app_name ) String meg; |
@BindView(R.id.btnOne)
public Button btnOne;
@BindView(R.id.imgOne)
public ImageView imgOne;
public class MainActivity extends AppCompatActivity {
@BindViews({R.id.btnOne,R.id.btnTwo,R.id.btnThree})
public List
先在String文件中添加一个array数组
<resources>
<string name="app_name">ButterKnifeDemostring>
<string-array name="language">
<item>Javaitem>
<item>Kotlinitem>
<item>Citem>
<item>C++item>
<item>PHPitem>
<item>JavaScriptitem>
string-array>
resources>
而后直接绑定使用
public class MainActivity extends AppCompatActivity {
@BindArray(R.array.language)
String[] language;
@BindViews({R.id.btnOne,R.id.btnTwo,R.id.btnThree})
public List
public class MainActivity extends AppCompatActivity {
@BindView(R.id.imgOne)
public ImageView imgOne;
@BindBitmap(R.drawable.ic_launcher)
public Bitmap ic_launcher;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定ButterKnife
ButterKnife.bind(this);
imgOne.setImageBitmap(ic_launcher);
}
}
新建一个资源文件bool.xml
<resources>
<bool name="isPlay">truebool>
<bool name="isDo">falsebool>
resources>
使用情况
@BindBool(R.bool.isPlay)
public boolean isPlay;
@BindColor(R.color.colorAccent)
int colorAccent;
先添加一个dimen.xml文件
<resources>
<dimen name="textview_height">25dpdimen>
<dimen name="textview_width">150dpdimen>
<dimen name="ball_radius">3dpdimen>
<dimen name="font_size">16spdimen>
resources>
使用情况
@BindDimen(R.dimen.font_size) int font_size;
@BindDrawable(R.drawable.ic_launcher_background) Drawable ic_launcher_background;
@BindFloat(R.dimen.font_size) float font_size;
先添加一个资源文件integer.xml
<resources>
<integer name="max_value">99integer>
<integer name="min_value">1integer>
resources>
使用情况
@BindInt(R.integer.max_value) int max_value;
@BindString( R.string.app_name ) String appName;
名称 | 作用 |
---|---|
@OnClick | 点击事件 |
@OnLongClick | 长按事件 |
@OnCheckedChanged | 选中,取消选中 |
@OnEditorAction | 软键盘的功能键 |
@OnFocusChange | 焦点改变 |
@OnItemClick | item被点击(注意这里有坑,如果item里面有Button等这些有点击的控件事件的,需要设置这些控件属性focusable为false) |
@OnItemLongClick | item长按(返回真可以拦截onItemClick) |
@OnItemSelected | item被选择事件 |
@OnPageChange | 页面改变事件 |
@OnTextChanged | EditText里面的文本变化事件 |
@OnTouch | 触摸事件 |
@Optional | 选择性注入,如果当前对象不存在,就会抛出一个异常,为了压制这个异常,可以在变量或者方法上加入一下注解,让注入变成选择性的,如果目标View存在,则注入, 不存在,则什么事情都不做=如下代码 |
@OnClick(R.id.btnOne)
public void btnOne(View view) {
}
//无参
@OnClick(R.id.btnOne)
public void btnOne() {
}
// 任意参数,默认强转,可为绑定View的子类
@OnClick(R.id.btnOne)
public void buttonOnClick(Button btn) {
btn.setText("按钮1");
}
//绑定多个Id
@OnClick({R.id.btnOne, R.id.btnTwo, R.id.btnThree})
public void buttonOnClick(View view) {
switch (view.getId()) {
case R.id.btnOne:
Toast.makeText(this,"按钮1",Toast.LENGTH_SHORT).show();
break;
case R.id.btnTwo:
Toast.makeText(this,"按钮2",Toast.LENGTH_SHORT).show();
break;
case R.id.btnThree:
Toast.makeText(this,"按钮3",Toast.LENGTH_SHORT).show();
break;
}
}
// 自定义 View,绑定自己的监听,不指定 ID
public class MyButton extends Button {
@OnClick
public void onClick() {
}
}
@OnLongClick(R.id.btnOne)
public boolean onLongClick(View view) {
return true;
}
演示布局样式
<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:orientation="horizontal" tools:context="com.itman.butterknifedemo.MainActivity">
<RadioGroup android:id="@+id/rg_main" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="@color/white" android:orientation="vertical">
<RadioButton android:id="@+id/rbJava" android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="false" android:text="Java" />
<RadioButton android:id="@+id/rbKotlin" android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="false" android:text="Kotlin" />
<RadioButton android:id="@+id/rbJavaScript" android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="false" android:text="JavaScript" />
RadioGroup>
LinearLayout>
使用情况:
@OnCheckedChanged({R.id.rbJava,R.id.rbKotlin,R.id.rbJavaScript})
public void OnCheckedChangeListener(CompoundButton view, boolean ischanged ){
switch (view.getId()) {
case R.id.rbJava:
if (ischanged){//注意:这里一定要有这个判断,只有对应该id的按钮被点击了,ischanged状态发生改变,才会执行下面的内容
//选中,未选中变化状态的逻辑
}
break;
case R.id.rbKotlin:
if (ischanged) {
//选中,未选中变化状态的逻辑
}
break;
case R.id.rbJavaScript:
if (ischanged) {
//选中,未选中变化状态的逻辑
}
break;
default:
break;
}
}
@OnEditorAction(R.id.tvOne)
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
return true;
}
@OnFocusChange(R.id.etOne)
public void onFocusChanged(View view, boolean hasFocus) {
}
@OnItemClick(R.id.lvContent)
public void onItemClick(AdapterView> parent, View view, int position, long id) {
}
@OnItemLongClick(R.id.lvContent)
public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
return true;
}
//利用注解对Spinner item 作选择监听事件处理方式
@OnItemSelected(R.id.spContent)//默认callback为ITEM_SELECTED
public void onItemSelected(int position) {
Toast.makeText(this, "position: " + position, Toast.LENGTH_SHORT).show();
}
/* * 注解onNothingSelected,需要在注解参数添加一个callback, * 注意的是Spinner中只要有数据,默认都会选中第0个数据,所以想进入到onNothingSelected()方法,就需要把Adapter中的数据都清空 */
@OnItemSelected(value = R.id.spContent, callback = OnItemSelected.Callback.NOTHING_SELECTED)
public void onNothingSelected() {
Toast.makeText(this, "Nothing", Toast.LENGTH_SHORT).show();
}
@OnPageChange(R.id.vpContent)
public void onPageSelected(int position) {
}
@OnPageChange(value = R.id.vpContent, callback = PAGE_SCROLL_STATE_CHANGED)
public void onPageStateChanged(int state) {
}
@OnPageChange(value = R.id.vpContent, callback = PAGE_SCROLLED)
public void onPageStateChanged(int position, float positionOffset, int positionOffsetPixels) {
}
@OnTextChanged(R.id.etContent)
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@OnTextChanged(value = R.id.etContent, callback = BEFORE_TEXT_CHANGED)
public void onBeforeTextChanged(CharSequence s, int start, int count, int after) {
}
@OnTextChanged(value = R.id.etContent, callback = AFTER_TEXT_CHANGED)
public void onAfterTextChanged(Editable s) {
}
@OnTouch(R.id.btnOne)
public boolean onTouch(View view, MotionEvent event) {
return false;
}
@Optional @OnClick(R.id.maybe_missing)
public void onMaybeMissingClicked() {
}
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* ;
}
-keepclasseswithmembernames class * {
@butterknife.* ;
}