以前怎么也不能够理解android中的回调事件,比方说点击事件的实现为什么要通过:
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
这样的形式来调用呢。
下面是我上一篇文章中那个试类代码
链接
1.首先是MainActivity.java
public class MainActivity extends Activity {
private MyTextView text;
private MyTopBar topBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (MyTextView) findViewById(R.id.text);
topBar = (MyTopBar) findViewById(R.id.topBar);
topBar.setOnTopBarClickListener(new OnTopBarClickListener() {
@Override
public void rightClick() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "rightButton被点击", Toast.LENGTH_SHORT).show();
}
@Override
public void leftClick() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "leftButton被点击", Toast.LENGTH_SHORT).show();
}
});
}
}
2.然后是MyTopBar
public class MyTopBar extends RelativeLayout{
public static final int LEFT = 0;
public static final int RIGHT = 1;
private String title;
private int titleSize;
private int titleColor;
private String leftText;
private int leftTextSize;
private Drawable leftBackground;
private String rightText;
private int rightTextSize;
private Drawable rightBackground;
private TextView titleText;
private TextView leftButton;
private TextView rightButton;
private LayoutParams titleParams;
private LayoutParams leftParams;
private LayoutParams rightParams;
private OnTopBarClickListener topBarListener;
public MyTopBar(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
//当你在xml布局文件中填写属性时,他会动态查找这个类中的相对应的属性来匹配类型
TypedArray typeArray = getResources().obtainAttributes(attrs, R.styleable.TopBar);
title = typeArray.getString(R.styleable.TopBar_title);
titleSize = (int) typeArray.getDimension(R.styleable.TopBar_titleSize, 0);
titleColor= typeArray.getColor(R.styleable.TopBar_titleColor,Color.WHITE);
leftText = typeArray.getString(R.styleable.TopBar_leftText);
leftTextSize = (int) typeArray.getDimension(R.styleable.TopBar_leftTextSize, 0);
leftBackground = typeArray.getDrawable(R.styleable.TopBar_leftBackground);
rightText = typeArray.getString(R.styleable.TopBar_rightText);
rightTextSize = (int) typeArray.getDimension(R.styleable.TopBar_rightTextSize, 0);
rightBackground = typeArray.getDrawable(R.styleable.TopBar_rightBackground);
titleText = new TextView(context);
leftButton = new TextView(context);
rightButton = new TextView(context);
titleText.setText(title);
titleText.setTextSize(titleSize);
titleText.setTextColor(titleColor);
leftButton.setText(leftText);
leftButton.setTextSize(leftTextSize);
leftButton.setBackground(leftBackground);
rightButton.setText(rightText);
rightButton.setTextSize(rightTextSize);
rightButton.setBackground(rightBackground);
titleParams = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.MATCH_PARENT);
titleParams.addRule(RelativeLayout.CENTER_IN_PARENT);
leftParams = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.MATCH_PARENT);
leftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
rightParams = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.MATCH_PARENT);
rightParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
typeArray.recycle();
addView(titleText, titleParams);
addView(leftButton, leftParams);
addView(rightButton, rightParams);
leftButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
topBarListener.leftClick();
}
});
rightButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
topBarListener.rightClick();
}
});
}
public interface OnTopBarClickListener{
void leftClick();
void rightClick();
}
public void setOnTopBarClickListener(OnTopBarClickListener topBarListener){
this.topBarListener = topBarListener;
}
public void setBtnVisible(int id,boolean flag){
if(id == LEFT){
if(flag){
leftButton.setVisibility(View.VISIBLE);
}else{
leftButton.setVisibility(View.GONE);
}
}else{
if(flag){
rightButton.setVisibility(View.VISIBLE);
}else{
rightButton.setVisibility(View.GONE);
}
}
}
}
上面的代码太多,我把代码拿出来看,
1 . 首先在MyTopBar中定义一个public 的接口如下
public interface OnTopBarClickListener{
void leftClick();
void rightClick();
}
2. 然后提供一个公众方法用以设置接口的实例对象
public void setOnTopBarClickListener(OnTopBarClickListener topBarListener){
this.topBarListener = topBarListener;
}
3. 当左右俩边的按钮被点击时,调用回调的方法。
leftButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
topBarListener.leftClick();
}
});
rightButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
topBarListener.rightClick();
}
});
可是,有人会这样问,当左右俩边的按钮被点击时,他们下的topBarListener.rightClick(),并没有看到此方法的定义啊,这个就是重点了,往下看。
4. 在MainActivity中
topBar.setOnTopBarClickListener(new OnTopBarClickListener() {
@Override
public void rightClick() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "rightButton被点击", Toast.LENGTH_SHORT).show();
}
@Override
public void leftClick() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "leftButton被点击", Toast.LENGTH_SHORT).show();
}
});
可以看到MyTopBar中的方法实现在这里,这就令人很纳闷了,这时怎么回事。
首先我们来分析一下:new OnTopBarClickListener() {
@Override
public void rightClick() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "rightButton被点击", Toast.LENGTH_SHORT).show();
}
@Override
public void leftClick() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "leftButton被点击", Toast.LENGTH_SHORT).show();
}
}
这段代码是new 实例化了一个匿名内部对象类。
什么事匿名内部对象类?
匿名对象类:一般是一个对象只会被用到一次,如果单独放到一个文件中,觉得没必要。然后匿名对象类用于 :
某个抽象类或者接口的实例只会被用到一次。
然后通过 new 关键字产生一个匿名对象类。
接着看上面的topBar.setOnTopBarClickListener();
通过这个方法我们将昕创建的匿名对象类传递给了MyTopBar,这样的话,当按钮被点击的时候,他调用的是我们匿名对象的方法。
使用匿名对象内部类的好处:匿名对象类可以使用当前类中任何私有属性与方法,这种方式非常方便,我们在另外一个类里面面调用方法,然后回调过来可以使用当前类中的方法,是不是很变态啊。
完整试类在前面一篇博客中有完整的代码。