android滑動事件監聽
❶ 移動端touch觸屏滑動事件、滑動觸屏事件監聽!
一、觸摸事件
ontouchstart、ontouchmove、ontouchend、ontouchcancel
目前移動端瀏覽器均支持這4個觸摸事件,包括IE。由於觸屏也支持MouseEvent,因此他們的順序是需要注意的:touchstart → mouseover → mousemove → mousedown → mouseup → click1
Apple在iOS 2.0中引入了 觸摸事件API ,Android正迎頭趕上這一事實標准,縮小差距。最近一個W3C工作組正合力制定這一 觸摸事件規范 。
二、規范
這里我們介紹幾種普及得比較好的觸摸事件,你可以在絕大多數現代瀏覽器中來測試這一事件(必須是觸屏設備哦):
touchstart: 觸摸開始的時候觸發
touchmove: 手指在屏幕上滑動的時候觸發
touchend: 觸摸結束的時候觸發
而每個觸摸事件都包括了三個觸摸列表,每個列表裡包含了對應的一系列觸摸點(用來實現多點觸控):
touches: 當前位於屏幕上的所有手指的列表。
targetTouches: 位於當前DOM元素上手指的列表。
changedTouches: 涉及當前事件手指的列表。
每個觸摸點由包含了如下觸摸信息(常用):
identifier: 一個數值,唯一標識觸摸會話(touch session)中的當前手指。一般為從0開始的流水號(android4.1,uc)
target: DOM元素,是動作所針對的目標。
pageX / pageX / clientX / clientY/screenX/screenY : 一個數值,動作在屏幕上發生的位置(page包含滾動距離,client不包含滾動距離,screen則以屏幕為基準)。
radiusX / radiusY/ rotationAngle: 畫出大約相當於手指形狀的橢圓形,分別為橢圓形的兩個半徑和旋轉角度。初步測試瀏覽器不支持,好在功能不常用,歡迎大家反饋。
有了這些信息,我們就可以依據這些事件信息為用戶提供不同的反饋了。
下面,我將為大家展示一個小demo,用touchmove實現的單指拖動:
三、手勢事件
手勢是指利用多點觸控進行旋轉、拉伸等操作,例如圖片、網頁的放大、旋轉。需要兩個或以上的手指同時觸摸時才會觸發手勢事件。關於縮放我們需要注意的一點 是元素的位置坐標:我們通常使用offsetX、getBoundingClientRect等方法獲取元素的位置坐標,但在手機瀏覽器中頁面經常會在使 用中被縮放,那縮放後的元素坐標會改變嗎?答案是有所差異。用一個情景來說明這個問題:頁面A載入完成後, JavaScript 獲 取到該元素在document中的坐標為(100,100),接著用戶放大了頁面,此時用JavaScript再次輸出元素坐標,依然還是 (100,100),但該元素在屏幕上的響應區域會根據縮放比例產生偏移。你可以打開那個打磚塊游戲demo,等頁面完全載入完成後,再放大,此時你會發 現即使手指觸摸在「touch here」區域外部,也可以控制到球板,因為區域發生了偏移。除非頁面刷新或者恢復縮放,否則偏移量將一直存在。
四、重力感應
重力感應較簡單,只需要為body節點添加onorientationchange事件即可。在此事件中由window.orientation屬性得到代表當前手機方向的數值。window.orientation的值列表如下:
0:與頁面首次載入時的方向一致
-90:相對原始方向順時針轉了90°
180:轉了180°
90:逆時針轉了90°據我測試,Android2.1尚未支持重力感應。以上即目前的觸屏事件,這些事件尚未並入標准,但已被廣泛使用。本人Android2.1,未在其他環境下測試。
❷ 在android系統中,那些被監聽對象有哪些
在android系統中,那些被監聽對象有哪些:1、單擊事件(View.OnClickListener):當用戶觸碰到某個組件或者方向鍵被按下時產生該事件,該事件的處理方法是onClick()。
2、焦點事件(View.OnFocusChangeListener):組件得到或者失去焦點時產生該事件,事件處理方法是onFocusChange()。
3、按鍵事件(View.OnKey Listener):用戶按下或者釋放設備上的某個按鍵時產生,事件處理方法是 onKey()。
4、觸碰事件(View.OnTouchListener):設備具有觸摸屏功能時,觸碰屏幕產生該事件。事件處理方法是onTouch()。
5、創建上下文菜單事件(View.OnCreateContextMenu Listener):創建上下文菜單時產生該事件,事件處理方法是 onCreateContextMenu()。
❸ android頁面中如何實現滑動監聽呢
實現OnGestureListener,網路搜素OnGestureListener,有太多了。如果左右時onFling
❹ Android 雙擊單擊事件監聽手勢檢測GestureDetector原理及實現
app我們常用的手勢有很多的地方,比如右滑關閉界面等。手勢控制分為觸發動作(Touch Mechanics,用戶手指在屏幕上如何動作)和觸發行為(Touch Activities,界面上特定動作在特定情境下引發的結果)。這是因為同樣的觸發動作(如單次觸擊)在不同情境下可能會帶來不同的結果(如輕觸,取消,開啟/關閉指示),同樣單次觸發行為(如放大)可能是由多種觸發動作(如捏放,雙次觸擊,雙次觸擊拖拽等)實現。
一般情況下,我們知道View類有個View.OnTouchListener內部介面,通過重寫他的onTouch(View v, MotionEvent event)方法,我們可以處理一些touch事件,但是這個方法太過簡單,如果需要處理一些復雜的手勢,用這個介面就會很麻煩(因為我們要自己根據用戶觸摸的軌跡去判斷是什麼手勢)。
Android sdk給我們提供了GestureDetector類,通過這個類我們可以識別很多的手勢,主要是通過他的onTouchEvent(event)方法完成了不同手勢的識別。雖然他能識別手勢,但是不同的手勢要怎麼處理,應該是提供給程序員實現的。
一.GestureDetector簡介
1.組成
GestureDetector類用來識別觸摸屏的各種手勢,它包含了兩個介面和一個內部類:
介面:
OnGestureListener:用來監聽手勢事件(6種)。
OnDoubleTapListener:用來監聽雙擊事件。
內部類:
SimpleOnGestureListener:用來監聽所有的手勢。實際上它實現了上述兩個介面,不過方法體是空的,需要我們自己寫。我們可以繼承這個類,重寫裡面的方法進行手勢處理。
2.構造
GestureDetector gestureDetector = new GestureDetector(GestureDetector.OnGestureListener listener);
GestureDetector gestureDetector = new GestureDetector(Context context,GestureDetector.OnGestureListener listener);
GestureDetector gestureDetector = new GestureDetector(Context context,GestureDetector.SimpleOnGestureListener listener);
3.方法
(1)onTouchEvent(MotionEvent ev) 分析捕捉到的觸摸事件觸發相應的回調函數
(2)setIsLongpressEnabled(boolean isLongpressEnabled) 設置「長按」是否可用
(3)setOnDoubleTapListener(GestureDetector.OnDoubleTapListener onDoubleTapListener) 設置雙擊監聽器
4.使用
流程:
首先,系統捕捉屏幕的觸摸事件(onTouchListener),這時還未涉及具體手勢,只是簡單地捕捉到觸摸。
接著,在onTouch()方法中調用GestureDetector的onTouchEvent()方法,將捕捉到的MotionEvent交給GestureDetector來處理
最後,還需要實現抽象方法。
可根據需要選擇:
重寫OnGestureListener並通過構造函數傳入gestureDetector
重寫OnDoubleTapListener並通過GestureDetector.setOnDoubleTapListener方法傳入gestureDetector
重寫SimpleOnGestureListener並通過構造函數傳入gestureDetector
實現:
註:不要注重我寫的類是什麼類,要注重實現方法自定義view和activity中都可以,根據需要繼承上面三種listener,傳入構造函數即可;
public class TestDemo{
Context context;
public TestDemo(Context context){
this.context = context;
}
private GestureDetectordetector;
private void initView(){
detector =new GestureDetector(context, new MySimple());
detector =new GestureDetector(context, new MyGesture());
detector =new GestureDetector(context, new MyDoubleTap());
setOnTouchListener((v, event) -> {
// 事件監聽交給手勢類來處理
detector.onTouchEvent(event);
return true;
});
}
//與上面二選一
@Override
public boolean onTouchEvent(MotionEvent event) {
return detector.onTouchEvent(event);
}
// 手勢監聽器類SimpleOnGestureListener
private class MySimple extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapUp(MotionEvent e) {//一次單獨的輕擊抬起操作,也就是輕擊一下屏幕,立刻抬起來,才會有這個觸發;如果除了Down以外還有其它操作,那就不再是Single操作了,所以也就不會觸發這個事件
return super.onSingleTapUp(e);
}
@Override
public void onLongPress(MotionEvent e) {//長按事件;
super.onLongPress(e);
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {//在屏幕上拖動事件,只要手指移動就會執行,無論是用手拖動view,或者是以拋的動作滾動,都會多次觸發,這個方法在ACTION_MOVE動作發生時就會觸發他不會執行MotionEvent.ACTION_UP,通常用來實現放大縮小和移動。
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {//滑動屏幕,用戶按下觸摸屏、快速移動後松開,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE, 1個ACTION_UP觸發;是個甩的動作,這個甩的動作是在一個MotionEvent.ACTION_UP(手指抬起)發生時執行,通常用來實現翻頁效果
return super.onFling(e1, e2, velocityX, velocityY);
}
@Override
public void onShowPress(MotionEvent e) {//down事件發生而move或則up還沒發生前觸發該事件;
super.onShowPress(e);
}
@Override
public boolean onDown(MotionEvent e) {//down事件用戶按下屏幕
return super.onDown(e);
}
@Override
public boolean onDoubleTap(MotionEvent e) {//雙擊事件
return super.onDoubleTap(e);
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {//雙擊間隔中還發生其他的動作。通知DoubleTap手勢中的事件,包含down、up和move事件(這里指的是在雙擊之間發生的事件,例如在同一個地方雙擊會產生DoubleTap手勢,而在DoubleTap手勢裡面還會發生down和up事件,這兩個事件由該函數通知)
return super.onDoubleTapEvent(e);
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {//單擊事件。用來判定該次點擊是SingleTap而不是DoubleTap,如果連續點擊兩次就是DoubleTap手勢,如果只點擊一次,系統等待一段時間後沒有收到第二次點擊則判定該次點擊為SingleTap而不是DoubleTap,然後觸發SingleTapConfirmed事件。
return super.onSingleTapConfirmed(e);
}
}
// 手勢監聽器類GestureListener
private class MyGesture extends GestureDetector.OnGestureListener{
@Override
public boolean onDown(MotionEvent e) {//down事件用戶按下屏幕
return false;
}
@Override
public void onShowPress(MotionEvent e) {//down事件發生瞬間而move或則up還沒發生前觸發該事件;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {//一次單獨的輕擊抬起操作,也就是輕擊一下屏幕,立刻抬起來,才會有這個觸發;如果除了Down以外還有其它操作,那就不再是Single操作了,所以也就不會觸發這個事件;
return super.onSingleTapUp(e);
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {//在屏幕上拖動事件,只要手指移動就會執行,無論是用手拖動view,或者是以拋的動作滾動,都會多次觸發,這個方法在ACTION_MOVE動作發生時就會觸發他不會執行MotionEvent.ACTION_UP,通常用來實現放大縮小和移動。
return false;
}
@Override
public void onLongPress(MotionEvent e) {//長按事件,超過一定時長觸發該事件回調;
super.onLongPress(e);
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {//滑動屏幕,用戶按下觸摸屏、快速移動後松開,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE, 1個ACTION_UP觸發;是個甩的動作,這個甩的動作是在一個MotionEvent.ACTION_UP(手指抬起)發生時執行,通常用來實現翻頁效果
return super.onFling(e1, e2, velocityX, velocityY);
}
}
// 手勢監聽器類SimpleOnGestureListener
private class MyDoubleTap extends GestureDetector.OnDoubleTapListener {
@Override
public boolean onDoubleTap(MotionEvent e) {//雙擊事件
return super.onDoubleTap(e);
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {//雙擊間隔中還發生其他的動作。通知DoubleTap手勢中的事件,包含down、up和move事件(這里指的是在雙擊之間發生的事件,例如在同一個地方雙擊會產生DoubleTap手勢,而在DoubleTap手勢裡面還會發生down和up事件,這兩個事件由該函數通知)
return super.onDoubleTapEvent(e);
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {//單擊事件。用來判定該次點擊是SingleTap而不是DoubleTap,如果連續點擊兩次就是DoubleTap手勢,如果只點擊一次,系統等待一段時間後沒有收到第二次點擊則判定該次點擊為SingleTap而不是DoubleTap,然後觸發SingleTapConfirmed事件。
return super.onSingleTapConfirmed(e);
}
}
}
關於onFling()和onScroll()的區別:
onFling()是甩,這個甩的動作是在一個MotionEvent.ACTION_UP(手指抬起)發生時執行,而onScroll(),只要手指移動就會執行。他不會執行MotionEvent.ACTION_UP。onFling通常用來實現翻頁效果,而onScroll通常用來實現放大縮小和移動。
關於onSingleTapConfirmed和onSingleTapUp的一點區別: OnGestureListener有這樣的一個方法onSingleTapUp,和onSingleTapConfirmed容易混淆。二者的區別是:onSingleTapUp,只要手抬起就會執行,而對於onSingleTapConfirmed來說,如果雙擊的話,則onSingleTapConfirmed不會執行
SimpleOnGestureListener是GestureDetector類的一個內部類,該類是static class,也就是說它實際上是一個外部類。可以在外部繼承這個類,重寫裡面的手勢處理方法。
1.OnDoubleTapListener是用來檢測滑鼠雙擊事件的
2.SimpleOnGestureListener實際上實現了OnGestureListener 和OnDoubleTapListener,所以它可以完成以上提到的所有手勢識別(9種)
❺ 如何監聽android的屏幕滑動停止事件
android的屏幕滑動停止事件監聽方法為:
1、自定義一個ScrollView,內容只要將標準的ScrollView 拷貝出來,然後就可以利用Scroller的兩個屬性去判斷是否滾動完畢:
public final boolean isFinished() {
return mFinished;
}
public final int getDuration() {
return mDuration;
}
2、啟動線程來獲得當前的scrollview的高度,並實時更新就可以了,一旦高度不再發生變化則判斷為停止。
❻ Android RecyclerView 滾動監聽
前面整理了 ScrollView 的滑動監聽,這里再記錄一個 RecyclerView 的滑動事件。
❼ Android (基礎自定義組件)viewpagertap滑動器
視頻地址: http://www.imooc.com/learn/615
2.1.1主要定義畫筆、三角形使用path來實現。接著定義三角形的大小(寬高)以及初始化位置。
2.1.2設置mInitTranslationX參數,表示三角形初始化的位置,相當於marginLeft,計算方式是:
mInitTranslationX = 一個tab的寬度 - 三角形寬度的/2
2.1.3設置mTranslationX參數,表示每一移動一個tab時,三角形需要平移的寬度,如圖:
2.1.4 mTabVisibleCount,自定義屬性,布局中要顯示幾個tab,如上圖4個tab
2.2.1構造中主要獲取自定義屬性值,默認為4;以及設置畫筆
2.3.1三角形的寬度 = 一個tab寬度的1/6;如果覺得寬度的大小不合適, 可以改變1/6這個常量的比例
2.3.2三角形的高度 = 高度/2如圖:
2.4.1重寫父類dispatchDraw方法,此方法在invalidate()時,會重新執行
2.4.2通過 canvas.translate()設置三角形所在位置;X軸(上去看2.1.3),Y軸為但前組件的高度(最底部)。以及調用drawPath()方法使用畫筆。
2.5.1如標題主要是通過viewpager的position和positionOffset來計算mTranslationX的值;再通過scrollTo方法來平移但前組件,最後通過invalidate()方法重繪布局
2.5.2剩下的就是一些演算法和邏輯判斷
2.6.1獲取viewpager,監聽viewpager的滑動事件,自定義setScroll方法(2.5的方法)將但前position和滑動偏移量傳進去
2.6.2在此次以及監聽的viewpager的滑動事件,如果外界也需要監聽當前viewpager的話,會起沖突;此時就需要設置回調,對外提供介面
2.6.3setTextHighLight()方法設置選中的tab為高亮顏色
2.7.1獲取list集合,將每一個item設置成一個textview,再通過setTextItemOnclickEvent()方法設置點擊事件
3.1app:visible_tab_count自定義屬性;如果不設置默認為自定義組件的COUNT_TAB_VISIBLE變數值
http://pan..com/s/1qYGUTAW
http://pan..com/s/1slpi5v3
❽ Android RecycleView滾動監聽,以及view回收的細節
主要細節是,如果要在recycleView在回收的同時,做UI調整容易出現的問題。
一、xml可見的最外層設置為margin,view的回收還有添加的時間點可能不好計算,容易出現卡頓的情況,
二、如果是實用方法smoothScrollBy,第一個view剛好滾出可視區的時候是沒有被回收的,技巧就是滾動距離加1
沒圖沒真相,以下是業務需求的效果
首先想法是通過behavior解決問題,但是後來發現behavior需要好多個,各種相互觀察好麻煩,所以想一下可不可以直接使用RecycleView,通過滾動監聽改變圖片大小實現功能,初步想法是第一個可視view不斷變小,第二個可視的view不斷變大,如下圖
滾動的初步想法是這樣的通過滾動距離dx,來改變view的大小
但是後來發現dx,效果不行,有興趣的同學自己試一下,所以想了另外一個思路,根據下標為2的view也就是第三本書的位置,修改前面兩本書的寬度,所以不需要dx了,這里順便提一下,書本這個view是重寫了ImageView的,把寬高比固定為3:4,所以只需要不斷的改變書本的寬度就好了,其中bookWidth 為小書本的原始高度
到這里基本上就實現了滾動效果了,但是業務需求是當手指不在滑動的時候,不允許書本被覆蓋的,所以這里就要,監聽滾動狀態
這個地方必須使用smoothScrollBy,不能是ScrollBy,因為ScrollBy不會回調onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy)這個方法,造成view寬度沒有重新設定。
項目地址: https://gitee.com/feng87/BookShelf
❾ android fragment怎麼監聽上下滑動
在Android應用中,經常需要手勢滑動操作,比如上下滑動,或左右方向滑動,處理手勢滑動 。通常有兩種方法:一種是單獨實現setOnTouchListener監聽器來,另一種是構建手勢探測器
第一種方法,就是在要實現滑動的View中,實現OnTouchListener監聽事件,然後判斷KeyDonw和KeyUp 直接的位置距離來判斷滑動方向,核心實現代碼如下:
/**
* 設置上下滑動作監聽器
* @author jczmdeveloper
*/
private void setGestureListener(){
myView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPosX = event.getX();
mPosY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
mCurPosX = event.getX();
mCurPosY = event.getY();
break;
case MotionEvent.ACTION_UP:
if (mCurPosY - mPosY > 0
&& (Math.abs(mCurPosY - mPosY) > 25)) {
//向下滑動
} else if (mCurPosY - mPosY < 0
&& (Math.abs(mCurPosY - mPosY) > 25)) {
//向上滑動
collapse();
}
break;
}
return true;
}
});
}
第二種方法:就是構建手勢探測器,如GestureDetector mygesture = new GestureDetector(this);,然後在onFling方法中根據MotionEvent的兩個參數的 按下和滑動以及放開的位置和距離來判斷滑動方向以及滑動速度等的。要構建GestureDetector,必須要和OnTouchListener一起使用,因為必須設置Touch監聽,核心實現實例如下:
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class TagScrollView extends FrameLayout implements OnTouchListener, OnGestureListener{
private float mPosX, mPosY, mCurPosX, mCurPosY;
private static final int FLING_MIN_DISTANCE = 20;// 移動最小距離
private static final int FLING_MIN_VELOCITY = 200;// 移動最大速度
//構建手勢探測器
GestureDetector mygesture = new GestureDetector(this);
public TagScrollView(Context context) {
this(context, null);
}
public TagScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TagScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//setGestureListener();
//設置Touch監聽
this.setOnTouchListener(this);
//允許長按
this.setLongClickable(true);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return mygesture.onTouchEvent(event);
}
@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub
// e1:第1個ACTION_DOWN MotionEvent
// e2:最後一個ACTION_MOVE MotionEvent
// velocityX:X軸上的移動速度(像素/秒)
// velocityY:Y軸上的移動速度(像素/秒)
// X軸的坐標位移大於FLING_MIN_DISTANCE,且移動速度大於FLING_MIN_VELOCITY個像素/秒
//向
if (e1.getY() - e2.getY() > FLING_MIN_DISTANCE){
// && Math.abs(velocityX) > FLING_MIN_VELOCITY) {
collapse();
}
//向上
if (e2.getY() - e1.getY() > FLING_MIN_DISTANCE
&& Math.abs(velocityX) > FLING_MIN_VELOCITY) {
}
return false;
}
}
❿ android怎麼監聽手指抬起屏幕的事件
一般情況下,你在MotionEvent.ACTION_UP或者MotionEvent.ACTION_POINTER_UP等UP事件的回調中處理即可,因為手指在屏幕上如果按著即使不動的情況下,其實Action_move仍在回調,就是用戶比較難模擬出來那種完全手指按著屏幕一個像素點也沒有動的情況。
或者你不想在UP事件中處理,那麼就在Move中檢測單位事件內移動的具體,比如100ms內如果用戶手指移動距離小於你自己定義的閥值的話,可以認為用戶沒有移動手指。
寫了半天才發現你問的不是這個問題。
你的問題可以通過先計算你將要滑動屏幕到的最終位置,然後通過判斷你現在已經滑動到的位置,如果兩個位置間的距離小於某個閥值比如一像素的話,那麼就可以看做屏幕滑動停止了。
可以參考一下launcher中對屏幕滑動結束的處理邏輯。