zoukankan      html  css  js  c++  java
  • 滑动

    platformframeworksasecorejavaandroidviewViewConfiguration.java

    ViewConfiguration类中有判断是否滑动的若干配置项默认值设置。

     

    getScaledTouchSlop() 手指的移动要大于这个距离才算滑动,返回的mTouchSlop来自TOUCH_SLOP的取值。

    getScaledDoubleTapSlop() 第一个触点和后面触点的距离小于这个数值算双击,返回的mDoubleTapTouchSlop来自mTouchSlop

    getScaledPagingTouchSlop()手指的移动要大于这个距离才算翻页,返回的mPagingTouchSlop来自mTouchSlop * 2

    getScaledEdgeSlop()获得一个触摸移动的最小像素值。也就是说,只有超过了这个值,才代表我们该滑屏处理;

    getScaledMaximumFlingVelocity() 用户滑动时的最大速度,单位是每秒多少像素

    getScaledMinimumFlingVelocity() 用户滑动时的最小速度

     

    /**

    * @return Distance in pixels a touch can wander before we think the user is scrolling

    */

    public int getScaledTouchSlop() {

    return mTouchSlop;

    }

     

    /**

    * @deprecated Use {@link android.view.ViewConfiguration#get(android.content.Context)}.

    */

    @Deprecated

    public ViewConfiguration() {

    mEdgeSlop = EDGE_SLOP;

    mTouchSlop = TOUCH_SLOP;

    /** * @deprecated Use {@link #getScaledEdgeSlop()} instead.

    * Inset in dips to look for touchable content when the user touches the edge of the screen

    */

    private static final int EDGE_SLOP = 12;

    /**

    * Distance a touch can wander before we think the user is scrolling in dips.

    * Note that this value defined here is only used as a fallback by legacy/misbehaving

    * applications that do not provide a Context for determining density/configuration-dependent

    * values.

    *

    * To alter this value, see the configuration resource config_viewConfigurationTouchSlop

    * in frameworks/base/core/res/res/values/config.xml or the appropriate device resource overlay.

    * It may be appropriate to tweak this on a device-specific basis in an overlay based on

    * the characteristics of the touch panel and firmware.

    */

    private static final int TOUCH_SLOP = 8;

    /**

    * Distance the first touch can wander before we stop considering this event a double tap

    * (in dips)

    */

    private static final int DOUBLE_TAP_TOUCH_SLOP = TOUCH_SLOP;

     

    /**

    * Distance a touch can wander before we think the user is attempting a paged scroll

    * (in dips)

    *

    * Note that this value defined here is only used as a fallback by legacy/misbehaving

    * applications that do not provide a Context for determining density/configuration-dependent

    * values.

    *

    * See the note above on {@link #TOUCH_SLOP} regarding the dimen resource

    * config_viewConfigurationTouchSlop. ViewConfiguration will report a paging touch slop of

    * config_viewConfigurationTouchSlop * 2 when provided with a Context.

    */

    private static final int PAGING_TOUCH_SLOP = TOUCH_SLOP * 2;

     

    /**

    @deprecated Use {@link #getScaledDoubleTapSlop()} instead.

    * Distance in dips between the first touch and second touch to still be considered a double tap

    */

    private static final int DOUBLE_TAP_SLOP = 100;

    /**

    * @return Distance in pixels between the first touch and second touch to still be

    * considered a double tap

    */

    public int getScaledDoubleTapSlop() {

    return mDoubleTapSlop;

    }

    /**

    * @return Inset in pixels to look for touchable content when the user touches the edge of the

    * screen

    */

    public int getScaledEdgeSlop() {

    return mEdgeSlop;

    }

    <!-- Minimum velocity to initiate a fling, as measured in dips per second. -->

    <dimen name="config_viewMinFlingVelocity">50dp</dimen>

     

    <!-- Maximum velocity to initiate a fling, as measured in dips per second. -->

    <dimen name="config_viewMaxFlingVelocity">8000dp</dimen>

     

    /**

    * Creates a new configuration for the specified context. The configuration depends on

    * various parameters of the context, like the dimension of the display or the density

    * of the display.

    *

    * @param context The application context used to initialize this view configuration.

    *

    * @see #get(android.content.Context)

    * @see android.util.DisplayMetrics

    */

    private ViewConfiguration(Context context) {

    final Resources res = context.getResources();

    final DisplayMetrics metrics = res.getDisplayMetrics();

    final Configuration config = res.getConfiguration();

    final float density = metrics.density;

    final float sizeAndDensity;

    if (config.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_XLARGE)) {

    sizeAndDensity = density * 1.5f;

    } else {

    sizeAndDensity = density;

    }

     

    mEdgeSlop = (int) (sizeAndDensity * EDGE_SLOP + 0.5f);

    mFadingEdgeLength = (int) (sizeAndDensity * FADING_EDGE_LENGTH + 0.5f);

    mScrollbarSize = (int) (density * SCROLL_BAR_SIZE + 0.5f);

    mDoubleTapSlop = (int) (sizeAndDensity * DOUBLE_TAP_SLOP + 0.5f);

    mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f);

     

    // Size of the screen in bytes, in ARGB_8888 format

    final WindowManager win = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);

    final Display display = win.getDefaultDisplay();

    final Point size = new Point();

    display.getRealSize(size);

    mMaximumDrawingCacheSize = 4 * size.x * size.y;

     

    mOverscrollDistance = (int) (sizeAndDensity * OVERSCROLL_DISTANCE + 0.5f);

    mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f);

     

    if (!sHasPermanentMenuKeySet) {

    final int configVal = res.getInteger(

    com.android.internal.R.integer.config_overrideHasPermanentMenuKey);

     

    switch (configVal) {

    default:

    case HAS_PERMANENT_MENU_KEY_AUTODETECT: {

    IWindowManager wm = WindowManagerGlobal.getWindowManagerService();

    try {

    sHasPermanentMenuKey = !wm.hasNavigationBar();

    sHasPermanentMenuKeySet = true;

    } catch (RemoteException ex) {

    sHasPermanentMenuKey = false;

    }

    }

    break;

     

    case HAS_PERMANENT_MENU_KEY_TRUE:

    sHasPermanentMenuKey = true;

    sHasPermanentMenuKeySet = true;

    break;

     

    case HAS_PERMANENT_MENU_KEY_FALSE:

    sHasPermanentMenuKey = false;

    sHasPermanentMenuKeySet = true;

    break;

    }

    }

     

    mFadingMarqueeEnabled = res.getBoolean(

    com.android.internal.R.bool.config_ui_enableFadingMarquee);

    mTouchSlop = res.getDimensionPixelSize(

    com.android.internal.R.dimen.config_viewConfigurationTouchSlop);

    mPagingTouchSlop = mTouchSlop * 2;

     

    mDoubleTapTouchSlop = mTouchSlop;

     

    mMinimumFlingVelocity = res.getDimensionPixelSize(

    com.android.internal.R.dimen.config_viewMinFlingVelocity);

    mMaximumFlingVelocity = res.getDimensionPixelSize(

    com.android.internal.R.dimen.config_viewMaxFlingVelocity);

    mGlobalActionsKeyTimeout = res.getInteger(

    com.android.internal.R.integer.config_globalActionsKeyTimeout);

    }

     

    platformframeworksasecore es esvaluessymbols.xml

    <java-symbol type="dimen" name="config_viewConfigurationTouchSlop" />

    <java-symbol type="dimen" name="config_viewMinFlingVelocity" />

    <java-symbol type="dimen" name="config_viewMaxFlingVelocity" />

     

    frameworks/base/core/res/res/values/config.xml

    <!-- Base "touch slop" value used by ViewConfiguration as a

    movement threshold where scrolling should begin. -->

    <dimen name="config_viewConfigurationTouchSlop">8dp</dimen>

     

    <!-- Minimum velocity to initiate a fling, as measured in dips per second. -->

    <dimen name="config_viewMinFlingVelocity">50dp</dimen>

     

    <!-- Maximum velocity to initiate a fling, as measured in dips per second. -->

    <dimen name="config_viewMaxFlingVelocity">8000dp</dimen>

     

    private GestureDetector mGestureDetector;

     

    @Override

    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    mGestureDetector = new GestureDetector(this, new MyGestureListener());

    }

     

    @Override

    public boolean onTouchEvent(MotionEvent event) {

    return mGestureDetector.onTouchEvent(event);

    }

     

     

    class MyGestureListener extends GestureDetector.OnGestureListener{ //共有6个方法:

     

    // 用户轻触触屏:Touch down(仅一次)时触发, e为down时的MotionEvent:

    boolean onDown(MotionEvent e){return true;}

     

    // 用户轻触触屏,且尚未松开或拖动:

    // 在Touch down(仅一次)之后一定时间(115ms)触发,e为down时的MotionEvent:

    void onShowPress(MotionEvent e){return true;}

     

    // 用户(轻触触屏后)松开:Touch up(仅一次)时触发,e为up时的MotionEvent:

    boolean onSingleTapUp(MotionEvent e){return true;}

     

    // 用户轻触触屏,并拖动:

    // 按下并滑动时触发,e1为down(仅一次)时的MotionEvent,e2为move(多个)时的MotionEvent:

    boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY){return true;}

     

    // 用户长按触屏(此View必须是可长按的: myView->setLongClickable(true);):

    // 在Touch down之后一定时间(500ms)后,由多个down事件触发,e为down时的MotionEvent:

    void onLongPress(MotionEvent e){return true;}

     

    // 用户按下触屏、快速移动后松开:

    // 按下并快速滑动一小段距离(多个move),up时触发,e1为down(仅一次)时的MotionEvent,

    //e2为up(仅一次)时的MotionEvent:

    boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY){return true;}

    }

    // -------------------------------------------------------------------------------

     

    至于doubletap的检测,可以通过设置mGestureDetector的OnDoubleTapListener来实现:

     

    GestureDetector.OnDoubleTapListener doubleTapListener = new GestureDetector.OnDoubleTapListener() {

     

    // 完成一次单击,并确定(300ms内)没有发生第二次单击事件后触发,e为down时的MotionEvent:

    boolean onSingleTapConfirmed(MotionEvent e){return true;}

     

    // 第二次单击down时触发,e为第一次down时的MotionEvent:

    boolean onDoubleTap(MotionEvent e){return true;}

     

    // 第二次单击down、move和up时都触发,e为不同时机下的MotionEvent:

    boolean onDoubleTapEvent(MotionEvent e){return true;}

    }

    mGestureDetector.setDoubleTapListener(doubleTapListener);

    // -------------------------------------------------------------------------------

     

     

    具体地说,典型的触屏事件及其listener执行的流程见下:

     

    1). 单击事件的执行流程:

    有两种情况,一种是时间很短,一种时间稍长。

    时间很短:onDown ----> onSingleTapUp ----> onSingleTapConfirmed

    时间稍长:onDown ----> onShowPress ----> onSingleTapUp ----> onSingleTapConfirmed

    2). 长按事件

    onDown ----> onShowPress ----> onLongPress

    3.抛(fling):手指触动屏幕后,稍微滑动后立即松开:

    onDown ----> onScroll ----> onScroll ----> onScroll ----> ……… ----> onFling

    4.拖动(drag)

    onDown ----> onScroll ----> onScroll ----> onFiling

    注意:有的时候会触发onFiling,但是有的时候不会触发,z这是因为人的动作不标准所致。

     

    ViewConfiguration滑动参数设置类:

    /**   

      * 包含了方法和标准的常量用来设置UI的超时、大小和距离   

      */

     public class ViewConfiguration {    

         // 设定水平滚动条的宽度和垂直滚动条的高度,单位是像素px    

         private static final int SCROLL_BAR_SIZE = 10;    

                 

         //定义滚动条逐渐消失的时间,单位是毫秒    

         private static final int SCROLL_BAR_FADE_DURATION = 250;    

                 

         // 默认的滚动条多少秒之后消失,单位是毫秒    

         private static final int SCROLL_BAR_DEFAULT_DELAY = 300;    

                 

         // 定义边缘地方褪色的长度    

         private static final int FADING_EDGE_LENGTH = 12;    

                 

         //定义子控件按下状态的持续事件    

         private static final int PRESSED_STATE_DURATION = 125;    

                     

         //定义一个按下状态转变成长按状态的转变时间    

         private static final int LONG_PRESS_TIMEOUT = 500;    

                     

         //定义用户在按住适当按钮,弹出全局的对话框的持续时间    

         private static final int GLOBAL_ACTIONS_KEY_TIMEOUT = 500;    

                     

         //定义一个touch事件中是点击事件还是一个滑动事件所需的时间,如果用户在这个时间之内滑动,那么就认为是一个点击事件    

         private static final int TAP_TIMEOUT = 115;    

                     

         /**   

          * Defines the duration in milliseconds we will wait to see if a touch event    

          * is a jump tap. If the user does not complete the jump tap within this interval, it is   

          * considered to be a tap.    

          */

         //定义一个touch事件时候是一个点击事件。如果用户在这个时间内没有完成这个点击,那么就认为是一个点击事件    

         private static final int JUMP_TAP_TIMEOUT = 500;    

                 

         //定义双击事件的间隔时间    

         private static final int DOUBLE_TAP_TIMEOUT = 300;    

                     

         //定义一个缩放控制反馈到用户界面的时间    

         private static final int ZOOM_CONTROLS_TIMEOUT = 3000;    

                 

         /**   

          * Inset in pixels to look for touchable content when the user touches the edge of the screen   

          */

         private static final int EDGE_SLOP = 12;    

                     

         /**   

          * Distance a touch can wander before we think the user is scrolling in pixels   

          */

         private static final int TOUCH_SLOP = 16;    

                     

         /**   

          * Distance a touch can wander before we think the user is attempting a paged scroll   

          * (in dips)   

          */

         private static final int PAGING_TOUCH_SLOP = TOUCH_SLOP * 2;    

                     

         /**   

          * Distance between the first touch and second touch to still be considered a double tap   

          */

         private static final int DOUBLE_TAP_SLOP = 100;    

                     

         /**   

          * Distance a touch needs to be outside of a window's bounds for it to   

          * count as outside for purposes of dismissing the window.   

          */

         private static final int WINDOW_TOUCH_SLOP = 16;    

                 

        //用来初始化fling的最小速度,单位是每秒多少像素    

         private static final int MINIMUM_FLING_VELOCITY = 50;    

                     

         //用来初始化fling的最大速度,单位是每秒多少像素    

         private static final int MAXIMUM_FLING_VELOCITY = 4000;    

                 

         //视图绘图缓存的最大尺寸,以字节表示。在ARGB888格式下,这个尺寸应至少等于屏幕的大小    

         @Deprecated    

         private static final int MAXIMUM_DRAWING_CACHE_SIZE = 320 * 480 * 4; // HVGA screen, ARGB8888    

                 

         //flingsscrolls摩擦力度大小的系数    

         private static float SCROLL_FRICTION = 0.015f;    

                 

         /**   

          * Max distance to over scroll for edge effects   

          */

         private static final int OVERSCROLL_DISTANCE = 0;    

                 

         /**   

          * Max distance to over fling for edge effects   

          */

         private static final int OVERFLING_DISTANCE = 4;    

                 

     }

     

    public class ViewConfiguration {

    ......

    //不推荐使用,推荐ViewConfiguration.get(Context)获取实例

    public ViewConfiguration() {}

    public static ViewConfiguration get(Context context) {}

    //不推荐使用,推荐getScaledScrollBarSize()代替;获取水平滚动条的宽或垂直滚动条的高

    public static int getScrollBarSize() {}

    public int getScaledScrollBarSize() {}

    //滚动条褪去消失的持续时间

    public static int getScrollBarFadeDuration() {}

    //滚动条消失的延迟时间

    public static int getScrollDefaultDelay() {}

    //不推荐使用,推荐getScaledFadingEdgeLength()代替;褪去边缘的长度

    public static int getFadingEdgeLength() {}

    public int getScaledFadingEdgeLength() {}

    //按下的持续时间长度

    public static int getPressedStateDuration() {}

    //按住状态转变为长按状态需要的时间

    public static int getLongPressTimeout() {}

    //重新按键判断时间

    public static int getKeyRepeatTimeout() {}

    //重复按键延迟的时间

    public static int getKeyRepeatDelay() {}

    //判断是单击还是滚动的时间,在这个时间内没有移动则是单击,否则是滚动

    public static int getTapTimeout() {}

    //在这个时间内没有完成这个点击,那么就认为是一个点击事件

    public static int getJumpTapTimeout() {}

    //得到双击间隔时间,在这个时间内是双击,否则是单击

    public static int getDoubleTapTimeout() {}

    //不推荐使用,推荐getScaledEdgeSlop()代替;判断是否滑动事件

    public static int getEdgeSlop() {}

    public int getScaledEdgeSlop() {}

    //不推荐使用,推荐getScaledTouchSlop()代替;滑动的时候,手的移动要大于这个距离才算移动

    public static int getTouchSlop() {}

    public int getScaledTouchSlop() {}

    //触摸边沿padding区域的判断

    public int getScaledPagingTouchSlop() {}

    //不推荐使用,推荐getScaledDoubleTapSlop()代替;判断是否双击的阈值

    public static int getDoubleTapSlop() {}

    public int getScaledDoubleTapSlop() {}

    //不推荐使用,推荐getScaledWindowTouchSlop()代替;触摸窗体边沿区域判断

    public static int getWindowTouchSlop() {}

    public int getScaledWindowTouchSlop() {}

    //不推荐使用,推荐getScaledMinimumFlingVelocity()代替;得到滑动的最小速度, 以像素/每秒来进行计算

    public static int getMinimumFlingVelocity() {}

    public int getScaledMinimumFlingVelocity() {}

    //不推荐使用,推荐getScaledMaximumFlingVelocity()代替;得到滑动的最大速度, 以像素/每秒来进行计算

    public static int getMaximumFlingVelocity() {}

    public int getScaledMaximumFlingVelocity() {}

    //不推荐使用,推荐getScaledMaximumDrawingCacheSize()代替;获取最大的图形可缓存大小,单位bytes

    public static int getMaximumDrawingCacheSize() {}

    public int getScaledMaximumDrawingCacheSize() {}

    ......

    }

     

     

    1. dip: device independent pixels(设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGAHVGAQVGA 推荐使用这    这个,不依赖像素。 
       
    这里要特别注意dip与屏幕密度有关,而屏幕密度又与具体的硬件有关,硬件设置不正确,有可能导致dip不能正常显示。在屏幕密度为160的显示屏上,1dip=1px,有时候可能你的屏幕分辨率很大如480*800,但是屏幕密度没有正确设置比如说还是160,那么这个时候凡是使用dip的都会显示异常,基本都是显示过小。 
         dip
    的换算: 
               dip
    value=(int) (pxvalue/1.5 + 0.5) 
    2. dp:
    很简单,和dip是一样的。 
    3. px: pixels(
    像素),不同的设备不同的显示屏显示效果是相同的,这是绝对像素,是多少就永远是多少不会改变。 
    4.  sp: scaled pixels(
    放大像素). 主要用于字体显示best for textsize 

    备注: 根据google的推荐,像素统一使用dip,字体统一使用sp  

    举个例子区别pxdip

    px就是像素,如果用px,就会用实际像素画,比个如吧,用画一条长度为240px的横线,在480宽的模拟器上看就是一半的屏宽,而在320宽的模拟器上看就是23的屏宽了。

    dip,就是把屏幕的高分成480分,宽分成320分。比如你做一条160dip的横线,无论你在320480的模拟器上,都是一半屏的长度。


    public static int dip2px(Context context, float dipValue){ 
                    final float scale = context.getResources().getDisplayMetrics().density; 
                    return (int)(dipValue * scale + 0.5f); 
            } 
            
        public static int px2dip(Context context, float pxValue){ 
                    final float scale = context.getResources().getDisplayMetrics().density; 
                    return (int)(pxValue / scale + 0.5f); 
            } 

     

    class MyScrollListener implements OnScrollListener {  
      
            @Override  
            public void onScroll(AbsListView view, int firstVisibleItem,  
                    int visibleItemCount, int totalItemCount) {  
                /** 
                * firstVisibleItem
    表示在当前屏幕显示的第一个listItem在整个listView里面的位置(下标从0开始) 
                * visibleItemCount
    表示在现时屏幕可以见到的ListItem(部分显示的ListItem也算)总数 
                * totalItemCount
    表示ListViewListItem总数  
                * listView.getLastVisiblePosition()
    表示在现时屏幕最后一个ListItem 
                * (
    最后ListItem要完全显示出来才算)在整个ListView的位置(下标从0开始)  
                */  
              
            }  
                
                                                                                                                                            
            @Override  
            public void onScrollStateChanged(AbsListView view, int scrollState) { 
        /**
        *scrollState
    有三种状态,分别是SCROLL_STATE_IDLESCROLL_STATE_TOUCH_SCROLLSCROLL_STATE_FLING
        *SCROLL_STATE_IDLE
    是当屏幕停止滚动时
        *SCROLL_STATE_TOUCH_SCROLL
    是当用户在以触屏方式滚动屏幕并且手指仍然还在屏幕上时(The user is scrolling using touch, and their finger is still on the screen
        *SCROLL_STATE_FLING
    是当用户由于之前划动屏幕并抬起手指,屏幕产生惯性滑动时(The user had previously been scrolling using touch and had performed a fling
        */  
                Log.d("load", "onScrollStateChanged");  
            }  
        } 

  • 相关阅读:
    5,MongoDB 之 "$" 的奇妙用法
    4,MongoDB 之 $关键字 及 $修改器 $set $inc $push $pull $pop MongoDB
    3,MongoDB之数据类型
    2,MongoDB之增删改查及pymongo的使用
    1,MongoDB简介和安装
    19,Ubuntu安装之python开发
    18,Shell编程实战
    17,saltstack高效运维
    16.2,docker网络
    如何使用 window api 转换字符集?
  • 原文地址:https://www.cnblogs.com/fanfeng/p/5573771.html
Copyright © 2011-2022 走看看