日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android官方开发文档Training系列课程中文版:手势处理之ViewGroup的事件管理

發(fā)布時間:2024/7/5 Android 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android官方开发文档Training系列课程中文版:手势处理之ViewGroup的事件管理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原文地址:https://developer.android.com/training/gestures/viewgroup.html

在ViewGroup中處理觸摸事件要格外小心,因?yàn)樵赩iewGroup中有很多子View,而這些子View對于不同的觸摸事件來說是不同的目標(biāo)。要確保每個View都正確的接收了相應(yīng)的觸摸事件。

在ViewGroup中攔截觸摸事件

onInterceptTouchEvent()方法會在觸摸事件到達(dá)ViewGroup的表面時調(diào)用,這包括內(nèi)部的子View。如果onInterceptTouchEvent()返回了true,那么MotionEvent對象就會被攔截,這意味著該次事件不會傳給子View,而是會傳給ViewGroup本身的onTouchEvent()方法。

onInterceptTouchEvent()給了ViewGroup本身一個機(jī)會:在子View獲得任何事件之前一個攔截該事件的機(jī)會。如果onInterceptTouchEvent()返回了true,那么原先處理該次事件的子View就會收到一個ACTION_CANCEL的事件,并且原先事件的剩余事件都會被傳到該ViewGroup的onTouchEvent()方法中做常規(guī)處理。onInterceptTouchEvent()還可以返回false,這樣的話,該次事件則會通過View樹繼續(xù)向下傳遞,直到到達(dá)目標(biāo)View為止,目標(biāo)View會在自己的onTouchEvent()方法中處理該次事件。

在下面的示例代碼中,類MyViewGroup繼承了ViewGroup,并包含了多個View,這些View我們在這里稱之為子View,而MyViewGroup稱為父容器View。如果你在水平方向上滑動手指,那么子View皆不會收到觸摸事件。MyViewGroup會通過滾動它的內(nèi)部來實(shí)現(xiàn)觸摸事件的處理。不管如何,如果你按下了子View中的按鈕,或者在垂直方向上滑動,那么ViewGroup則不會去攔截這些事件,因?yàn)樽覸iew是該次事件的目標(biāo)View。在這些情況下,onInterceptTouchEvent()應(yīng)該返回false,且MyViewGroup的onTouchEvent()方法也不會被調(diào)用。

public class MyViewGroup extends ViewGroup {private int mTouchSlop;...ViewConfiguration vc = ViewConfiguration.get(view.getContext());mTouchSlop = vc.getScaledTouchSlop();...@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {/** This method JUST determines whether we want to intercept the motion.* If we return true, onTouchEvent will be called and we do the actual* scrolling there.*/final int action = MotionEventCompat.getActionMasked(ev);// Always handle the case of the touch gesture being complete.if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {// Release the scroll.mIsScrolling = false;return false; // Do not intercept touch event, let the child handle it}switch (action) {case MotionEvent.ACTION_MOVE: {if (mIsScrolling) {// We're currently scrolling, so yes, intercept the// touch event!return true;}// If the user has dragged her finger horizontally more than// the touch slop, start the scroll// left as an exercise for the readerfinal int xDiff = calculateDistanceX(ev);// Touch slop should be calculated using ViewConfiguration// constants.if (xDiff > mTouchSlop) {// Start scrolling!mIsScrolling = true;return true;}break;}...}// In general, we don't want to intercept touch events. They should be// handled by the child view.return false;}@Overridepublic boolean onTouchEvent(MotionEvent ev) {// Here we actually handle the touch event (e.g. if the action is ACTION_MOVE,// scroll this container).// This method will only be called if the touch event was intercepted in// onInterceptTouchEvent...} }

這里要注意,ViewGroup還提供了requestDisallowInterceptTouchEvent()方法。當(dāng)子View不希望它的父容器及祖先容器攔截觸摸事件時,ViewGroup會在 onInterceptTouchEvent()方法中對其進(jìn)行調(diào)用,從而判斷是否要攔截本次事件。

使用ViewConfiguration常量

在上面的代碼中使用了ViewConfiguration來初始化一個名為mTouchSlop的變量。你可以使用ViewConfiguration來訪問Android系統(tǒng)所使用的常用距離、速度及時間。

“mTouchSlop”引用了觸摸事件在被攔截之前手指移動的以像素為單位的距離。Touch slop經(jīng)常被用來在用戶在執(zhí)行觸摸操作時防止產(chǎn)生意外滾動。

ViewConfiguration的另外兩個常用方法是getScaledMinimumFlingVelocity()和getScaledMaximumFlingVelocity()。這兩個方法分別返回了用于初始化滾動的最小、最大的速度值。以每秒幾像素為單位:

ViewConfiguration vc = ViewConfiguration.get(view.getContext()); private int mSlop = vc.getScaledTouchSlop(); private int mMinFlingVelocity = vc.getScaledMinimumFlingVelocity(); private int mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();...case MotionEvent.ACTION_MOVE: {...float deltaX = motionEvent.getRawX() - mDownX;if (Math.abs(deltaX) > mSlop) {// A swipe occurred, do something}...case MotionEvent.ACTION_UP: {...} if (mMinFlingVelocity <= velocityX && velocityX <= mMaxFlingVelocity&& velocityY < velocityX) {// The criteria have been satisfied, do something} }

擴(kuò)展子View的觸控區(qū)域

Android提供的TouchDelegate使擴(kuò)展子View的觸控區(qū)域成為了可能。這對于子View本身特別小,而它的觸控區(qū)域需要很大時很有用。如果需要的話,你也可以使用這種方式來縮小子View的觸控區(qū)域。

在下面的示例中,ImageButton作為我們的”delegate view”(這里的意思是需要父容器擴(kuò)展觸控區(qū)域的那個View)。下面是示例的布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/parent_layout"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity" ><ImageButton android:id="@+id/button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@null"android:src="@drawable/icon" /> </RelativeLayout>

下面的代碼做了以下這些事情:

  • 獲得父容器View,并Post一個Runnale對象到UI線程。這可以確保在調(diào)用getHitRect()方法之前父容器已經(jīng)對子View完成了排布。getHitRect()會返回父容器坐標(biāo)內(nèi)當(dāng)前View的點(diǎn)擊矩陣(觸控區(qū)域)。
  • 找到ImageButton,然后調(diào)用它的getHitRect()方法獲得該View的觸控邊界。
  • 擴(kuò)大ImageButton的觸控區(qū)域。
  • 實(shí)例化一個TouchDelegate,將要擴(kuò)展的觸控區(qū)域矩陣與要擴(kuò)展觸控區(qū)域的ImageView作為參數(shù)傳入。
  • 將TouchDelegate設(shè)置給父容器View,只有這樣做,我們所觸碰到的擴(kuò)展區(qū)域才會被路由到子View上。

在TouchDelegate代理的范圍內(nèi),父容器View將會接收所有的觸摸事件。如果觸摸事件發(fā)生在子View本身的觸控區(qū)域內(nèi),那么父容器View會將所有的觸摸事件傳給子View處理:

public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// Get the parent viewView parentView = findViewById(R.id.parent_layout);parentView.post(new Runnable() {// Post in the parent's message queue to make sure the parent// lays out its children before you call getHitRect()@Overridepublic void run() {// The bounds for the delegate view (an ImageButton// in this example)Rect delegateArea = new Rect();ImageButton myButton = (ImageButton) findViewById(R.id.button);myButton.setEnabled(true);myButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Toast.makeText(MainActivity.this,"Touch occurred within ImageButton touch region.",Toast.LENGTH_SHORT).show();}});// The hit rectangle for the ImageButtonmyButton.getHitRect(delegateArea);// Extend the touch area of the ImageButton beyond its bounds// on the right and bottom.delegateArea.right += 100;delegateArea.bottom += 100;// Instantiate a TouchDelegate.// "delegateArea" is the bounds in local coordinates of// the containing view to be mapped to the delegate view.// "myButton" is the child view that should receive motion// events.TouchDelegate touchDelegate = new TouchDelegate(delegateArea,myButton);// Sets the TouchDelegate on the parent view, such that touches// within the touch delegate bounds are routed to the child.if (View.class.isInstance(myButton.getParent())) {((View) myButton.getParent()).setTouchDelegate(touchDelegate);}}});} }

總結(jié)

以上是生活随笔為你收集整理的Android官方开发文档Training系列课程中文版:手势处理之ViewGroup的事件管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。