今天来讲解一下注解框架ButterKnife,此框架由Android之神Jake Wharton开源的。

GitHub的链接地址:https://github.com/JakeWharton/butterknife

ButterKnife框架的优点:

  1. 强大的View绑定和Click事件处理功能,简化代码,提升开发效率
  2. 方便的处理Adaper里的ViewHolder绑定问题
  3. 运行时不会影响app效率,使用配置方便
  4. 代码清晰,可读性强

一、在项目中导入ButterKnife

1、找到项目的app下的build.grade,直接添加下面两行依赖,刷新即可

dependencies {    compile 'com.jakewharton:butterknife:8.5.1'    annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'}

2、在项目的build.gradle中添加

buildscript { repositories { mavenCentral() }  dependencies { classpath 'com.jakewharton:butterknife-gradle-plugin:8.5.1' }}

3、在主程序依赖Module的build.gradle中添加

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;  ...}

二、绑定ButterKnife

1.在Activity中绑定

public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //绑定ButterKnife        ButterKnife.bind(this);    }}

2.在Fragment中绑定

注意: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();    }}

3.在ViewHolder中绑定

    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;

1. @BindView 绑定一个View

    @BindView(R.id.btnOne)    public Button btnOne;    @BindView(R.id.imgOne)    public ImageView imgOne;

2. @BindViews 绑定多个View

public class MainActivity extends AppCompatActivity {    @BindViews({R.id.btnOne,R.id.btnTwo,R.id.btnThree})    public List

3. @BindArray 绑定绑定string里面array数组

先在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

4. @BindBitmap 绑定资源图片

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);    }}

5. @BindBool 绑定真假boolean

新建一个资源文件bool.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <bool name="isPlay">truebool>    <bool name="isDo">falsebool>resources>

使用情况

    @BindBool(R.bool.isPlay)    public boolean isPlay;

6. @BindColor 绑定color

    @BindColor(R.color.colorAccent)    int colorAccent;

7. @BindDimen 绑定Dimen

先添加一个dimen.xml文件

<?xml version="1.0" encoding="utf-8"?><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;

8. @BindDrawable 绑定Drawable

@BindDrawable(R.drawable.ic_launcher_background) Drawable ic_launcher_background;

9. @BindFloat 绑定Float

    @BindFloat(R.dimen.font_size) float font_size;

10. @BindInt 绑定Int

先添加一个资源文件integer.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <integer name="max_value">99integer>    <integer name="min_value">1integer>resources>

使用情况

    @BindInt(R.integer.max_value) int max_value;

11. @BindString 绑定一个String

@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存在,则注入, 不存在,则什么事情都不做=如下代码

1. @OnClick 绑定点击事件

    @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() {        }    }

2. @OnLongClick 绑定长按事件

    @OnLongClick(R.id.btnOne)    public boolean onLongClick(View view) {        return true;    }

3. @OnCheckedChanged 绑定选中,取消选中

演示布局样式

<?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: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;        }    }

4. @OnEditorAction 绑定软件盘的功能键

    @OnEditorAction(R.id.tvOne)    public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {        return true;    }

5. @OnFocusChange 绑定焦点改变

    @OnFocusChange(R.id.etOne)    public void onFocusChanged(View view, boolean hasFocus) {    }

6. @OnItemClick 绑定Item的点击事件

    @OnItemClick(R.id.lvContent)    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {    }

7. @OnItemLongClick 绑定Item的长按事件

    @OnItemLongClick(R.id.lvContent)    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {        return true;    }

8. @OnItemSelected 绑定Item被选择

    //利用注解对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();    }

9. @OnPageChange 绑定页面改变事件

    @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) {    }

10. @OnTextChanged 绑定EditText里面文本变化事件

    @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) {    }

11. @OnTouch 绑定触摸事件

    @OnTouch(R.id.btnOne)    public boolean onTouch(View view, MotionEvent event) {        return false;    }

12. @Optional 绑定选择性注入事件

    @Optional @OnClick(R.id.maybe_missing)    public void onMaybeMissingClicked() {    }




五、代码混淆

-keep class butterknife.** { *; }-dontwarn butterknife.internal.**-keep class **$$ViewBinder { *; }-keepclasseswithmembernames class * {    @butterknife.* ;}-keepclasseswithmembernames class * {    @butterknife.* ;}

更多相关文章

  1. Android在onTouchEvent或setOnTouchListener中处理长按事件
  2. 探秘ListView的ConvertView以及ViewHolder原理
  3. 更新ADT20后出现This template depends on Android(安卓)Support
  4. 【android】使用Event Bus模式解耦Android(安卓)App组件间通信
  5. Android(安卓)开发艺术探究V第三章之view的事件分发机制
  6. 菜鸟进阶之Android(安卓)Touch事件传递(一)
  7. android手机震动的节奏例子--Vibrator对象及周期运用
  8. 第三部分:Android(安卓)应用程序接口指南---第二节:UI---第十章 拖
  9. 安卓TV开发(九) Android模拟事件 遥控器变身成鼠标来操作TV

随机推荐

  1. 一个有趣的android加载动画
  2. 细看 Google+ 里最有希望成为杀手级应用
  3. Android(安卓)9.0实现系统内录(只录制系统
  4. 关于Android中的Intent一点说明
  5. Android中的拿来主义
  6. android构建系统总览
  7. Android平台上四种保存数据的方法
  8. 51 信用卡管家 Android(安卓)客户端内部
  9. android植入广告赚钱是不是只是个梦??
  10. 使用EasyPermissions高效处理权限