當前位置:首頁 » 安卓系統 » androidview事件

androidview事件

發布時間: 2022-08-14 19:46:34

㈠ android 自定義view滑動和點擊事件沖突怎麼解決

在Android中,對一個View同時調用OnTouch事件和OnClick事件時,導致事件沖突,比如onClick事件打算執行A動作,OnTouch事件打算執行B動作,但是在實際使用時會發現,當調用OnTouch時,有可能會同時執行A,B兩個動作,這是因為OnClick事件本身就是在OnTouch事件中發生的;在onTouch事件中,如果返回true,就不會執行onClick,返回false,就同時執行onClick方法,要想把OnTouch和onClick事件完全的區分。可能過下列方法,解決該沖突問題:
就是在 OnTouch中的MotionEvent.ACTION_DOWN 時,記錄下點(X1,Y1),
在 MotionEvent.ACTION_UP 時,記錄下點(X2,Y2),然後比對 倆點之間的距離,如果小於一個較小數值(比如5),就認為是Click事件,onTouch中返回false,如果距離較大,可以當作onTouch事件去處理,返回true:
示範如下:
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
x1 = event.getX();
y1 = event.getY();
}
if (event.getAction() == MotionEvent.ACTION_UP) {
x2 = event.getX();
y2 = event.getY();
if (Math.abs(x1 - x2) < 6) {
return false;// 距離較小,當作click事件來處理
}
if(Math.abs(x1 - x2) >60){ // 真正的onTouch事件
}
}
return true;// 返回true,不執行click事件
}

㈡ android怎麼用代碼讓一個view執行點擊事件

view.setOnClickListener(new View.OnClickListener() {//視圖設置一個點擊事件的監聽器
@Override
public void onClick(View v) {//重寫點擊事件的回調方法
//在這里添加點擊後要執行的代碼
}
});

㈢ android中的View是做什麼的

View類是Android的一個超類,這個類幾乎包含了所有的屏幕類型。每一個View都有一個用於繪圖的畫布,這個畫布可以進行任意擴展。在游戲開發中葉可以自定義視圖(View),這個畫布的功能更能滿足我們在游戲開發中的需要。在Android中,任何一個View類都只需重寫onDraw 方法來實現界面顯示,自定義的視圖可以是復雜的3D實現,也可以是非常簡單的文本形式等。

游戲中最重要的就是需要與玩家交互,比如鍵盤輸入、觸筆點擊事件,我們如何來處理這些事件呢?Android中提供了 onKeyUp、onKeyDown、onKeyMultiple、onKeyPreIme、onTouchEvent、onTrackballEvent等方法,可以輕松地處理游戲中的事件信息。所以,在繼承View時,需要重載這幾個方法,當有按鍵按下或彈起等事件時,按鍵代碼自動會傳輸給這些相應的方法來處理。

游戲的核心是不斷地繪圖和刷新界面,圖我們已經通過onDraw 方法繪制了,下面來分析如何刷新界面。Android中提供了 invalidate 方法來實現界面刷新,注意,invalidate 不能直接在線程中調用, 就是不可以在子線程中調用明白乎?因為它違背了 Android的單線程模型:Android UI操作並不是線程安全的,並且這些操作必須在UI 線程中執行,因此Android中最常用的方法就是利用Handler來實現UI線程的更新。 其實用 AsyncTask 也可以。

㈣ Android中怎麼去判斷點擊事件中的View

每一個View都有一個Id(R.id.viewId)、在你onclick(View v)這個方法中、v既是你點擊對象的view、但是怎麼去判斷是不是你點擊的那個view就直接可以由v.getId() == R.id.viewId來判斷是否為點擊事件的view

㈤ 誰可以解釋下,android事件分發為什麼要設計成從根view到子view,而不是從子vie

Android事件傳遞流程在網上可以找到很多資料,FrameWork層輸入事件和消費事件,可以參考:
Touch事件派發過程詳解
這篇blog闡述了底層是如何處理屏幕輸,並往上傳遞的。Touch事件傳遞到Activity的DecorView時,往下走就是ViewGroup和子View之間的事件傳遞,可以參考郭神的這兩篇博客
Android事件分發機制完全解析,帶你從源碼的角度徹底理解(上)
Android事件分發機制完全解析,帶你從源碼的角度徹底理解(下)
郭神的兩篇博客清楚明白地說明了View之間事件傳遞的大方向,但是具體的一些晦暗的細節闡述較少,本文主要是總結這兩篇博客的同時,側重於兩點:
事件分發過程中一些細節到底如何實現的?
子view到底如何和父View搶事件,父View又是如何攔截事件不發送給子View,以及如果我們需要處理這種混亂的關系才能讓兩者和諧相處?。
MotionEvent抽象
要明白View的事件傳遞,很有必要先說一下Touch事件是如何在Android系統中抽象的,這主要使用的就是MotionEvent。這個類經歷了幾次重大的修改,一次是在2.x版本支持多點觸摸,一次是4.x將大部分代碼甩給native層處理。
一次簡單的事件
我們先舉個栗子來說明一次完整的事件,用戶觸屏 滑動 到手機離開屏幕,這認為是一次完整動作序列(movement traces)。一個動作序列中包含很多動作Action,比如在用戶按下時,會封裝一個MotionEvent,分發給視圖樹,我們可以通過motionevent.getAction拿到這個動作是ACTION_DOWN。同樣,在手指抬起時,我們可以接收到Action類型是Action_UP的MotionEvent。對於滑動(MOVE)這個操作,Android為了從效率出發,會將多個MOVE動作打包到一個MotionEvent中。通過getX getY可以獲取當前的坐標,如果要訪問打包的緩存數據,可以通過getHistorical**()函數來獲取。
加入多點觸摸
對於單點的操作來看,MotionEvent顯得比較簡單,但是考慮引入多點觸摸呢?我們定義一個接觸點為(Pointer)。每一個觸摸點Pointer都會有一個當次動作序列的唯一Id和Index.MotionEvent中多個手指的操作API大部分都是通過pointerindex來進行的,如:獲取不同Pointer的觸碰位置,getX(int pointerIndex);獲取PointerId等等。大部分情況下,pointerid == pointeridex。
我們從onTouch接受到一個MotionEvent,怎麼拿到多個觸碰點的信息?為了解開筆者剛開始學習這部分知識時的困惑,我們首先樹立起一種概念:一個MotionEvent只允許有一個Action(動作),而且這個Action會包含觸發這次Action的觸碰點信息,對於MOVE操作來說,一定是當前所有觸碰點都在動。只有ACTION_POINTER_DOWN這類事件事件會在Action裡面指定是哪一個POINTER按下。
在MotionEvent的底層實現中,是通過一個16位來存儲Action和Pointer信息(PointerIndex)。低8位表示Action,理論上可以表示255種動作類型;高8位表示觸發這個Action的PointerIndex,理論上Android最多可以支持255點同時觸摸,但是在上層代碼使用的時候,默認多點最多存在32個,不然事件在分發的時候會有問題。
ACTION_DOWN OR ACTION_POINTER_DOWN:
這兩個按下操作的區別是ACTION_DOWN是一個系列動作的開始,而ACTION_POINTER_DOWN是在一個系列動作中間有另外一個觸碰點觸碰到屏幕。
這部分詳細的描述,請參考:
android觸控,先了解MotionEvent
到這里,鋪墊終於結束了,我們開始直奔主題。
View的事件傳遞
Android的Touch事件傳遞到Activity頂層的DecorView(一個FrameLayout)之後,會通過ViewGroup一層層往視圖樹的上面傳遞,最終將事件傳遞給實際接收的View。下面給出一些重要的方法。如果你對這個流程比較熟悉的話,可以跳過這里,直接進入第二部分。
dispatchTouchEvent
事件傳遞到一個ViewGroup上面時,會調用dispatchTouchEvent。代碼有刪減
public boolean dispatchTouchEvent(MotionEvent ev) {

boolean handled = false;
if (onFilterTouchEventForSecurity(ev)) {
final int action = ev.getAction();
final int actionMasked = action & MotionEvent.ACTION_MASK;

// Attention 1 :在按下時候清除一些狀態
if (actionMasked == MotionEvent.ACTION_DOWN) {
cancelAndClearTouchTargets(ev);
//注意這個方法
resetTouchState();
}

// Attention 2:檢查是否需要攔截
final boolean intercepted;
//如果剛剛按下 或者 已經有子View來處理
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
// 不是一個動作序列的開始 同時也沒有子View來處理,直接攔截
intercepted = true;
}

//事件沒有取消 同時沒有被當前ViewGroup攔截,去找是否有子View接盤
if (!canceled && !intercepted) {
//如果這是一系列動作的開始 或者有一個新的Pointer按下 我們需要去找能夠處理這個Pointer的子View
if (actionMasked == MotionEvent.ACTION_DOWN
|| (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN)
|| actionMasked == MotionEvent.ACTION_HOVER_MOVE) {
final int actionIndex = ev.getActionIndex(); // always 0 for down

//上面說的觸碰點32的限制就是這里導致
final int idBitsToAssign = split ? 1 << ev.getPointerId(actionIndex)
: TouchTarget.ALL_POINTER_IDS;

final int childrenCount = mChildrenCount;
if (newTouchTarget == null && childrenCount != 0) {
final float x = ev.getX(actionIndex);
final float y = ev.getY(actionIndex);

//對當前ViewGroup的所有子View進行排序,在上層的放在開始
final ArrayList<View> preorderedList = buildOrderedChildList();
final boolean customOrder = preorderedList == null
&& isChildrenDrawingOrderEnabled();
final View[] children = mChildren;
for (int i = childrenCount - 1; i >= 0; i--) {
final int childIndex = customOrder
? getChildDrawingOrder(childrenCount, i) : i;
final View child = (preorderedList == null)
? children[childIndex] : preorderedList.get(childIndex);

// canViewReceivePointerEvents visible的View都可以接受事件
// isTransformedTouchPointInView 計算是否落在點擊區域上
if (!canViewReceivePointerEvents(child)
|| !isTransformedTouchPointInView(x, y, child, null)) {
ev.setTargetAccessibilityFocus(false);
continue;
}

//能夠處理這個Pointer的View是否已經處理之前的Pointer,那麼把
newTouchTarget = getTouchTarget(child);
if (newTouchTarget != null) {
// Child is already receiving touch within its bounds.
// Give it the new pointer in addition to the ones it is handling.
newTouchTarget.pointerIdBits |= idBitsToAssign;
break;
} }
//Attention 3 : 直接發給子View
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
// Child wants to receive touch within its bounds.
mLastTouchDownTime = ev.getDownTime();
if (preorderedList != null) {
// childIndex points into presorted list, find original index
for (int j = 0; j < childrenCount; j++) {
if (children[childIndex] == mChildren[j]) {
mLastTouchDownIndex = j;
break;
}
}
} else {
mLastTouchDownIndex = childIndex;
}
mLastTouchDownX = ev.getX();
mLastTouchDownY = ev.getY();
newTouchTarget = addTouchTarget(child, idBitsToAssign);
= true;
break;
}

}
}

}
}

// 前面已經找到了接收事件的子View,如果為NULL,表示沒有子View來接手,當前ViewGroup需要來處理
if (mFirstTouchTarget == null) {
// ViewGroup處理
handled = dispatchTransformedTouchEvent(ev, canceled, null,
TouchTarget.ALL_POINTER_IDS);
} else {

if() {
//ignore some code
if (dispatchTransformedTouchEvent(ev, cancelChild,
target.child, target.pointerIdBits)) {
handled = true;
}
}

}
return handled;
}

上面代碼中的Attention在後面部分將會涉及,重點注意。
這里需要指出一點的是,一系列動作中的不同Pointer可以分配給不同的View去響應。ViewGroup會維護一個PointerId和處理View的列表TouchTarget,一個TouchTarget代表一個可以處理Pointer的子View,當然一個View可以處理多個Pointer,比如兩根手指都在某一個子View區域。TouchTarget內部使用一個int來存儲它能處理的PointerId,一個int32位,這也就是上層為啥最多隻能允許同時最多32點觸碰。
看一下Attention 3 處的代碼,我們經常說view的dispatchTouchEvent如果返回false,那麼它就不能系列動作後面的動作,這是為啥呢?因為Attention 3處如果返回false,那麼它不會被記錄到TouchTarget中,ViewGroup認為你沒有能力處理這個事件。
這里可以看到,ViewGroup真正處理事件是在dispatchTransformedTouchEvent裡面,跟進去看看:
dispatchTransformedTouchEvent
private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
View child, int desiredPointerIdBits) {

//沒有子類處理,那麼交給viewgroup處理
if (child == null) {
handled = super.dispatchTouchEvent(transformedEvent);
} else {
final float offsetX = mScrollX - child.mLeft;
final float offsetY = mScrollY - child.mTop;
transformedEvent.offsetLocation(offsetX, offsetY);
if (! child.hasIdentityMatrix()) {
transformedEvent.transform(child.getInverseMatrix());
}

handled = child.dispatchTouchEvent(transformedEvent);
}
return handled;
}

可以看到這里不管怎麼樣,都會調用View的dispatchTouchEvent,這是真正處理這一次點擊事件的地方。
dispatchTouchEvent
public boolean dispatchTouchEvent(MotionEvent event) {
if (onFilterTouchEventForSecurity(event)) {
//先走View的onTouch事件,如果onTouch返回True
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}

if (!result && onTouchEvent(event)) {
result = true;
}
}
return result;
}

我們給View設置的onTouch事件處在一個較高的優先順序,如果onTouch執行返回true,那麼就不會去走view的onTouchEvent,而我們一些點擊事件都是在onTouchEvent中處理的,這也是為什麼onTouch中返回true,view的點擊相關事件不會被處理。

㈥ android 判斷view是否有設置了點擊事件

在對一個VIEW注冊單擊事件監聽後,onTouchEvent中是無法接收到該VIEW中的DOWN事件的,這其中有著一個事件傳遞的過程,介意你可以去查下,提供你一個解決方法:你可以使用setOnTouchListener來處理這個ImageView的點擊事件,OnTouchListener裡面的方法onTouch是有返回值的,返回true則說明已處理完畢不會再繼續傳遞這個事件;返回false則說明未處理完畢需要繼續傳遞這個事件,按你現在的問題,你應當返回false。

㈦ android 如何獲取一個界面最頂層的view並處理單擊事件的分發機制

android事件分發機制 就是一個觸摸事件發生了,從一個窗口傳遞到一個視圖,再傳遞到另外一個視圖,最後被消費的過程,在android中還是比較復雜的傳遞流程如下:

(1) 事件從Activity.dispatchTouchEvent()開始傳遞,只要沒有被停止或攔截,從最上層的View(ViewGroup)開始一直往下(子View)傳遞。子View可以通過onTouchEvent()對事件進行處理。

(2) 事件由父View(ViewGroup)傳遞給子View,ViewGroup可以通過onInterceptTouchEvent()對事件做攔截,停止其往下傳遞。

㈧ 如何監聽android view的生命周期

android view有以下14個周期:
1、onFinishInflate() 當View中所有的子控制項均被映射成xml後觸發 。
2、onMeasure( int , int ) 確定所有子元素的大小 。
3、onLayout( boolean , int , int , int , int ) 當View分配所有的子元素的大小和位置時觸發 。
4、onSizeChanged( int , int , int , int ) 當view的大小發生變化時觸發 。
5、onDraw(Canvas) view渲染內容的細節。
6、onKeyDown( int , KeyEvent) 有按鍵按下後觸發 。
7、onKeyUp( int , KeyEvent) 有按鍵按下後彈起時觸發 。
8、onTrackballEvent(MotionEvent) 軌跡球事件 。
9、onTouchEvent(MotionEvent) 觸屏事件 。
10、onFocusChanged( boolean , int , Rect) 當View獲取或失去焦點時觸發 。
11、onWindowFocusChanged( boolean ) 當窗口包含的view獲取或失去焦點時觸發 。
12、onAttachedToWindow() 當view被附著到一個窗口時觸發 。
13、onDetachedFromWindow() 當view離開附著的窗口時觸發,Android123提示該方法和 onAttachedToWindow() 是相反的。
14、onWindowVisibilityChanged( int ) 當窗口中包含的可見的view發生變化時觸發。

㈨ android view 內的imageview 設置 點擊事件

1、
iv.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Log.d("dd", "123");
}
});

2、圖片的id是項目自動生成的
在的值在R.java文件裡面
你可以把你要顯示的圖片的id放到一個數據裡面
int image_id = {R.id.imageView1,R.id.imageView2,....};
然後通過數據的位置
訪問id為imageView5的即
v.findViewByid(image_id[4]);

熱點內容
ios應用上傳 發布:2024-09-08 09:39:41 瀏覽:438
ios儲存密碼哪裡看 發布:2024-09-08 09:30:02 瀏覽:870
opensslcmake編譯 發布:2024-09-08 09:08:48 瀏覽:653
linux下ntp伺服器搭建 發布:2024-09-08 08:26:46 瀏覽:744
db2新建資料庫 發布:2024-09-08 08:10:19 瀏覽:173
頻率計源碼 發布:2024-09-08 07:40:26 瀏覽:780
奧迪a6哪個配置帶後排加熱 發布:2024-09-08 07:06:32 瀏覽:101
linux修改apache埠 發布:2024-09-08 07:05:49 瀏覽:209
有多少個不同的密碼子 發布:2024-09-08 07:00:46 瀏覽:566
linux搭建mysql伺服器配置 發布:2024-09-08 06:50:02 瀏覽:995