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");  
            }  
        } 

  • 相关阅读:
    centos7.6 安装与配置 MongoDB yum方式
    MongoDB 介绍
    centos 关闭selinux
    前端 HTML标签属性
    前端 HTML 标签嵌套规则
    前端 HTML 标签分类
    前端 HTML body标签相关内容 常用标签 表单标签 form里面的 input标签介绍
    前端 HTML body标签相关内容 常用标签 表单标签 form 表单控件分类
    前端 HTML form表单标签 select标签 option 下拉框
    POJ 1426
  • 原文地址:https://www.cnblogs.com/fanfeng/p/5573771.html
Copyright © 2011-2022 走看看