Button's four click events
程序员文章站
2022-07-21 21:18:00
第一种:内部类的方式 第二种:匿名内部类 第三种按钮点击事件:让当前类实现onClickListener接口。 第四种按钮的点击事件: 如果将click方法中的View v去掉或者方法名不是click都会报异常。 原因是什么呢? 查看View源码得知: 查看View源码里面的onClick属性: 里 ......
第一种:内部类的方式
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这个名字,然后通过反射实现。