1. 程式人生 > >onTouch onTouchEvent 與 onClick三者呼叫先後分析

onTouch onTouchEvent 與 onClick三者呼叫先後分析

看程式碼,這裡初始化了一個自定義的TextView,為它設了OnTouchListener和OnClickListener分別對應onTouch和onClick方法:

public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnTouchListener {

    private static final String TAG = "MainActivity";
    private MyTextView myTextView;

    @Override
    protected
void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myTextView = (MyTextView) findViewById(R.id.mytextview); myTextView.setOnClickListener(this); myTextView.setOnTouchListener(this); } @Override
public void onClick(View view) { Log.d(TAG,"onClick"); } @Override public boolean onTouch(View view, MotionEvent motionEvent) { Log.d(TAG,"onTouch"); return false; } }

在自定義的TextView中,我們設定了OnTouchEvent監聽


public class MyTextView extends TextView {
    private
static final String TAG = "MyTextView"; public MyTextView(Context context) { super(context); } public MyTextView(Context context, AttributeSet attrs) { super(context, attrs); } public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } //第一步 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec)); } private int measureHeight(int measureSpec) { int result = 0; int mode = MeasureSpec.getMode(measureSpec); int size = MeasureSpec.getSize(measureSpec); if (mode == MeasureSpec.EXACTLY){ result = size; } else { result = 200; if (mode == MeasureSpec.AT_MOST){ result = Math.min(result,size); } } return result; } private int measureWidth(int measureSpec) { int result = 0; int mode = MeasureSpec.getMode(measureSpec); int size = MeasureSpec.getSize(measureSpec); if (mode == MeasureSpec.EXACTLY){ result = size; } else { result = 200; if (mode == MeasureSpec.AT_MOST){ result = Math.min(result,size); } } return result; } //第二步 @Override protected void onDraw(Canvas canvas) { //繪製文字內容前 super.onDraw(canvas); //繪製文字內容後 } @Override public boolean onTouchEvent(MotionEvent event) { Log.d(TAG,"onTouchEvent"); return super.onTouchEvent(event); } }

可以看到這三個監聽方法我們都打了Log,那我們在下執行過程:

02-16 04:23:48.566 25076-25076/lwp.myview D/MainActivity: onTouch
02-16 04:23:48.566 25076-25076/lwp.myview D/MyTextView: onTouchEvent
02-16 04:23:48.577 25076-25076/lwp.myview D/MainActivity: onTouch
02-16 04:23:48.577 25076-25076/lwp.myview D/MyTextView: onTouchEvent
02-16 04:23:48.584 25076-25076/lwp.myview D/MainActivity: onTouch
02-16 04:23:48.585 25076-25076/lwp.myview D/MyTextView: onTouchEvent
02-16 04:23:48.585 25076-25076/lwp.myview D/SettingsInterface:  from settings cache , name = sound_effects_enabled , value = 0
02-16 04:23:48.585 25076-25076/lwp.myview D/MainActivity: onClick

這裡我們看到,(1)onTouch最先執行,(2)然後是onTouchEvent,由於onTouch返回了false所以onTouchEvent可以執行,在經歷若干次的(1)(2)重複之後,當我手擡起的時候,才會進行onClick操作,對於OnTouch(Activity中setOnTouchListener)->onTouchEvent(view中)->onClick(Activity中setOnClickListener)我們是沒有疑問的,這是在onTouchEvent 返回super.onTouchEvent(event)的情況下並且onTouch返回false,但是如果onTouchEvent返回了false(onTouch返回true我就不說了,因為它一旦返回true,onClick和onTouchEvent就根本不會執行),那麼點選這個TextView一次,無論長按多久,在一次down-(move)-up裡,只會提示一次:

02-16 23:50:00.078 17772-17772/lwp.myview D/MainActivity: onTouch
02-16 23:50:00.088 17772-17772/lwp.myview D/MyTextView: onTouchEvent

好的,讓我們看下這三個按,移,擡,更加深入的看下:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d(TAG,"onTouchEvent");
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                Log.d(TAG,"ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.d(TAG,"ACTION_MOVE");
                break;
            case MotionEvent.ACTION_UP:
                Log.d(TAG,"ACTION_UP");
                break;
        }
//        return super.onTouchEvent(event);
        return false;
//        return false;
    }

Log如下:

02-16 23:53:40.589 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:53:40.589 17772-17772/lwp.myview D/MyTextView: ACTION_DOWN

好的,這樣我們就發現了,當onTouchEvent返回了false,那也就是它在接受到down事件之後返回了false,之後的move,up也就不會交給onTouchEvent處理了,自然就列印一次;那如果是return了true的話,照這個理解,應該是down,up,move都會執行,並且會執行多次,那我們看下:

02-16 23:57:06.467 17772-17772/lwp.myview D/MyTextView: ACTION_MOVE
02-16 23:57:06.485 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:57:06.485 17772-17772/lwp.myview D/MyTextView: ACTION_MOVE
02-16 23:57:06.500 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:57:06.500 17772-17772/lwp.myview D/MyTextView: ACTION_MOVE
02-16 23:57:06.517 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:57:06.517 17772-17772/lwp.myview D/MyTextView: ACTION_MOVE
02-16 23:57:06.534 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:57:06.534 17772-17772/lwp.myview D/MyTextView: ACTION_MOVE
02-16 23:57:06.562 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:57:06.562 17772-17772/lwp.myview D/MyTextView: ACTION_MOVE
02-16 23:57:06.620 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:57:06.620 17772-17772/lwp.myview D/MyTextView: ACTION_MOVE
02-16 23:57:06.656 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:57:06.656 17772-17772/lwp.myview D/MyTextView: ACTION_MOVE
02-16 23:57:06.666 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:57:06.666 17772-17772/lwp.myview D/MyTextView: ACTION_MOVE
02-16 23:57:06.684 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:57:06.685 17772-17772/lwp.myview D/MyTextView: ACTION_MOVE
02-16 23:57:06.706 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:57:06.707 17772-17772/lwp.myview D/MyTextView: ACTION_MOVE
02-16 23:57:06.733 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:57:06.733 17772-17772/lwp.myview D/MyTextView: ACTION_MOVE
02-16 23:57:06.756 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:57:06.756 17772-17772/lwp.myview D/MyTextView: ACTION_MOVE
02-16 23:57:06.773 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:57:06.773 17772-17772/lwp.myview D/MyTextView: ACTION_MOVE
02-16 23:57:06.779 17772-17772/lwp.myview D/MyTextView: onTouchEvent
02-16 23:57:06.779 17772-17772/lwp.myview D/MyTextView: ACTION_UP

看結果,確實如此。
由此,我們的出結論:
1.onTouch返回true,則onTouchEvent和onClick都不會執行;
2.onTouch(onTouchListener)返回false,如果onTouchEvent不是返回super.onTouchEvent(event);也就算是說不管onTouchEvent返回true還是false,onClick(onCLickListener)都不會執行,這可以從super的原始碼看出(原始碼裡會進行判斷執行到OnCLickListener),而且我們知道onClick執行也就會在觸控擡起(up)的時候執行;

相關推薦

onTouch onTouchEvent onClick三者呼叫先後分析

看程式碼,這裡初始化了一個自定義的TextView,為它設了OnTouchListener和OnClickListener分別對應onTouch和onClick方法: public class MainActivity extends AppCompatA

cc++相互呼叫機制分析實現

c++通常被稱為Better c,多數是因為c++程式可以很簡單的呼叫c函式,語法上基本實現相容。最常用的呼叫方式就是c++模組呼叫c實現的dll匯出函式,很簡單的用法,使用extern "C"將c標頭檔案或者函式修飾下。 本文主要涉及到在c模組中如何呼叫c++函式,或者換個名字,extern

finally子句return語句呼叫先後問題及具體原理解析

分析和例子來源於《深入java虛擬機器》一書。 finally語句一定會執行嗎? 答案是不一定。 雖然很多地方都強調一些釋放資源的方法要在finally語句塊中執行,因為finally語句塊一定會執行,但是其實也是有條件的。 finally語

onClick onTouch onTouchEvent呼叫順序

通過原始碼檢視: View – dispatchTouchEvent方法中    可以看出:  onTouchListener的介面的優先順序是要高於onTouchEvent的,假若onTouchListener中的onTouch方法返回true,  表示此次

Android中onTouchonClick兩種監聽的完全解析

之前專案中做一個豎直方向的ViewPager效果(詳見我的另一篇博文),這幾天做了幾個改動,突然發現我設定的OnTouchListener對觸控事件的監聽突然不起作用了,琢磨了半天覺得問題就出在onTouch的返回值true還是false上,後來自己測試的時候發現不光與這個有關,與OnClickLi

《Android群英傳》學習筆記之ActivityActivity呼叫分析

一、Activity 1、Activity形態: Active/Running 處於棧頂,可互動。 Paused 被遮擋但未被完全覆蓋,失去焦點,不可互動。 Stopped 被完全覆蓋,但保持了所有狀

# c++中的複合繼承相關建構函式的呼叫先後

複合關係 #include <iostream> class A{ public: A(int m=0):a(m){ std::cout<<"base's defualt建構函式"<<std::

堆疊、棧幀函式呼叫過程分析

函式呼叫是程式設計中的重要環節,也是程式設計師應聘時常被問及的,本文就函式呼叫的過程進行分析。 一、堆和棧 首先要清楚的是程式對記憶體的使用分為以下幾個區: l         棧區(stack):由編譯器自動分配和釋放,存放函式的引數值,區域性變數的值等。操作方式類似於資料結構中的棧。 l        

Android OnTouchEventOnClick、OnLongClick、OnTouch、TouchDelegate關係

說明:本部落格為原創,轉載請註明出處 http://blog.csdn.net/gucun4848 由於作者水平有限,錯誤在所難免,請見諒,可以留言,本人會及時改正 索引 基於上篇Android Touch事件總結一,本篇介紹To

Socket系統呼叫深度分析

學習一下對Socket與系統呼叫的分析分析 一、介紹 我們都知道高階語言的網路程式設計最終的實現都是呼叫了系統的Socket API程式設計介面,在作業系統提供的socket系統介面之上可以建立不同埠之間的網路連線,從而使我們可以編寫各基於不同網路協議的應用程式。而使用者程式一般都是執行在使用者態,依靠的So

百度推廣:下拉框相關搜索優化分析

營銷型網站建設 競價賬戶托管 網站推廣 全網營銷 我們想要做好百度推廣,就必須根據百度對外展現出來的數據對網站內容進行更新。因為只有這樣,才會讓百度和用戶都漸漸喜歡上我們的網站。那麽,什麽是百度對外展現的數據呢?一個是百度下拉框,一個是百度相關搜索,二者是我們做網站優化一定要分析透徹的。

CentOS7.2通用二進制格式安裝mariadb-5.5.46-linux-x86_64.tar.gz文檔啟動時失敗排查分析

centos7.2通用二進制格式安裝mariadb-5.5.46-linux-x86_64.tar.gzCentOS7.2通用二進制格式安裝mariadb-5.5.46-linux-x86_64.tar.gz提前準備好mariadb-5.5.46-linux-x86_64.tar.gz[[email 

String、StringBufferStringBuilder三者的區別

不可變 abcd ges 區別 ++ 源碼 重新 strong blog 簡單的說: String:創建的是字符串常量,創建的字符串會放入內存的常量池中,是不可變的對象。如果要對String類型的內容進行改變,實際上每次改變都會重新new一個String類型的字符串對象,指

hrefonclick()分別添加this對象

itl round color title undefined obj script clas 對象 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"&

Java - "JUC線程池" 線程狀態拒絕策略源碼分析

int 簡單 his 類型 post 由於 lec java turn Java多線程系列--“JUC線程池”04之 線程池原理(三) 本章介紹線程池的生命周期。在"Java多線程系列--“基礎篇”01之 基本概念"中,我們介紹過,線程有5種狀態:新建狀態,就緒狀態,運

js click onclick 事件綁定解綁

賦值 event blog 標簽 style button 代碼 .net element click 與 onclick 1.onclick 事件會在對象被點擊時發生。 <input id="btn1" type="button" onclick="test(

C#4.0新特性之協變逆變實例分析

alt out thumb def 3.0 介紹 ted 路徑 運行 本文實例講述了C#4.0新特性的協變與逆變,有助於大家進一步掌握C#4.0程序設計。具體分析如下: 一、C#3.0以前的協變與逆變 如果你是第一次聽說這個兩個詞,別擔心,他們其實很常見。C#4.0中

Linux 目錄文件權限分析

line 那是 list tro 到你 什麽 打不開 利用 修改   如果說在Java世界中,萬物皆對象,那麽在Linux世界中,可以說萬物皆文件。Linux文件一般分為兩種,一般文件和目錄文件。文件權限對於數據安全至關重要,有必要清楚的知道一般文件權限和目錄文件權限的意義

Gartner:2017年SIEM(安全信息事件管理)市場分析

gartner siem mq soc 安全管理平臺 2017年度的Gartner SIEM魔力象限在比往常推遲了4個月之後終於發布了。在Gartner眼中,SIEM已經是一個成熟市場。但這個市場依然十分活躍:客戶需求在變化,市場格局也在變化,技術革新也在不斷重塑SIEM自身。讓我們先看矩

SALALchemy Sessionscoped_session的源碼分析

一次 def mov ans resource with alc set val 我們發現Session與scoped_session都有一些方法: 但是scoped_session的源碼裏面沒有設置這些方法讓我們從源碼裏去窺探下源碼在哪裏設置了這些方法: Session裏