您当前的位置:首页 > Android教程

Android开发学习教程(8)- 详解Android Button点击事件原理

时间:2022-01-04 10:20:11 阅读数:15,112人阅读
版权声明:转载请注明出处,谢谢!
—— 只有你成功了,才有选择的权力,才会被更多的人尊重。

上一篇我们知道了Button的基本用法,最后讲到了Button的点击事件是通过setOnClickListener方法来实现的。那么APP是如果把用户的点击动作和setOnClickListener关联起来的呢,要弄明白这个问题,我们先来看看APP中是什么时侯处理用户点击动作的。要看问题还得从代码看起,这里以上一篇中的Button基本用法项目举例,打开TestActivity点击事件的主要代码:

	button.setOnClickListener(new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			Toast.makeText(TestActivity.this, "我被点击了", Toast.LENGTH_SHORT).show();
		}
	});

我们来看setOnClickListener的源码:

	/**
	 * 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方法:

	/**
	*实现此方法以处理触摸屏幕移动事件。
	*包括:
	*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();
					}

上面那个执行点击回调的子线程:

	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;
	}

------转载请注明出处,感谢您对原创作者的支持------

有偿提供技术支持、Bug修复、项目外包、毕业设计、大小作业

Android学习小站

Q Q:1095817610

微信:jx-helu

邮箱:1095817610@qq.com

添加请备注"Android学习小站"