在Android开发中,需要大量的编写初始化布局、点击事件、监听事件等一些简单重复的代码,会无形中浪费时间和精力。而使用ButterKnife这个开源库可以让我们从大量的findViewById()和setOnclicktListener()中解放出来。
ButterKnife:是视图注入中相对简单易懂的开源框架,其优势在于:
1. 强大的View绑定和Click事件处理功能,简单代码,提高开发效率
2. 方便的处理Adapter和ViewHolder绑定问题
3. 提高APP运行效率,使用配置方便
4. 代码清晰,可读性强
参考资料:
ButterKnife官网:http://jakewharton.github.io/butterknife/
在实际使用时,为了提高效率,也可以在Studio中使用插件:Android ButterKnife Aelezny
ButterKnife使用心得:
1.ButtKnife初始化ButterKnife.bind(this)必须在setContentView()之后,所以ButterKnife不能在Application中初始化。
2.ButtKnife在Fragment和Adapter中使用时,初始化代码有所不同
ButterKnife.bind(this, mRootView);
3.属性布局不能用private or static 修饰,用public,否则会报错
4.虽然使用ButterKnife很方便,但由于ButterKnife不是安卓原生的,所以使用时如果出错了,Studio
报错会很奇怪,需要耐心找。
ButterKnife使用步骤:
ButterKnife最新版本是8.4,需要编译工具Studio24以上,所以这里我是用了7.0的版本进行演示。其中我用到了ImageView,TextView,Button,CheckBox一些我们常用的控件以及ButterKnife在Fragment的使用的说明。最新8.4版本方法名有所改动,建议看官方文档,整体和原理没什么变动。
效果图:
一、 在gradle文件中进行关联
compile 'com.jakewharton:butterknife:7.0.1' 二、按照需求设计布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical"> <ImageView android:layout_marginTop="30dp" android:id="@+id/imgShow" android:layout_width="200dp" android:layout_height="200dp" android:src="@mipmap/dahuangfeng" /> <TextView android:id="@+id/txtShowText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="汽车人变形" android:textSize="24sp" />
<Button android:id="@+id/btnOK" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="跳到第二个页面" android:textSize="24sp" /> <TextView android:id="@+id/txtShowMessage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="我来显示信息" android:textSize="24sp" />< CheckBox
三、在onCreate里进行初始化(注意不同的版本初始化的方法皆不一样,且注解控件的后缀名都不同
ButterKnife.bind(this); 四、加注解(相当于findViewByID,注意格式),先更改显示信息的TextView看下效果
@Bind(R.id.txtShowMessage) TextView txtShowMessage; 五、使用注解完成点击事件的设置
txtShowMessage.setText("哈哈哈哈");此时运行一下看看效果:
@Bind(R.id.imgShow) ImageView imgShow;2.使用注解完成点击事件的设置
@OnClick(R.id.txtShowText) public void change(TextView textView){ imgShow.animate().scaleXBy(0.5f).alpha(0.3f).setDuration(2000).start(); textView.setText("变形成功"); }运行看一下效果:
public class MainActivity extends AppCompatActivity { @Bind(R.id.txtShowMessage) TextView txtShowMessage; @Bind(R.id.imgShow) ImageView imgShow; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //在布局文件后,进行ButterKnife的绑定,参数类对象 ButterKnife.bind(this); //使用TextView设置数据 txtShowMessage.setText("哈哈哈哈"); } //让TextView具备了点击事件,同时参数里就可以找到这个TextVIew(只能够在这个方法里使用其对象) //相当于即做了onClick点击事件,又做了findVIewByID //设置点击事件,权限必须是默认权限以上 @OnClick(R.id.txtShowText) public void change(TextView textView){ //让ImageViews做动画 imgShow.animate().scaleXBy(0.5f).alpha(0.3f).setDuration(2000).start(); //具备点击事件的TextView,改变其文字 textView.setText("变形成功"); } /*给多个控件一起设置点击事件格式: @OnClick( { , , .....} ) public void onClick(View view)参数是View view{ switch (view.getId()) { case R.id..... ..... break;} } */ @OnClick({R.id.btnOK,R.id.chbShow}) public void onClick(View view){ switch (view.getId()){ //为跳转到第二个页面的button设置了点击事件 case R.id.btnOK: Intent intent = new Intent(MainActivity.this, Main2Activity.class); startActivity(intent); break; case R.id.chbShow: //为CheckBox设置了点击事件 Toast.makeText(MainActivity.this, "试试就试试", Toast.LENGTH_SHORT).show(); break; } } }看一下效果图:
<FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/container" xmlns:android="http://schemas.android.com/apk/res/android">FrameLayout>2.fragment布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/imgShow2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:src="@mipmap/ic_arrow_back_black_48dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:text="第二个页面" android:textSize="24sp" /> <ListView android:id="@+id/lstShow" android:layout_width="match_parent" android:layout_marginTop="8dp" android:layout_below="@+id/imgShow" android:layout_height="match_parent">ListView> RelativeLayout>3.ListView适配器
public class MyAdapter extends BaseAdapter{ //上下文 Context mContext; //构造方法,从外界得到上下文对象 public MyAdapter(Context context) { mContext = context; } //listVIew加载的字符串,图片 int[] carsId={R.mipmap.car_black,R.mipmap.car_green,R.mipmap.car_red,R.mipmap.car_yellow}; String [] comentStr={"哈哈哈哈哈", "啦啦啦啦啦", "嘎嘎嘎嘎嘎", "嘿嘿嘿嘿嘿", "卡卡卡卡卡"}; @Override public int getCount() { return carsId.length; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if(convertView == null ){ convertView= LayoutInflater.from(mContext).inflate(R.layout.item_list, null); viewHolder=new ViewHolder( convertView) ; convertView.setTag(viewHolder); }else{ viewHolder= (ViewHolder) convertView.getTag(); } //使用Random随机设置图片和评论文本,new Random().nextInt:随机产生0到指定int数的整数 viewHolder.car_IV.setImageResource(carsId[new Random().nextInt(4)]); viewHolder.comment1_TV.setText(comentStr[new Random().nextInt(3)]); viewHolder.comment2_TV.setText(comentStr[new Random().nextInt(3)]); return convertView; } //创建listView里面用到的ViewHolder,首先要创建其构造方法,参数是VIew view public static class ViewHolder{ @Bind(R.id.imgShowPic) ImageView car_IV; @Bind(R.id.txtShowComment1) TextView comment1_TV; @Bind(R.id.txtShowComment2) TextView comment2_TV; public ViewHolder(View view) { //进行ButterKnife的初始化,参数1 类对象,参数2VIew对象 ButterKnife.bind(this,view); } } }4.item_list布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/imgShowPic"
android:layout_width="wrap_content"
android:layout_height="360dp" />
<TextView
android:id="@+id/txtShowComment1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textColor="@android:color/black"
android:textSize="16sp" />
<TextView
android:id="@+id/txtShowComment2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="@android:color/black"
android:textSize="16sp" />
LinearLayout>
5.Main2Activity
public class Main2Activity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); //把Activity里的ID替换成一个Fragment getSupportFragmentManager().beginTransaction() .replace(R.id.container, new PlaceHolderFragment()) .commit(); } //一个静态的内部类,继承Fragment public static class PlaceHolderFragment extends Fragment { //建立listview对象 @Bind(R.id.lstShow) ListView lstShow; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment, container, false); //进行ButterKnife的绑定,在Fragment使用即使两个参数 1.类对象 2.容器View对象, ButterKnife.bind(this, rootView); //创建一个adapter传递上下文,getActivity就是获取Fragment依赖Activity的上下文 MyAdapter adapter = new MyAdapter(getActivity()); lstShow.setAdapter(adapter); return rootView; } //给Image设置点击事件,关闭当前Activity,上下文调用finish @OnClick(R.id.imgShow2) public void finishActivity() { getActivity().finish(); } } }效果图: