Butter Knife 8
- // 部分代码省略…
- @Override
- public View getView(int position, View view, ViewGroup parent) {
- ViewHolder holder;
- if (view != null) {
- holder = (ViewHolder) view.getTag();
- } else {
- view = inflater.inflate(R.layout.testlayout, parent, false);
- holder = new ViewHolder(view);
- view.setTag(holder);
- }
- holder.name.setText(”诺诺”);
- // etc…
- return view;
- }
- static class ViewHolder {
- @BindView(R.id.title) TextView name;
- @BindView(R.id.job_title) TextView jobTitle;
- public ViewHolder(View view) {
- ButterKnife.bind(this, view);
- }
- }
- }
public class MyAdapter extends BaseAdapter {
// 部分代码省略...
@Override
public View getView(int position, View view, ViewGroup parent) {
ViewHolder holder;
if (view != null) {
holder = (ViewHolder) view.getTag();
} else {
view = inflater.inflate(R.layout.testlayout, parent, false);
holder = new ViewHolder(view);
view.setTag(holder);
}
holder.name.setText("诺诺");
// etc...
return view;
}
static class ViewHolder {
@BindView(R.id.title) TextView name;
@BindView(R.id.job_title) TextView jobTitle;
public ViewHolder(View view) {
ButterKnife.bind(this, view);
}
}
}
1.快速生成注解view和onclick代码
操作流程如图:(AS上操作)
首先将鼠标放置在初始化view布局文件的位置上,然后按快捷键Shift+Alt+S –> Alt+Insert –>Ctrl+Shif+F12,最后选择生成view和点击事件。
第一步:
第二步:
第三步:(注:上面的选项,自己勾选试试自动生成的代码效果就明白了。非常简单。)
2.使用注意事项
1)ButterKinfe的注解标签因版本不同而有所变化。8.0.0之前的Bind标签在8.0.0之后变成了BindView,
而8.7.0之后在绑定view时,要用R2.id.XXX,而不再是常用的R.id.XXX。
Note:我在实际使用时用R.id.XXX和R2.id.XXX都可以,目前本人并未发现有什么异常。自动生成代码时是R.id.XXX;建议使用R2.id.XXX。因为网上都说使用R2是因为library中的R字段的id值不是final类型的,但是你的应用module中确是final类型的……
2)默认情况下,@bind和 listener 的绑定是必需的。如果无法找到目标视图,将抛出一个异常。
要抑制此行为并创建可选绑定,可以将@Nullable注解添加到字段中,或将@Optional注解添加到方法。
**Note:**任何被命名为@Nullable的注解都可以用于成员变量。鼓励使用Android的”support-annotations”库中的@Nullable注解。
eg:
[java] view plain copy
print ?
- @Nullable
- @BindView(R.id.might_not_be_there)
- TextView mightNotBeThere;
- @Optional
- @OnClick(R.id.maybe_missing)
- public void onMaybeMissingClicked() {
- // TODO …
- }
@Nullable
@BindView(R.id.might_not_be_there)
TextView mightNotBeThere;
@Optional
@OnClick(R.id.maybe_missing)
public void onMaybeMissingClicked() {
// TODO ...
}
3.绑定注解
(注:此处作个统计,后面会有详细解释)
@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;
4.事件注解
(注:此处作个统计,后面会有详细解释)
@OnClick—->点击事件
@OnCheckedChanged —->选中,取消选中
@OnEditorAction —->软键盘的功能键
@OnFocusChange —->焦点改变
@OnItemClick item—->被点击(注意这里有坑,如果item里面有Button等这些有点击的控件事件的,需要设置这些控件属性focusable为false)
@OnItemLongClick item—->长按(返回真可以拦截onItemClick)
@OnItemSelected —->item被选择事件
@OnLongClick —->长按事件
@OnPageChange —->页面改变事件
@OnTextChanged —->EditText里面的文本变化事件
@OnTouch —->触摸事件
@Optional —->
选择性注入,如果当前对象不存在,就会抛出一个异常,为了压制这个异常,可以在变量或者方法上加入一下注解,让注入变成选择性的,如果目标View存在,则注入, 不存在,则什么事情都不做=如下代码
eg:
[java] view plain copy
print ?
- @Optional
- @OnCheckedChanged(R.id.cb_test)
- public void onCheckedChanged(CompoundButton buttonView,boolean isChecked){
- if(isChecked){
- tvTest.setText(”被选中…”);
- }else{
- tvTest.setText(”被取消…”);
- }
- }
@Optional
@OnCheckedChanged(R.id.cb_test)
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked){
if(isChecked){
tvTest.setText("被选中...");
}else{
tvTest.setText("被取消...");
}
}
5.绑定view
1)@BindView() : 布局id 注解
eg:
[java] view plain copy
print ?
- @BindView( R2.id.button)
- public Button button;
@BindView( R2.id.button)
public Button button;
Note:
button 的修饰类型不能是:private 或者 static 。 否则会报错:错误: @BindView fields must not be private or static. (com.ButterknifeActivity.button)
2)@BindViews(): 布局内多个控件 id 注解
eg:
[java] view plain copy
print ?
- public class MainActivity extends AppCompatActivity {
- @BindViews({ R2.id.button1, R2.id.button2, R2.id.button3})
- public List buttonList ;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- ButterKnife.bind(this);
- buttonList.get( 0 ).setText( “hello 1 ”);
- buttonList.get( 1 ).setText( “hello 2 ”);
- buttonList.get( 2 ).setText( “hello 3 ”);
- }
- }
public class MainActivity extends AppCompatActivity {
@BindViews({ R2.id.button1, R2.id.button2, R2.id.button3})
public List<Button> buttonList ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
buttonList.get( 0 ).setText( "hello 1 ");
buttonList.get( 1 ).setText( "hello 2 ");
buttonList.get( 2 ).setText( "hello 3 ");
}
}
6.绑定资源
(注:只举例常用的几个,使用方式的都是类似的,有不会用的可以给我评论留言。)
1)@BindString() :绑定string 字符串
eg:
[java] view plain copy
print ?
- public class ButterknifeActivity extends AppCompatActivity {
- @BindView(R2.id.button) //绑定button 控件
- public Button button ;
- @BindString(R2.string.app_name) //绑定资源文件中string字符串
- String str;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_butterknife);
- //绑定activity
- ButterKnife.bind( this ) ;
- button.setText( str );
- }
- }
public class ButterknifeActivity extends AppCompatActivity {
@BindView(R2.id.button) //绑定button 控件
public Button button ;
@BindString(R2.string.app_name) //绑定资源文件中string字符串
String str;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_butterknife);
//绑定activity
ButterKnife.bind( this ) ;
button.setText( str );
}
}
2)@BindArray() : 绑定string里面array数组
eg:
// 资源文件R.array.city
[html] view plain copy
print ?
- <resources>
- <string name=“app_name”>城市</string>
- <string-array name=“city”>
- <item>北京市</item>
- <item>天津市</item>
- <item>哈尔滨市</item>
- <item>大连市</item>
- <item>香港市</item>
- </string-array>
- </resources>
<string name="app_name">城市</string>
<string-array name="city">
<item>北京市</item>
<item>天津市</item>
<item>哈尔滨市</item>
<item>大连市</item>
<item>香港市</item>
</string-array>
//示例
[java] view plain copy
print ?
- public class ButterknifeActivity extends AppCompatActivity {
- @BindView(R2.id.button) //绑定button 控件
- public Button button ;
- @BindString(R2.string.app_name) //绑定资源文件中string字符串
- String str;
- @BindArray(R2.array.city) //绑定string里面array数组
- String [] citys ;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_butterknife);
- //绑定activity
- ButterKnife.bind( this ) ;
- button.setText(citys[0]);
- }
- }
public class ButterknifeActivity extends AppCompatActivity {
@BindView(R2.id.button) //绑定button 控件
public Button button ;
@BindString(R2.string.app_name) //绑定资源文件中string字符串
String str;
@BindArray(R2.array.city) //绑定string里面array数组
String [] citys ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_butterknife);
//绑定activity
ButterKnife.bind( this ) ;
button.setText(citys[0]);
}
}
3)@BindBitmap( ) : 绑定Bitmap 资源
eg:
[java] view plain copy
print ?
- public class ButterknifeActivity extends AppCompatActivity {
- @BindView( R2.id.imageView ) //绑定ImageView 控件
- public ImageView imageView ;
- @BindBitmap(R2.drawable.bm)//绑定Bitmap 资源
- public Bitmap bitmap ;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_butterknife);
- //绑定activity
- ButterKnife.bind( this ) ;
- imageView.setImageBitmap(bitmap);
- }
- }
public class ButterknifeActivity extends AppCompatActivity {
@BindView( R2.id.imageView ) //绑定ImageView 控件
public ImageView imageView ;
@BindBitmap(R2.drawable.bm)//绑定Bitmap 资源
public Bitmap bitmap ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_butterknife);
//绑定activity
ButterKnife.bind( this ) ;
imageView.setImageBitmap(bitmap);
}
}
**Note:**这里的图片资源引用存在一个小问题:drawable文件夹下的图片使用R或R2引用都没问题;但是mipmap文件夹下的图片资源引用目前只能使用R。
4)@BindColor( ) : 绑定一个颜色值
eg:
[java] view plain copy
print ?
- public class ButterknifeActivity extends AppCompatActivity {
- @BindView( R2.id.button) //绑定一个控件
- public Button button;
- @BindColor( R2.color.colorAccent ) //具体色值在color文件中
- int black ; //绑定一个颜色值
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_butterknife);
- //绑定activity
- ButterKnife.bind( this ) ;
- button.setTextColor( black );
- }
- }
public class ButterknifeActivity extends AppCompatActivity {
@BindView( R2.id.button) //绑定一个控件
public Button button;
@BindColor( R2.color.colorAccent ) //具体色值在color文件中
int black ; //绑定一个颜色值
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_butterknife);
//绑定activity
ButterKnife.bind( this ) ;
button.setTextColor( black );
}
}
7.点击事件绑定
(注:只举例常用的几个,使用方式的都是类似的,有不会用的可以给我评论留言。)
Note:不用声明view,不用setOnClickLisener()就可以绑定点击事件
1)绑定事件
@OnClick( ) : 绑定控件点击事件
@OnLongClick( ) : 绑定控件长按事件
eg:
[java] view plain copy
print ?
- public class ButterknifeActivity extends AppCompatActivity {
- @OnClick(R2.id.button1 ) //给 button1 设置一个点击事件
- public void showToast(){
- Toast.makeText(this, “is a click”, Toast.LENGTH_SHORT).show();
- }
- @OnLongClick( R2.id.button1 ) //给 button1 设置一个长按事件
- public boolean showToast2(){
- Toast.makeText(this, “is a long click”, Toast.LENGTH_SHORT).show();
- return true ;
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_butterknife);
- //绑定activity
- ButterKnife.bind( this ) ;
- }
- }
public class ButterknifeActivity extends AppCompatActivity {
@OnClick(R2.id.button1 ) //给 button1 设置一个点击事件
public void showToast(){
Toast.makeText(this, "is a click", Toast.LENGTH_SHORT).show();
}
@OnLongClick( R2.id.button1 ) //给 button1 设置一个长按事件
public boolean showToast2(){
Toast.makeText(this, "is a long click", Toast.LENGTH_SHORT).show();
return true ;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_butterknife);
//绑定activity
ButterKnife.bind( this ) ;
}
}
2)指定多个id绑定事件
eg:
[java] view plain copy
print ?
- public class ButterknifeActivity extends AppCompatActivity {
- //提示:这是可以自动生成的,大家不要什么都手动敲哦
- @OnClick({R.id.ll_product_name, R.id.ll_product_lilv, R.id.ll_product_qixian, R.id.ll_product_repayment_methods})
- public void onViewClicked(View view) {
- switch (view.getId()) {
- case R.id.ll_product_name:
- System.out.print(”我是点击事件1”);
- break;
- case R.id.ll_product_lilv:
- System.out.print(”我是点击事件2”);
- break;
- case R.id.ll_product_qixian:
- System.out.print(”我是点击事件3”);
- break;
- case R.id.ll_product_repayment_methods:
- System.out.print(”我是点击事件4”);
- break;
- }
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_butterknife);
- //绑定activity
- ButterKnife.bind( this ) ;
- }
- }
public class ButterknifeActivity extends AppCompatActivity {
//提示:这是可以自动生成的,大家不要什么都手动敲哦
@OnClick({R.id.ll_product_name, R.id.ll_product_lilv, R.id.ll_product_qixian, R.id.ll_product_repayment_methods})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.ll_product_name:
System.out.print("我是点击事件1");
break;
case R.id.ll_product_lilv:
System.out.print("我是点击事件2");
break;
case R.id.ll_product_qixian:
System.out.print("我是点击事件3");
break;
case R.id.ll_product_repayment_methods:
System.out.print("我是点击事件4");
break;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_butterknife);
//绑定activity
ButterKnife.bind( this ) ;
}
}
Note:下面是错误的写法,多条点击事件不可以用R2的方式:
eg:
[java] view plain copy
print ?
- public class ButterknifeActivity extends AppCompatActivity {
- @OnClick({R2.id.ll_product_name, R2.id.ll_product_lilv, R2.id.ll_product_qixian, R2.id.ll_product_repayment_methods})
- public void onViewClicked(View view) {
- switch (view.getId()) {
- case R2.id.ll_product_name:
- System.out.print(”我是点击事件1”);
- break;
- case R2.id.ll_product_lilv:
- System.out.print(”我是点击事件2”);
- break;
- case R2.id.ll_product_qixian:
- System.out.print(”我是点击事件3”);
- break;
- case R2.id.ll_product_repayment_methods:
- System.out.print(”我是点击事件4”);
- break;
- }
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_butterknife);
- //绑定activity
- ButterKnife.bind( this ) ;
- }
- }
public class ButterknifeActivity extends AppCompatActivity {
@OnClick({R2.id.ll_product_name, R2.id.ll_product_lilv, R2.id.ll_product_qixian, R2.id.ll_product_repayment_methods})
public void onViewClicked(View view) {
switch (view.getId()) {
case R2.id.ll_product_name:
System.out.print("我是点击事件1");
break;
case R2.id.ll_product_lilv:
System.out.print("我是点击事件2");
break;
case R2.id.ll_product_qixian:
System.out.print("我是点击事件3");
break;
case R2.id.ll_product_repayment_methods:
System.out.print("我是点击事件4");
break;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_butterknife);
//绑定activity
ButterKnife.bind( this ) ;
}
}
如果一定要使用R2的写法,可以单一逐次写,下面写法是正确的
eg:
[java] view plain copy
print ?
- public class ButterknifeActivity extends AppCompatActivity {
- @OnClick(R2.id.ll_product_name)
- public void onViewClicked1(View view) {
- System.out.print(”我是点击事件1”);
- }
- @OnClick(R2.id.ll_product_lilv)
- public void onViewClicked2(View view) {
- System.out.print(”我是点击事件2”);
- }
- @OnClick(R2.id.ll_product_qixian)
- public void onViewClicked3(View view) {
- System.out.print(”我是点击事件3”);
- }
- @OnClick(R2.id.ll_product_repayment_methods)
- public void onViewClicked4(View view) {
- System.out.print(”我是点击事件4”);
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_butterknife);
- //绑定activity
- ButterKnife.bind( this ) ;
- }
- }
public class ButterknifeActivity extends AppCompatActivity {
@OnClick(R2.id.ll_product_name)
public void onViewClicked1(View view) {
System.out.print("我是点击事件1");
}
@OnClick(R2.id.ll_product_lilv)
public void onViewClicked2(View view) {
System.out.print("我是点击事件2");
}
@OnClick(R2.id.ll_product_qixian)
public void onViewClicked3(View view) {
System.out.print("我是点击事件3");
}
@OnClick(R2.id.ll_product_repayment_methods)
public void onViewClicked4(View view) {
System.out.print("我是点击事件4");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_butterknife);
//绑定activity
ButterKnife.bind( this ) ;
}
}
3)自定义View使用注解事件
Note:不用指定id,直接注解OnClick
eg:
[java] view plain copy
print ?
- public class MyButton extends Button {
- @OnClick
- public void onClick() {}
- }
public class MyButton extends Button {
@OnClick
public void onClick() {}
}
8.绑定监听
(**注:**本来不打算详细贴这段代码的,英文说明文档中就有,想想为了便于新生理解,还是贴出来吧。前后对比学习,很快就容易理解了。)
1)Listeners可以自动配置到方法中。
eg:
[java] view plain copy
print ?
- @OnClick(R.id.submit)
- public void submit(View view) {
- // TODO submit data to server…
- }
@OnClick(R.id.submit)
public void submit(View view) {
// TODO submit data to server…
}
2)对监听器方法的所有参数都是可选的。
eg:
[java] view plain copy
print ?
- @OnClick(R.id.submit)
- public void submit() {
- // TODO submit data to server…
- }
@OnClick(R.id.submit)
public void submit() {
// TODO submit data to server…
}
3)定义一个特定类型,它将自动被转换。
eg:
[java] view plain copy
print ?
- @OnClick(R.id.submit)
- public void sayHi(Button button) {//看参数这里的变化就明白了
- button.setText(”Hello!”);
- }
@OnClick(R.id.submit)
public void sayHi(Button button) {//看参数这里的变化就明白了
button.setText("Hello!");
}
4)在单个绑定中指定多个id,用于公共事件处理。
(注:其实这里讲的就是上面的指定多个id绑定点击事件处理,不只是点击事件,其他事件监听也是可以的。很容易理解,不贴代码了。)
5)自定义视图可以通过不指定ID来绑定到它们自己的监听器。
eg:
[java] view plain copy
print ?
- public class FancyButton extends Button {
- @OnClick
- public void onClick() {
- // TODO do something!
- }
- }
public class FancyButton extends Button {
@OnClick
public void onClick() {
// TODO do something!
}
}
6) Listener中多方法注解
方法注解,其对应的监听器有多个回调,可用于绑定到其中任何一个。每个注解都有一个它绑定的默认回调。使用回调参数指定一个替换。
eg:以Spinner为例
原始方式:
[java] view plain copy
print ?
- Spinner s=new Spinner(this);
- //原始方法:Spinner 条目选择监听事件 正常写法
- s.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- }
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- }
- });
Spinner s=new Spinner(this);
//原始方法:Spinner 条目选择监听事件 正常写法
s.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Butter Knife 注解方式:
[java] view plain copy
print ?
- public class ButterknifeActivity extends AppCompatActivity {
- /*利用注解对Spinner item 作选择监听事件处理方式*/
- @OnItemSelected(R.id.my_spiner)//默认callback为ITEM_SELECTED
- void onItemSelected(int position) {
- Toast.makeText(this, “position: ” + position, Toast.LENGTH_SHORT).show();
- }
- /*
- * 注解onNothingSelected,需要在注解参数添加一个callback,
- * 注意的是Spinner中只要有数据,默认都会选中第0个数据,所以想进入到onNothingSelected()方法,就需要把Adapter中的数据都清空
- */
- @OnItemSelected(value = R.id.my_spiner, callback = OnItemSelected.Callback.NOTHING_SELECTED)
- void onNothingSelected() {
- Toast.makeText(this, “Nothing”, Toast.LENGTH_SHORT).show();
- }
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_butterknife);
- //绑定activity
- ButterKnife.bind( this ) ;
- Spinner s=new Spinner(this);
- }
- }
public class ButterknifeActivity extends AppCompatActivity {
/*利用注解对Spinner item 作选择监听事件处理方式*/
@OnItemSelected(R.id.my_spiner)//默认callback为ITEM_SELECTED
void onItemSelected(int position) {
Toast.makeText(this, "position: " + position, Toast.LENGTH_SHORT).show();
}
/*
* 注解onNothingSelected,需要在注解参数添加一个callback,
* 注意的是Spinner中只要有数据,默认都会选中第0个数据,所以想进入到onNothingSelected()方法,就需要把Adapter中的数据都清空
*/
@OnItemSelected(value = R.id.my_spiner, callback = OnItemSelected.Callback.NOTHING_SELECTED)
void onNothingSelected() {
Toast.makeText(this, "Nothing", Toast.LENGTH_SHORT).show();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_butterknife);
//绑定activity
ButterKnife.bind( this ) ;
Spinner s=new Spinner(this);
}
}
7) @OnCheckedChanged监听的使用
原方法应是:setOnCheckedChangeListener()
在使用注解@OnCheckedChanged的时候,出现了CompoundButton这个参数,因为理解有误,传参有误,还出现了无法转换成CompoundButton的bug。正常使用该注解时,格式如下:
[java] view plain copy
print ?
- @OnCheckedChanged({R.id.XXX})
- public void OnCheckedChangeListener(CompoundButton view, boolean ischanged ){
- }
@OnCheckedChanged({R.id.XXX})
public void OnCheckedChangeListener(CompoundButton view, boolean ischanged ){
}
参数是CompoundButton是变化的按钮控件事件id,ischanged是指该控件是否被点击改变。
具体使用请看示例:
eg:
xml文件:
(注:这里只是举例,方便大家理解,其他相关按钮控件也是通用的。不要纠结具体布局,有看不明白的地方可以给我留言。)
[java] view plain copy
print ?
- <?xml version=“1.0” encoding=“utf-8”?>
- <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
- android:layout_width=”match_parent”
- android:layout_height=”match_parent”
- android:orientation=”vertical”>
- <RadioGroup
- android:id=”@+id/rg_main”
- android:layout_width=”fill_parent”
- android:layout_height=”48dp”
- android:layout_alignParentBottom=”true”
- android:background=”@color/white”
- android:orientation=”horizontal”>
- <RadioButton
- android:id=”@+id/rg_home”
- android:layout_width=”match_parent”
- android:layout_height=”match_parent”
- android:focusable=”false”
- android:text=”@string/nav_one” />
- <RadioButton
- android:id=”@+id/rg_wealth”
- android:layout_width=”match_parent”
- android:layout_height=”match_parent”
- android:focusable=”false”
- android:text=”@string/nav_two” />
- <RadioButton
- android:id=”@+id/rg_account”
- android:layout_width=”match_parent”
- android:layout_height=”match_parent”
- android:focusable=”false”
- android:text=”@string/nav_four” />
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RadioGroup
android:id="@+id/rg_main"
android:layout_width="fill_parent"
android:layout_height="48dp"
android:layout_alignParentBottom="true"
android:background="@color/white"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rg_home"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="false"
android:text="@string/nav_one" />
<RadioButton
android:id="@+id/rg_wealth"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="false"
android:text="@string/nav_two" />
<RadioButton
android:id="@+id/rg_account"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="false"
android:text="@string/nav_four" />
</RadioGroup>
类文件中的监听写法:
[java] view plain copy
print ?
- @OnCheckedChanged({R.id.rg_home,R.id.rg_wealth,R.id.rg_account})
- public void OnCheckedChangeListener(CompoundButton view, boolean ischanged ){
- switch (view.getId()) {
- case R.id.rg_home:
- if (ischanged){//注意:这里一定要有这个判断,只有按钮被点击了,ischanged状态发生改变,才会执行下面的内容
- //这里写你的按钮变化状态的UI及相关逻辑
- }
- break;
- case R.id.rg_wealth:
- if (ischanged) {
- //这里写你的按钮变化状态的UI及相关逻辑
- }
- break;
- case R.id.rg_account:
- if (ischanged) {
- //这里写你的按钮变化状态的UI及相关逻辑
- }
- break;
- default:
- break;
- }
- }
@OnCheckedChanged({R.id.rg_home,R.id.rg_wealth,R.id.rg_account})
public void OnCheckedChangeListener(CompoundButton view, boolean ischanged ){
switch (view.getId()) {
case R.id.rg_home:
if (ischanged){//注意:这里一定要有这个判断,只有按钮被点击了,ischanged状态发生改变,才会执行下面的内容
//这里写你的按钮变化状态的UI及相关逻辑
}
break;
case R.id.rg_wealth:
if (ischanged) {
//这里写你的按钮变化状态的UI及相关逻辑
}
break;
case R.id.rg_account:
if (ischanged) {
//这里写你的按钮变化状态的UI及相关逻辑
}
break;
default:
break;
}
}
9.使用findById
Butter Knife仍然包含了findById()方法,用于仍需从一个view ,Activity,或者Dialog上初始化view的时候,并且它可以自动转换类型。
eg:
[java] view plain copy
print ?
- 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 iv = ButterKnife.findById(view, R.id.iv);
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 iv = ButterKnife.findById(view, R.id.iv);
10.设置多个view的属性
apply()
作用:允许您立即对列表中的所有视图进行操作。
Action和Setter接口
作用:Action和Setter接口允许指定简单的行为。
eg:
[java] view plain copy
print ?
- public class ButterknifeActivity extends AppCompatActivity {
- @BindViews({R2.id.first_name, R2.id.middle_name, R2.id.last_name})
- List nameViews;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_butterknife);
- //绑定activity
- ButterKnife.bind(this);
- //看不懂的小伙伴,多敲几遍代码,实际操作一下自然就懂了。相信我!如果你重复敲了10遍以上的代码,并认真思考了还没懂,欢迎给我评论留言。
- //设置多个view的属性
- //方式1:传递值
- ButterKnife.apply(nameViews, DISABLE);
- //方式2:指定值
- ButterKnife.apply(nameViews, ENABLED, false);
- 方式3 设置View的Property
- ButterKnife.apply(nameViews, View.ALPHA, 0.0f);//一个Android属性也可以用于应用的方法。
- }
- /*
- * Action接口设置属性
- */
- static final ButterKnife.Action DISABLE = new ButterKnife.Action() {
- @Override
- public void apply(View view, int index) {
- view.setEnabled(false);//目的是使多个view都具备此属性
- }
- };
- /*
- * Setter接口设置属性
- */
- 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);//目的是使多个view都具备此属性,可变boolean值是可以传递的
- }
- };
- }
public class ButterknifeActivity extends AppCompatActivity {
@BindViews({R2.id.first_name, R2.id.middle_name, R2.id.last_name})
最后
小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
资料⬅专栏获取
/80007661)10.设置多个view的属性
apply()
作用:允许您立即对列表中的所有视图进行操作。
Action和Setter接口
作用:Action和Setter接口允许指定简单的行为。
eg:
[java] view plain copy
print ?
- public class ButterknifeActivity extends AppCompatActivity {
- @BindViews({R2.id.first_name, R2.id.middle_name, R2.id.last_name})
- List nameViews;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_butterknife);
- //绑定activity
- ButterKnife.bind(this);
- //看不懂的小伙伴,多敲几遍代码,实际操作一下自然就懂了。相信我!如果你重复敲了10遍以上的代码,并认真思考了还没懂,欢迎给我评论留言。
- //设置多个view的属性
- //方式1:传递值
- ButterKnife.apply(nameViews, DISABLE);
- //方式2:指定值
- ButterKnife.apply(nameViews, ENABLED, false);
- 方式3 设置View的Property
- ButterKnife.apply(nameViews, View.ALPHA, 0.0f);//一个Android属性也可以用于应用的方法。
- }
- /*
- * Action接口设置属性
- */
- static final ButterKnife.Action DISABLE = new ButterKnife.Action() {
- @Override
- public void apply(View view, int index) {
- view.setEnabled(false);//目的是使多个view都具备此属性
- }
- };
- /*
- * Setter接口设置属性
- */
- 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);//目的是使多个view都具备此属性,可变boolean值是可以传递的
- }
- };
- }
public class ButterknifeActivity extends AppCompatActivity {
@BindViews({R2.id.first_name, R2.id.middle_name, R2.id.last_name})
最后
小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
[外链图片转存中…(img-efHg69gN-1719050367990)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
资料⬅专栏获取
相关文章:
![](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fimg2.imgtp.com%2F2024%2F05%2F27%2FecnWy72K.jpg&pos_id=img-efHg69gN-1719050367990)
Butter Knife 8
// 部分代码省略… Override public View getView(int position, View view, ViewGroup parent) { ViewHolder holder; if (view ! null) { holder (ViewHolder) view.getTag(); } else { view inflater.inflate(R.layout.testlayout, parent, false); holder new ViewHolde…...
![](https://img-blog.csdnimg.cn/direct/145b71164f4546b89f5f21df5ef95986.png)
AMSR/ADEOS-II L1A Raw Observation Counts V003地球表面和大气微波辐射的详细观测数据
AMSR/ADEOS-II L1A Raw Observation Counts V003 简介 AMSR/ADEOS-II L1A Raw Observation Counts V003数据是由日本航空航天研究开发机构(JAXA)的AMSR (Advanced Microwave Scanning Radiometer)仪器收集的一组原始观测计数数据。这些数据是从ADEOS-I…...
![](https://img-blog.csdnimg.cn/direct/35e390749415432aa319580d44556b58.png)
MySQL之复制(十一)
复制 复制的问题和解决方案 数据损坏或丢失的错误 当一个二进制日志损坏时,能恢复多少数据取决于损坏的类型,有几种比较常见的类型: 1.数据改变,但事件仍是有效的SQL 不幸的是,MySQL甚至无法察觉这种损坏。因此最好还是经常检查…...
![](https://img-blog.csdnimg.cn/img_convert/fc74563092fc8198377fdd5aaa789509.png)
深入源码设计!Vue3.js核心API——Computed实现原理
如果您觉得这篇文章有帮助的话!给个点赞和评论支持下吧,感谢~ 作者:前端小王hs 阿里云社区博客专家/清华大学出版社签约作者/csdn百万访问前端博主/B站千粉前端up主 此篇文章是博主于2022年学习《Vue.js设计与实现》时的笔记整理而来 书籍&a…...
![](https://img-blog.csdnimg.cn/direct/52575a1eba634caeab76612fc7180d75.gif#pic_center)
驾考小技巧:老北京布鞋!距离高考出分还剩3天,我却看到有些孩子已经拿了“满分”——早读(逆天打工人爬取热门微信文章解读)
我20年驾校4000多块钱,你呢? 引言Python 代码第一篇 洞见 距离高考出分还剩3天,我却看到有些孩子已经拿了“满分”第二篇 视频新闻结尾 引言 昨天的文章顺利发出 看来“梅西” 这两个字在我们这边 不是敏感词 只是很多个罗粉搞得有点过头了 …...
![](https://www.ngui.cc/images/no-images.jpg)
java-正则表达式 2
7. 复杂的正则表达式示例(续) 7.1 验证日期格式 以下正则表达式用于验证日期格式,例如YYYY-MM-DD。 import java.util.regex.*;public class RegexExample {public static void main(String[] args) {String[] dates {"2023-01-01&q…...
![](https://www.ngui.cc/images/no-images.jpg)
hadoop常见简单基础面试题
文章目录 hadoop简单基础面试题1. 请说下 HDFS 读写流程2. HDFS 在读取文件的时候,如果其中一个块突然损坏了怎么办3. HDFS 在上传文件的时候,如果其中一个 DataNode 突然挂掉了怎么办4. NameNode 在启动的时候会做哪些操作5.Secondary NameNode 了解吗&…...
![](https://www.ngui.cc/images/no-images.jpg)
泄漏检测(LDAR)在建档和检测过程中造假套路和不规范行为
第一章 建档环节造假和不规范 一、 企业行为: 企业为了节约检测费,采取部分建档,部分密封点检测的行为 二、 第三方检测公司不规范行为: 1、台账信息不准确,密封点命名不准确 &…...
![](https://img-blog.csdnimg.cn/direct/b6f1445972ea4eaaa79ae38eb876e2a8.png)
Android CTS环境搭建
CTS即Compatibility Test Suite意为兼容性测试,是Google推出的Android平台兼容性测试机制。其目的是尽早发现不兼容性,并确保软件在整个开发过程中保持兼容性。只有通过CTS认证的设备才能合法的安装并使用Google market等Google应用。 搭建CTS测试环境需…...
![](https://www.ngui.cc/images/no-images.jpg)
比较Zig、Rust和C++
比较Zig、Rust和C这三种编程语言,我们可以从以下几个关键维度来进行: 设计理念 表格 语言 设计理念 Zig 简洁性、模块化、避免常见错误 Rust 内存安全、并发性、性能 C 性能优化、资源控制、可扩展性 内存安全 Zig通过严格的编译时检查、可选…...
![](https://img-blog.csdnimg.cn/direct/72cc4d0c706e42d3817ed38dd376a03e.gif)
路由的params参数,命名路由,路由的params参数,命名路由
上篇我们讲了vue路由的使用 今天我们来讲vue中路由的嵌套,路由的params参数,命名路由 一.路由的params参数 1.配置路由规则,使用children配置项: router:[{path:/about,component:About,},{path:component:Home,//通过children配置子路由c…...
![](https://www.ngui.cc/images/no-images.jpg)
java:CompletableFuture的简单例子
java:CompletableFuture的简单例子 package com.chz.myTest;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.ExecutionException; import java.uti…...
![](https://www.ngui.cc/images/no-images.jpg)
element的table获取当前表格行
需求:验证表格同一行的最低限价不能超过销售定价 思路:先获取当前行table的index,然后在做大小比较 1.局部html <el-table-column label"销售定价(元)" min-width"200px"><template slot"header"&…...
![](https://img-blog.csdnimg.cn/direct/192a017d5f8e4c5e849410451e611e34.png)
html做一个分组散点图图的软件
在HTML中创建一个分组散点图,可以结合JavaScript库如D3.js或Plotly.js来实现。这些库提供了强大的数据可视化功能,易于集成和使用。下面是一个使用Plotly.js创建分组散点图的示例: 要添加文件上传功能,可以让用户上传包含数据的文…...
![](https://www.ngui.cc/images/no-images.jpg)
【SQL】UNION 与 UNION ALL 的区别
在 SQL 中,UNION 和 UNION ALL 都用于将两个或多个结果集合并为一个结果集,但它们在处理重复数据方面有显著区别。以下是它们的详细区别: 1. UNION UNION 操作符用于合并两个或多个 SELECT 语句的结果集,并自动去除结果集中重复…...
![](https://img-blog.csdnimg.cn/direct/0acc095fcdfe4aa59ee4596c98adbbee.png)
分类判决界面---W-H、H-K算法
本篇文章是博主在人工智能等领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在AI学习笔记&#…...
![](https://img-blog.csdnimg.cn/direct/d8225167d69c4e028830580b73447340.jpeg)
Python基础教程(三十):math模块
💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 💝Ὁ…...
![](https://img-blog.csdnimg.cn/img_convert/4d3fa1a94f7490439e438e8792c491e8.jpeg)
你只是重新发现了一些东西
指北君关于另外一条思维路径的发现。 "自以为是"的顿悟时刻 有很多时候,我会"自以为是"的发现/发明一些东西。这种"自以为是"的时刻通常还带有一些骄傲自豪的情绪。这种感觉特别像古希腊博学家阿基米德 在苦思冥想如何测量不规则物体…...
![](https://img-blog.csdnimg.cn/direct/5b11be156f4e49fda84e9fe4ec19f05d.png)
【英伟达GPU的挑战者】Groq—AI大模型推理的革命者
目录 引言第一部分:Groq简介第二部分:Groq的特点与优势1、高性能推理加速2、近存计算技术3、专用ASIC芯片设计4、低延迟与高吞吐量5、成本效益分析6、易用性与集成性7、软件与硬件的协同设计 第三部分:Groq的使用指南1、准备工作2、简单使用样…...
![](https://img-blog.csdnimg.cn/direct/42043c7098b64c63bf1d7a82ae2cb911.png)
Python学习路线
Python学习路线 领取资料 一、Python基础知识 Python入门:了解Python的安装方法、如何运行Python程序以及交互模式的使用,同时学习注释的添加方法。 数据类型:掌握Python中的各种数据类型,包括数字、布尔值、字符串、列表、元…...
![](https://www.ngui.cc/images/no-images.jpg)
C++ std::forward()
在线调试网站: https://wandbox.org/ #include <iostream> #include <thread> #include <mutex> void func(int &&args) {std::cout << args << std::endl; }int main () {int a 10;func(20); …...
![](https://img-blog.csdnimg.cn/direct/28edbba515494195b2405823ebde7468.png)
常见的8种排序(含代码):插入排序、冒泡排序、希尔排序、快速排序、简单选择排序、归并排序、堆排序、基数排序
时间复杂度O(n^2) 1、插入排序 (Insertion Sort) 从第一个元素开始,该元素可以认为已经被排序;取出下一个元素,在已经排序的元素序列中从后向前扫描;如果该元素(已排序)大于新元素,将该元素移到…...
![](https://img-blog.csdnimg.cn/direct/6bc4a880fa714b7b81c425bf16f1afb4.png)
go语言day2
使用cmd 中的 go install ; go build 命令出现 go cannot find main module 错误怎么解决? go学习-问题记录(开发环境)go: cannot find main module; see ‘go help modules‘_go: no flags specified (see go help mod edit)-CSDN博客 在本…...
![](https://img-blog.csdnimg.cn/direct/a98c1c234384468c9fe674f628ebac52.png)
vue echarts画多柱状图+多折线图
<!--多柱状图折线图--> <div class"echarts-box" id"multiBarPlusLine"></div>import * as echarts from echarts;mounted() {this.getMultiBarPlusLine() },getMultiBarPlusLine() {const container document.getElementById(multiBar…...
![](https://img-blog.csdnimg.cn/direct/0262b350c194473bb416eacf70aa39ac.png)
cesium for unity 打包webgl失败,提示不支持
platform webgl is not supported with HDRP use the Vulkan graphics AR instead....
![](https://www.ngui.cc/images/no-images.jpg)
python开发基础——day7 序列类型方法
一、初识序列类型方法 序列类型的概念:数据的集合,在序列类型里面可以存放任意的数据,也可以对数据进行更方便的操作,这个操作是叫增删改查(crud) ( 增加(Creat),读取查询(Retrieve),更新(Update)…...
![](https://www.ngui.cc/images/no-images.jpg)
用java写一个二叉树翻转
class TreeNode {int val;TreeNode left, right;TreeNode(int val) {this.val val;left right null;} }public class BinaryTree {TreeNode root;// 递归翻转二叉树public TreeNode invertTree(TreeNode root) {if (root null) {return null;}// 递归翻转左子树和右子树Tre…...
![](https://img-blog.csdnimg.cn/direct/32c369aa5895441f8afa5d306e3bec70.png)
数学建模系列(3/4):典型建模方法
目录 引言 1. 回归分析 1.1 线性回归 基本概念 Matlab实现 1.2 多元回归 基本概念 Matlab实现 1.3 非线性回归 基本概念 Matlab实现 2. 时间序列分析 2.1 时间序列的基本概念 2.2 移动平均 基本概念 Matlab实现 2.3 指数平滑 基本概念 Matlab实现 2.4 ARIM…...
![](https://img-blog.csdnimg.cn/img_convert/72d4de823391791ca9d4fa58019ae092.webp?x-oss-process=image/format,png)
AI播客下载:Machine Learning Street Talk(AI机器学习)
该频道由 Tim Scarfe 博士、Yannic Kilcher 博士和 Keith Duggar 博士管理。 他们做了出色的工作,对每个节目进行了彻底的研究,并与机器学习行业中一些受过最高教育、最全面的嘉宾进行了双向对话。 每一集都会教授一些新内容,并且提供未经过滤…...
![](https://img-blog.csdnimg.cn/direct/37928fcb0a6b4ca8a90a3e7cc90ff09a.jpeg)
鱼缸补水器工作原理是什么
鱼缸补水器是一种应用广泛的智能设备,主要用于自动监测和补充鱼缸内的水位,以确保鱼类生存环境的稳定。其工作原理简单而高效,为饲主提供了方便和安全的使用体验。 该补水器通常由两部分组成:控制器和吸盘。首先,用户…...
![](/images/no-images.jpg)
网站建设电话话术/惠州seo关键词排名
UVA_10806这个题目我们可以把边的容量设为1,费用设为权值,然后再引入一条边N-N1,容量设为2,费用设为0,然后去求1到N1的最小费用最大流,如果到N1的流量为2,则输出最小费用,否则就是无…...
![](/images/no-images.jpg)
国外免费服务器地址/黑帽seo是什么意思
1) SE最重要的工作是通过技术交流实现用户对公司的认同。一个销售员的第一步应该是推 销自己的公司,其次推销公司的产品,最后是推销个人魅力。但对于SE来说,SE首先要推 销个人魅力,认同用户并让用户认同自己提供的技术产品&#x…...
![](https://img-blog.csdnimg.cn/img_convert/117411addeccd274ef735573a7b6edab.png)
梧州住房和建设局网站/网店推广方案
GIF图现在已经融入了我们的日常网络生活,微信群、QQ群、朋友圈......一言不合就斗图,你怕了吗?不用担心,只要学会了Python之GIF倒放技能,你就是“斗图王”。咱们直接开始本文的内容!倒放前:倒放…...
![](https://img-blog.csdnimg.cn/img_convert/70fff190bf13cff06e2252910216d2ca.png)
哪些做调查问卷的网站/重庆百度地图
GIT的安装及上传代码到码云参考网址:https://blog.csdn.net/qq_34842671/article/details/70916587一:安装node.js搜索node.js官网,下载对应版本的node.js二:安装好之后,按住winR打开控制面板三:分别输入&a…...
![](https://img-blog.csdnimg.cn/20190317214843182.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dpbnRlcnNoaWk=,size_16,color_FFFFFF,t_70)
web网站开发学习/外贸推广渠道有哪些
操作系统概述 1.操作系统做了什么 我们编写这样一条C语言代码 #include<stdio.h>int main() {puts("hello world");return 0; }1.用户告诉操作系统执行此程序2.操作系统接收到指令,先去磁盘上找到此程序的相关信息,然后检查其类型是否为可执行文件;紧接着通…...
![](/images/no-images.jpg)
中文域名查询网站/百度网页浏览器
第 1 步:集成环信SDK 方式一: 推荐使用Cocoapods集成环信SDK。Cocoapods提供了一个简单的依赖管理系统,避免手动导入产生的错误(首先需要确认已经安装了Cocoapods)。 详情请见http://blog.csdn.net/fantasy_jun/art…...