第一种:内部类的方式
1 package com.example.phonedialer;
2
3 import com.example.click2.R;
4
5 import android.net.Uri;
6 import android.os.Bundle;
7 import android.app.Activity;
8 import android.content.Intent;
9 import android.view.Menu;
10 import android.view.View;
11 import android.view.View.OnClickListener;
12 import android.widget.Button;
13 import android.widget.EditText;
14 import android.widget.Toast;
15
16 public class MainActivity extends Activity {
17
18 private EditText et_number;
19
20
21 @Override
22 protected void onCreate(Bundle savedInstanceState) {
23 super.onCreate(savedInstanceState);
24 //加载一个布局
25 setContentView(R.layout.activity_main);
26 //找到我们关心的控件;通过源码得知EditText继承TextView,TextView继承自View,所以可以这样写。
27 et_number = (EditText) findViewById(R.id.editText1);
28
29 //找到按钮;通过源码得知Button继承自TextView,TextView继承自View,所以可以这样写。
30 Button btn_call = (Button) findViewById(R.id.button1);
31 /**
32 * 方法里面接收的参数是OnClickListener类型,发现它是一个接口类型。
33 * Interface definition for a callback to be invoked when a view is clicked.
34 * 定义了一个接口类型,注册了一个回调事件,当一个view被点击的时候走这个回调方法。
35 */
36 btn_call.setOnClickListener(new MyClickListener());
37 /**
38 * 这里的this(context也就是上下文的意思),代表MainActivity。查看源码可以得知
39 * MainActivity继承自Context.
40 */
41 //Toast.makeText(this, text, duration)
42
43 }
44 /**
45 * 定义一个类,去实现按钮需要的接口类型
46 */
47 private class MyClickListener implements OnClickListener {
48
49 /**
50 * Called when a view has been clicked.
51 * 当按钮已经被点击的时候调用该方法。
52 */
53 @Override
54 public void onClick(View v) {
55 /**
56 * 获取EditText控件的文本内容,第一时间想到通过et_number来获取,
57 * 但是这个变量不是全局变量,获取不到。所以需要将它变成全局变量。
58 * Return the text the TextView is displaying
59 * 返回TextView显示的内容。
60 * Editable android.widget.EditText.getText()
61 */
62 String number = et_number.getText().toString().trim();
63 if("".equals(number)) {
64 /**
65 * context上下文
66 * The method makeText(Context, CharSequence, int)
67 * in the type Toast is not applicable for the arguments (MainActivity.MyClickListener, String, int)
68 * 这里的this代表的是MainActivity.MyClickListener,需要的是一个Context,所以编译报错。
69 * 通过类名.this可以设置吐司要在哪个Activity显示。LENGTH_SHORT 0 LENGTH_LONG 1
70 */
71 Toast.makeText(MainActivity.this, "number不能为空", Toast.LENGTH_SHORT).show();
72 return;
73 }
74 //拿到number进行拨打电话.
75 /**
76 * 因为拨打电话的代码谷歌工程师已经写好了,所以不需要我们手动写逻辑,我们只需要
77 * 把它调起来就可以了。意图:Intent
78 */
79 Intent intent = new Intent();
80 //设置动作 打电话。
81 intent.setAction(Intent.ACTION_CALL);
82 //设置打的数据 uri数据。Uri data
83 /**
84 * Url:统一资源定位符
85 * Uri:统一资源标识符 自己定义的路径想代表什么就代表什么。
86 */
87 intent.setData(Uri.parse("tel:"+number));
88 //开启意图
89 startActivity(intent);
90
91
92
93 }
94
95 }
96
97
98
99 @Override
100 public boolean onCreateOptionsMenu(Menu menu) {
101 // Inflate the menu; this adds items to the action bar if it is present.
102 getMenuInflater().inflate(R.menu.main, menu);
103 return true;
104 }
105
106 }
第二种:匿名内部类
1 package com.example.phonedialer;
2
3 import com.example.click3.R;
4
5 import android.net.Uri;
6 import android.os.Bundle;
7 import android.app.Activity;
8 import android.content.Intent;
9 import android.view.Menu;
10 import android.view.View;
11 import android.view.View.OnClickListener;
12 import android.widget.Button;
13 import android.widget.EditText;
14 import android.widget.Toast;
15
16 public class MainActivity extends Activity {
17
18 private EditText et_number;
19
20
21 @Override
22 protected void onCreate(Bundle savedInstanceState) {
23 super.onCreate(savedInstanceState);
24 //加载一个布局
25 setContentView(R.layout.activity_main);
26 //找到我们关心的控件;通过源码得知EditText继承TextView,TextView继承自View,所以可以这样写。
27 et_number = (EditText) findViewById(R.id.editText1);
28
29 //找到按钮;通过源码得知Button继承自TextView,TextView继承自View,所以可以这样写。
30 Button btn_call = (Button) findViewById(R.id.button1);
31 /**
32 * 方法里面接收的参数是OnClickListener类型,发现它是一个接口类型。
33 * Interface definition for a callback to be invoked when a view is clicked.
34 * 定义了一个接口类型,注册了一个回调事件,当一个view被点击的时候走这个回调方法。
35 */
36 // btn_call.setOnClickListener(new MyClickListener());
37 btn_call.setOnClickListener(new OnClickListener() {
38
39 @Override
40 public void onClick(View v) {
41 // TODO Auto-generated method stub
42 /**
43 * 获取EditText控件的文本内容,第一时间想到通过et_number来获取,
44 * 但是这个变量不是全局变量,获取不到。所以需要将它变成全局变量。
45 * Return the text the TextView is displaying
46 * 返回TextView显示的内容。
47 * Editable android.widget.EditText.getText()
48 */
49 String number = et_number.getText().toString().trim();
50 if("".equals(number)) {
51 /**
52 * context上下文
53 * The method makeText(Context, CharSequence, int)
54 * in the type Toast is not applicable for the arguments (MainActivity.MyClickListener, String, int)
55 * 这里的this代表的是MainActivity.MyClickListener,需要的是一个Context,所以编译报错。
56 * 通过类名.this可以设置吐司要在哪个Activity显示。LENGTH_SHORT 0 LENGTH_LONG 1
57 */
58 Toast.makeText(MainActivity.this, "number不能为空", Toast.LENGTH_SHORT).show();
59 return;
60 }
61 //拿到number进行拨打电话.
62 /**
63 * 因为拨打电话的代码谷歌工程师已经写好了,所以不需要我们手动写逻辑,我们只需要
64 * 把它调起来就可以了。意图:Intent
65 */
66 Intent intent = new Intent();
67 //设置动作 打电话。
68 intent.setAction(Intent.ACTION_CALL);
69 //设置打的数据 uri数据。Uri data
70 /**
71 * Url:统一资源定位符
72 * Uri:统一资源标识符 自己定义的路径想代表什么就代表什么。
73 */
74 intent.setData(Uri.parse("tel:"+number));
75 //开启意图
76 startActivity(intent);
77 }
78 });
79
80 }
81
82
83
84 @Override
85 public boolean onCreateOptionsMenu(Menu menu) {
86 // Inflate the menu; this adds items to the action bar if it is present.
87 getMenuInflater().inflate(R.menu.main, menu);
88 return true;
89 }
90
91 }
第三种按钮点击事件:让当前类实现onClickListener接口。
1 package com.example.phonedialer;
2
3 import com.example.click3.R;
4
5 import android.net.Uri;
6 import android.os.Bundle;
7 import android.app.Activity;
8 import android.content.Intent;
9 import android.view.Menu;
10 import android.view.View;
11 import android.view.View.OnClickListener;
12 import android.widget.Button;
13 import android.widget.EditText;
14 import android.widget.Toast;
15
16 public class MainActivity extends Activity implements OnClickListener {
17
18 private EditText et_number;
19 private Button btn_call;
20 private Button btn_call1;
21 private Button btn_call2;
22 private Button btn_call3;
23
24 @Override
25 protected void onCreate(Bundle savedInstanceState) {
26 super.onCreate(savedInstanceState);
27 // 加载一个布局
28 setContentView(R.layout.activity_main);
29 // 找到我们关心的控件;通过源码得知EditText继承TextView,TextView继承自View,所以可以这样写。
30 et_number = (EditText) findViewById(R.id.editText1);
31
32 btn_call = (Button) findViewById(R.id.button1);
33 btn_call1 = (Button) findViewById(R.id.button2);
34 btn_call2 = (Button) findViewById(R.id.button3);
35 btn_call3 = (Button) findViewById(R.id.button4);
36 /**
37 * 方法里面接收的参数是OnClickListener类型,发现它是一个接口类型。 Interface definition for a
38 * callback to be invoked when a view is clicked.
39 * 定义了一个接口类型,注册了一个回调事件,当一个view被点击的时候走这个回调方法。
40 */
41 // btn_call.setOnClickListener(new MyClickListener());
42 btn_call.setOnClickListener(this);
43 btn_call1.setOnClickListener(this);
44 btn_call2.setOnClickListener(this);
45 btn_call3.setOnClickListener(this);
46
47 }
48
49 @Override
50 public boolean onCreateOptionsMenu(Menu menu) {
51 // Inflate the menu; this adds items to the action bar if it is present.
52 getMenuInflater().inflate(R.menu.main, menu);
53 return true;
54 }
55
56 @Override
57 public void onClick(View v) {
58 // 具体判断点击的是哪个按钮
59 switch (v.getId()) {
60 case R.id.button1:
61 callPhone(btn_call);
62 break;
63 case R.id.button2:
64 callPhone(btn_call1);
65 break;
66 case R.id.button3:
67 callPhone(btn_call2);
68 break;
69 case R.id.button4:
70 callPhone(btn_call3);
71 break;
72
73 default:
74 break;
75 }
76 }
77
78 private void callPhone(Button btn_call) {
79 btn_call.setOnClickListener(new OnClickListener() {
80
81 @Override
82 public void onClick(View v) {
83 // TODO Auto-generated method stub
84 /**
85 * 获取EditText控件的文本内容,第一时间想到通过et_number来获取,
86 * 但是这个变量不是全局变量,获取不到。所以需要将它变成全局变量。 Return the text the TextView
87 * is displaying 返回TextView显示的内容。 Editable
88 * android.widget.EditText.getText()
89 */
90 String number = et_number.getText().toString().trim();
91 if ("".equals(number)) {
92 /**
93 * context上下文 The method makeText(Context, CharSequence,
94 * int) in the type Toast is not applicable for the
95 * arguments (MainActivity.MyClickListener, String, int)
96 * 这里的this代表的是MainActivity
97 * .MyClickListener,需要的是一个Context,所以编译报错。
98 * 通过类名.this可以设置吐司要在哪个Activity显示。LENGTH_SHORT 0 LENGTH_LONG
99 * 1
100 */
101 Toast.makeText(MainActivity.this, "number不能为空",
102 Toast.LENGTH_SHORT).show();
103 return;
104 }
105 // 拿到number进行拨打电话.
106 /**
107 * 因为拨打电话的代码谷歌工程师已经写好了,所以不需要我们手动写逻辑,我们只需要 把它调起来就可以了。意图:Intent
108 */
109 Intent intent = new Intent();
110 // 设置动作 打电话。
111 intent.setAction(Intent.ACTION_CALL);
112 // 设置打的数据 uri数据。Uri data
113 /**
114 * Url:统一资源定位符 Uri:统一资源标识符 自己定义的路径想代表什么就代表什么。
115 */
116 intent.setData(Uri.parse("tel:" + number));
117 // 开启意图
118 startActivity(intent);
119 }
120 });
121
122 }
123 }
第四种按钮的点击事件:
1 package com.example.phonedialer;
2
3 import com.example.click4.R;
4
5 import android.net.Uri;
6 import android.os.Bundle;
7 import android.app.Activity;
8 import android.content.Intent;
9 import android.view.Menu;
10 import android.view.View;
11 import android.view.View.OnClickListener;
12 import android.widget.Button;
13 import android.widget.EditText;
14 import android.widget.Toast;
15
16 public class MainActivity extends Activity implements OnClickListener {
17
18 private EditText et_number;
19 private Button btn_call;
20 private Button btn_call1;
21 private Button btn_call2;
22 private Button btn_call3;
23 private Button btn_call4;
24
25 @Override
26 protected void onCreate(Bundle savedInstanceState) {
27 super.onCreate(savedInstanceState);
28 // 加载一个布局
29 setContentView(R.layout.activity_main);
30 // 找到我们关心的控件;通过源码得知EditText继承TextView,TextView继承自View,所以可以这样写。
31 et_number = (EditText) findViewById(R.id.editText1);
32
33 btn_call = (Button) findViewById(R.id.button1);
34 btn_call1 = (Button) findViewById(R.id.button2);
35 btn_call2 = (Button) findViewById(R.id.button3);
36 btn_call3 = (Button) findViewById(R.id.button4);
37 btn_call4 = (Button) findViewById(R.id.button5);
38 /**
39 * 方法里面接收的参数是OnClickListener类型,发现它是一个接口类型。 Interface definition for a
40 * callback to be invoked when a view is clicked.
41 * 定义了一个接口类型,注册了一个回调事件,当一个view被点击的时候走这个回调方法。
42 */
43 // btn_call.setOnClickListener(new MyClickListener());
44 btn_call.setOnClickListener(this);
45 btn_call1.setOnClickListener(this);
46 btn_call2.setOnClickListener(this);
47 btn_call3.setOnClickListener(this);
48
49 }
50
51 public void click(View v) {
52
53 callPhone(btn_call4);
54 }
55
56 @Override
57 public boolean onCreateOptionsMenu(Menu menu) {
58 // Inflate the menu; this adds items to the action bar if it is present.
59 getMenuInflater().inflate(R.menu.main, menu);
60 return true;
61 }
62
63 @Override
64 public void onClick(View v) {
65 // 具体判断点击的是哪个按钮
66 switch (v.getId()) {
67 case R.id.button1:
68 callPhone(btn_call);
69 break;
70 case R.id.button2:
71 callPhone(btn_call1);
72 break;
73 case R.id.button3:
74 callPhone(btn_call2);
75 break;
76 case R.id.button4:
77 callPhone(btn_call3);
78 break;
79
80 default:
81 break;
82 }
83 }
84
85 private void callPhone(Button btn_call) {
86 btn_call.setOnClickListener(new OnClickListener() {
87
88 @Override
89 public void onClick(View v) {
90 // TODO Auto-generated method stub
91 /**
92 * 获取EditText控件的文本内容,第一时间想到通过et_number来获取,
93 * 但是这个变量不是全局变量,获取不到。所以需要将它变成全局变量。 Return the text the TextView
94 * is displaying 返回TextView显示的内容。 Editable
95 * android.widget.EditText.getText()
96 */
97 String number = et_number.getText().toString().trim();
98 if ("".equals(number)) {
99 /**
100 * context上下文 The method makeText(Context, CharSequence,
101 * int) in the type Toast is not applicable for the
102 * arguments (MainActivity.MyClickListener, String, int)
103 * 这里的this代表的是MainActivity
104 * .MyClickListener,需要的是一个Context,所以编译报错。
105 * 通过类名.this可以设置吐司要在哪个Activity显示。LENGTH_SHORT 0 LENGTH_LONG
106 * 1
107 */
108 Toast.makeText(MainActivity.this, "number不能为空",
109 Toast.LENGTH_SHORT).show();
110 return;
111 }
112 // 拿到number进行拨打电话.
113 /**
114 * 因为拨打电话的代码谷歌工程师已经写好了,所以不需要我们手动写逻辑,我们只需要 把它调起来就可以了。意图:Intent
115 */
116 Intent intent = new Intent();
117 // 设置动作 打电话。
118 intent.setAction(Intent.ACTION_CALL);
119 // 设置打的数据 uri数据。Uri data
120 /**
121 * Url:统一资源定位符 Uri:统一资源标识符 自己定义的路径想代表什么就代表什么。
122 */
123 intent.setData(Uri.parse("tel:" + number));
124 // 开启意图
125 startActivity(intent);
126 }
127 });
128
129 }
130 }
如果将click方法中的View v去掉或者方法名不是click都会报异常。
原因是什么呢?
查看View源码得知:
查看View源码里面的onClick属性:
里面有一行 1 mHandler = getContext().getClass().getMethod(handlerName, 2 View.class); 这样的代码,拿到一个上下文对象的字节码文件(反射)。其中handlerName是onClick属性的名字click,而View.class是该方法需要传入的参数。
handlerName是怎么来的呢?
1 final String handlerName = a.getString(attr);是通过a拿到的。handlerName其实就是click。
a是什么呢?
1 public View(Context context, AttributeSet attrs, int defStyle) {
2 this(context);
3
4 TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
5 defStyle, 0);
从这段代码可以得知,通过attrs这个对象就找到了click这个名字,然后通过反射实现。