—— 只有你成功了,才有选择的权力,才会被更多的人尊重。
上一篇我们知道了Button的基本用法,最后讲到了Button的点击事件是通过setOnClickListener方法来实现的。那么APP是如果把用户的点击动作和setOnClickListener关联起来的呢,要弄明白这个问题,我们先来看看APP中是什么时侯处理用户点击动作的。要看问题还得从代码看起,这里以上一篇中的Button基本用法项目举例,打开TestActivity点击事件的主要代码:
| 123456 | button.setOnClickListener(``new View.OnClickListener() {`` ``@Override`` ``public void onClick(View v) {`` ``Toast.makeText(TestActivity.``this``, ``"我被点击了"``, Toast.LENGTH_SHORT).show();`` ``}``}); |
|---|
我们来看setOnClickListener的源码:
| 12345678910111213141516171819202122232425 | /**`` ``* Register a callback to be invoked when this view is clicked. If this view is not`` ``* clickable, it becomes clickable.`` ``*`` ``* @param l The callback that will run`` ``*`` ``* @see #setClickable(boolean)`` ``*/``public void setOnClickListener(``@Nullable OnClickListener l) {`` ``if (!isClickable()) {`` ``setClickable(``true``);`` ``}`` ``getListenerInfo().mOnClickListener = l;``}``注释写的很明白,注册一个当view被点击时的回调方法。可以看到把回调方案OnClickListener传给了getListenerInfo().mOnClickListener,getListenerInfo()跟进去:``static class ListenerInfo {`` ``@UnsupportedAppUsage`` ``ListenerInfo() {`` ``}``...``...``} |
|---|
一个静态类而已,里面定义了一堆接口,包括上面传递的点击事件mOnClickListener ,那么mOnClickListener 什么时侯被调用,view里面有一个onTouchEvent方法:
| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 | /**``*实现此方法以处理触摸屏幕移动事件。``*包括:``*1. 播放单击声音``*2. 调用OnClickListener``*/``public boolean onTouchEvent(MotionEvent event) {`` ``...``...``// 如果是可点击的`` ``if (clickable) {`` ``switch (action) {``// ACTION_UP 手指触摸屏幕抬起事件`` ``case MotionEvent.ACTION_UP:`` ``...``// 如果不可点击的,那么移出所有相关回调,并跳出循环`` ``if (!clickable) {`` ``removeTapCallback();`` ``removeLongPressCallback();`` ``mInContextButtonPress = ``false``;`` ``mHasPerformedLongPress = ``false``;`` ``mIgnoreNextUpEvent = ``false``;`` ``break``;`` ``}``// 如果view是被按下的状态(说明在手指按下时按的是这个view)`` ``if (prepressed) {`` ``boolean focusTaken = ``false``;`` ``if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {`` ``focusTaken = requestFocus();`` ``}`` ``// 设置按下状态`` ``if (prepressed) {`` ``setPressed(``true``, x, y);`` ``}`` ``if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {``// 能到这一步说明是单击事件,那么移除长按事件的回调`` ``removeLongPressCallback();`` ``if (!focusTaken) {`` ``// 创建一个执行点击回调的子线程`` ``if (mPerformClick == ``null``) {`` ``mPerformClick = ``new PerformClick();`` ``}``// 把子线程添加到UI线程的消息对列中等待处理`` ``if (!post(mPerformClick)) {`` ``performClickInternal();`` ``}`` ``}`` ``}`` ``...`` ``removeTapCallback();`` ``} |
|---|
上面那个执行点击回调的子线程:
| 1234567891011121314151617181920 | public boolean performClick() {`` ``...`` ``final boolean result;``// 这里的mListenerInfo就是我们在Activity中setOnClickListener传递过来的`` ``final ListenerInfo li = mListenerInfo;`` ``if (li != ``null && li.mOnClickListener != ``null``) {`` ``playSoundEffect(SoundEffectConstants.CLICK);``// 具体在这执行回调,即Activity中的public void onClick(View v) {...}`` ``li.mOnClickListener.onClick(``this``);`` ``result = ``true``;`` ``} ``else {`` ``result = ``false``;`` ``}`` ``...`` ``return result;``} |
|---|