一、Custom View
1、view的继承关系
view继承关系.png
2、Android 如何绘制试图层次
当activity获取焦点时,它必须提供layout层次的根节点,然后android 系统开始视图的绘制过程。绘制是从layout的根节点开始的,按照从上往下的顺序,父元素优先子元素。
绘制的两个过程:
measuring pass:实现measure(int,int)方法,顺序也是从上往下,每个view保存它自己的测量值
layout pass:实现layout(int,int,int,int)方法,顺序从上往下,在这个阶段每个layout manager负责他们各自所有子元素的位置,通过上一步测量的值
测量和绘制过程是交替进行的,layout manager可能运行 measure pass 若干次。例如 linearlayout需要支持weight属性,relativelayout需要测量子节点多次才能确定约束关系。
view或activity可以再次触发测量和绘制过程。通过 requestLayout()
在测量和布局计算完成后,视图就开始绘制自己。这个操作通过invalidate()触发。
3、view 截屏
每个view都支持创建当前显示状态的图片。
# Build the Drawing Cache
view.buildDrawingCache();
# Create Bitmap
Bitmap cache = view.getDrawingCache();
# Save Bitmap
saveBitmap(cache);
view.destroyDrawingCache();
二、自定义view
1、创建自定义view
通过继承view或它的子类,可以创建自定义view
通过onDraw()方法绘制视图,如果需要重新绘制,调用invalidate()触发onDraw()
如果定义自己的view,确保参考ViewConfiguration 类,它包含了一些常亮定义
2、测量
必须调用 setMeasuredDimenstion(int,int)设置结果
3、定义自定义 layout managers
通过继承ViewGroup
自定义layout manager 可以重写 onMeasure() 和 onLayout(),并且计算孩子元素的测量结果
测量孩子元素的大小通过measureChildWithMargins();
三、生命周期
一个视图会在它依附到一个已依附到window的布局结构时显示。
onAttachedToWindow() ,当window可以时调用
onDetachedFromWindow(),当视图从父元素中移除时调用(父元素必须依附到window)。例如当
activity被回收(finish()方法被调用)或者视图在listview中被回收。该方法可以用来停止动画和清理资源
四、定义自定义属性
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res/com.vogella.android.view.compoundview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
custom:titleText="Background color"
custom:valueColor="@android:color/holo_green_light"
/>
package com.vogella.android.view.compoundview;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class ColorOptionsView extends View {
private View mValue;
private ImageView mImage;
public ColorOptionsView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.Options, 0, 0);
String titleText = a.getString(R.styleable.Options_titleText);
int valueColor = a.getColor(R.styleable.Options_valueColor,
android.R.color.holo_blue_light);
a.recycle();
// more stuff
}
}
对于自定义属性中的format的值及其含义如下:
format属性值:reference 、color、boolean、dimension、float、integer、string、fraction、enum、flag
reference:参考某一资源ID。
(1)属性定义:
(2)属性使用:
android:layout_width = "42dip"
android:layout_height = "42dip"
android:background = "@drawable/图片ID"
/>
color:颜色值。
(1)属性定义:
(2)属性使用:
android:layout_width = "42dip"
android:layout_height = "42dip"
android:textColor = "#00FF00"
/>
boolean:布尔值。
(1)属性定义:
(2)属性使用:
android:layout_width = "42dip"
android:layout_height = "42dip"
android:focusable = "true"
/>
dimension:尺寸值。
(1)属性定义:
(2)属性使用:
android:layout_width = "42dip"
android:layout_height = "42dip"
/>
float:浮点值。
(1)属性定义:
(2)属性使用:
android:fromAlpha = "1.0"
android:toAlpha = "0.7"
/>
integer:整型值。
(1)属性定义:
(2)属性使用:
xmlns:android = "http://schemas.android.com/apk/res/android"
android:drawable = "@drawable/图片ID"
android:pivotX = "50%"
android:pivotY = "50%"
android:framesCount = "12"
android:frameDuration = "100"
/>
string:字符串。
(1)属性定义:
(2)属性使用:
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:apiKey = "0jOkQ80oD1JL9C6HAja99uGXCRiS2CGjKO_bc_g"
/>
fraction:百分数。
(1)属性定义:
(2)属性使用:
xmlns:android = "http://schemas.android.com/apk/res/android"
android:interpolator = "@anim/动画ID"
android:fromDegrees = "0"
android:toDegrees = "360"
android:pivotX = "200%"
android:pivotY = "300%"
android:duration = "5000"
android:repeatMode = "restart"
android:repeatCount = "infinite"
/>
enum:枚举值。
(1)属性定义:
(2)属性使用:
xmlns:android = "http://schemas.android.com/apk/res/android"
android:orientation = "vertical"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent">
flag:位或运算。
(1)属性定义:
(2)属性使用:
android:name = ".StyleAndThemeActivity"
android:label = "@string/app_name"
android:windowSoftInputMode = "stateUnspecified |stateUnchanged | stateHidden">
特别要注意:
属性定义时可以指定多种类型值。
(1)属性定义:
(2)属性使用:
android:layout_width = "42dip"
android:layout_height = "42dip"
android:background = "@drawable/图片ID|#00FF00"
/>
下面说说AttributeSet与TypedArray在自定义控件中的作用:
AttributeSet的作用就是在控件进行初始化的时候,解析布局文件中该控件的属性(key eg:background)与该值(value eg:@drawable/icon)的信息封装在AttributeSet中,传递给该控件(View)的构造函数。对于非Android自带的属性,在View类中处理时是无法识别的,因此需要我们自己解析。所以这就要用到另外一个类TypedArray。在AttributeSet中我们有属性名称,有属性值,但是控件如何知道哪个属性代表什么意思呢?这个工作就由TypedArray来做了。TypedArray对象封装了/values/attrs.xml中的styleable里定义的每个属性的类型信息,通过TypedArray我们就可以知道AttributeSet中封装的值到底是干什么的了,从而可以对这些数据进行应用。
AttributeSet就相当于一盒糖,TypedArray就相当于这盒糖上的标签说明,告诉用户每个糖的口味等。这盒糖有什么口味是由用户自己的styleable文件里面的内容来决定的。
五、练习
在 res/values下创建文件attrs.xml
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res/com.vogella.android.view.compoundview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:showDividers="middle"
android:divider="?android:attr/listDivider"
tools:context=".MainActivity" >
android:id="@+id/view1"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:background="?android:selectableItemBackground"
android:onClick="onClicked"
custom:titleText="Background color"
custom:valueColor="@android:color/holo_green_light"
/>
android:id="@+id/view2"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:background="?android:selectableItemBackground"
android:onClick="onClicked"
custom:titleText="Foreground color"
custom:valueColor="@android:color/holo_orange_dark"
/>
创建布局view_color_options.xml
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_centerVertical="true"
android:layout_marginLeft="16dp"
android:textSize="18sp"
/>
android:layout_width="26dp"
android:layout_height="26dp"
android:layout_centerVertical="true"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:layout_centerVertical="true"
android:visibility="gone"
/>
package com.vogella.android.customview.compoundview;
import com.vogella.android.view.compoundview.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class ColorOptionsView extends LinearLayout {
private View mValue;
private ImageView mImage;
public ColorOptionsView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.ColorOptionsView, 0, 0);
String titleText = a.getString(R.styleable.ColorOptionsView_titleText);
int valueColor = a.getColor(R.styleable.ColorOptionsView_valueColor,
android.R.color.holo_blue_light);
a.recycle();
setOrientation(LinearLayout.HORIZONTAL);
setGravity(Gravity.CENTER_VERTICAL);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.view_color_options, this, true);
TextView title = (TextView) getChildAt(0);
title.setText(titleText);
mValue = getChildAt(1);
mValue.setBackgroundColor(valueColor);
mImage = (ImageView) getChildAt(2);
}
public ColorOptionsView(Context context) {
this(context, null);
}
public void setValueColor(int color) {
mValue.setBackgroundColor(color);
}
public void setImageVisible(boolean visible) {
mImage.setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
package com.vogella.android.customview.compoundview;
import com.vogella.android.view.compoundview.R;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
public void onClicked(View view) {
String text = view.getId() == R.id.view1 ? "Background" : "Foreground";
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
}
-----------------------华丽的分割线---------------------
最后附上ViewConfiguration 类的源码
import android.app.AppGlobals;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.SparseArray;
/**
* 主要用来获取一些在UI中所使用到的标准常量,像超时、尺寸、距离
*/
public class ViewConfiguration {
/**
* 定义了水平滚动条的宽度和垂直滚动条的高度,单位是dip
*/
private static final int SCROLL_BAR_SIZE = 10;
/**
* 滚动条褪去所需要经历的时间,单位:milliseconds
*/
private static final int SCROLL_BAR_FADE_DURATION = 250;
/**
* 滚动条褪去之前的默认时间延迟,单位:milliseconds
*/
private static final int SCROLL_BAR_DEFAULT_DELAY = 300;
/**
* 定义褪去边缘的长度,单位:dip
*/
private static final int FADING_EDGE_LENGTH = 12;
/**
* 按下状态在子控件上的持续时间,单位:milliseconds
*/
private static final int PRESSED_STATE_DURATION = 64;
/**
* 定义一个按下状态转变成长按状态所需要持续的时间,单位:milliseconds
*/
private static final int DEFAULT_LONG_PRESS_TIMEOUT = 500;
/**
* 定义连续重复按键间的时间延迟,单位:milliseconds
*/
private static final int KEY_REPEAT_DELAY = 50;
/**
* 如果用户需要触发全局对话框,例如:关机,锁屏等,需要按下按钮所持续的事件,单位:milliseconds
*/
private static final int GLOBAL_ACTIONS_KEY_TIMEOUT = 500;
/**
* 定义一个触摸事件是点击还是滚动的事件间隔,如果在这个事件内没有移动,就认为这是一个点击,否则就是滚动,单位:milliseconds
*/
private static final int TAP_TIMEOUT = 180;
/**
* 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.
*/
private static final int JUMP_TAP_TIMEOUT = 500;
/**
* 定义双击的时间间隔,如果在这个时间内,就认为是双击
*/
private static final int DOUBLE_TAP_TIMEOUT = 300;
/**
* 定义双击最小的时间间隔
*/
private static final int DOUBLE_TAP_MIN_TIME = 40;
/**
* 定义一个触摸板触摸到释放可认为是一个点击事件而不是一个触摸移动手势的最大时间,
* 也就是说在这个时间内进行一次触摸和释放操作就可以认为是一次点击事件,单位:milliseconds
*/
private static final int HOVER_TAP_TIMEOUT = 150;
/**
* 定义一个触摸板在触摸释放之前可以移动的最大距离,
* 如果在这个距离之内就可以认为是一个点击事件,否则就是一个移动手势,单位:pixels
*/
private static final int HOVER_TAP_SLOP = 20;
/**
* 定义响应显示缩放控制的时间
*/
private static final int ZOOM_CONTROLS_TIMEOUT = 3000;
/**
* Inset in dips to look for touchable content when the user touches the edge of the screen
*/
private static final int EDGE_SLOP = 12;
/**
* 如果我们认为用户正在滚动,这里定义一个触摸事件可以滚动的距离,单位:dips
* 注意:这个值在这里定义只是作为那些没有提供上下文Context来决定密度和配置相关值的应用程序的一个备用值。
*/
private static final int TOUCH_SLOP = 8;
/**
* 定义双击事件之间可以移动的距离,单位:dips
*/
private static final int DOUBLE_TAP_TOUCH_SLOP = TOUCH_SLOP;
/**
* 定义用户尝试翻页滚动的触摸移动距离,单位:dips
*
* 注意:这个值在这里定义只是作为那些没有提供上下文Context来决定密度和配置相关值的应用程序的一个备用值。
*
*/
private static final int PAGING_TOUCH_SLOP = TOUCH_SLOP * 2;
/**
* 定义第一次点击和第二次点击可以认为是一次双击之间的距离。单位:dips
*/
private static final int DOUBLE_TAP_SLOP = 100;
/**
* Distance in dips 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最小的速度,单位:dips/s
*/
private static final int MINIMUM_FLING_VELOCITY = 50;
/**
* 一个fling最大的速度,单位:dips/s
*/
private static final int MAXIMUM_FLING_VELOCITY = 8000;
/**
* 分发一个重复访问事件的延迟事件,单位:milliseconds
*/
private static final long SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS = 100;
/**
* The maximum size of View's drawing cache, expressed in bytes. This size
* should be at least equal to the size of the screen in ARGB888 format.
*/
@Deprecated
private static final int MAXIMUM_DRAWING_CACHE_SIZE = 480 * 800 * 4; // ARGB8888
/**
* 滚动和滑动的摩擦系数
*/
private static final float SCROLL_FRICTION = 0.015f;
/**
* Max distance in dips to overscroll for edge effects
*/
private static final int OVERSCROLL_DISTANCE = 0;
/**
* Max distance in dips to overfling for edge effects
*/
private static final int OVERFLING_DISTANCE = 6;
private final int mEdgeSlop;
private final int mFadingEdgeLength;
private final int mMinimumFlingVelocity;
private final int mMaximumFlingVelocity;
private final int mScrollbarSize;
private final int mTouchSlop;
private final int mDoubleTapTouchSlop;
private final int mPagingTouchSlop;
private final int mDoubleTapSlop;
private final int mWindowTouchSlop;
private final int mMaximumDrawingCacheSize;
private final int mOverscrollDistance;
private final int mOverflingDistance;
private final boolean mFadingMarqueeEnabled;
private boolean sHasPermanentMenuKey;
private boolean sHasPermanentMenuKeySet;
static final SparseArray sConfigurations =
new SparseArray(2);
/**
* 这个方法被废除了,使用ViewConfiguration.get(Context)}替代
*/
@Deprecated
public ViewConfiguration() {
mEdgeSlop = EDGE_SLOP;
mFadingEdgeLength = FADING_EDGE_LENGTH;
mMinimumFlingVelocity = MINIMUM_FLING_VELOCITY;
mMaximumFlingVelocity = MAXIMUM_FLING_VELOCITY;
mScrollbarSize = SCROLL_BAR_SIZE;
mTouchSlop = TOUCH_SLOP;
mDoubleTapTouchSlop = DOUBLE_TAP_TOUCH_SLOP;
mPagingTouchSlop = PAGING_TOUCH_SLOP;
mDoubleTapSlop = DOUBLE_TAP_SLOP;
mWindowTouchSlop = WINDOW_TOUCH_SLOP;
//noinspection deprecation
mMaximumDrawingCacheSize = MAXIMUM_DRAWING_CACHE_SIZE;
mOverscrollDistance = OVERSCROLL_DISTANCE;
mOverflingDistance = OVERFLING_DISTANCE;
mFadingMarqueeEnabled = true;
}
/**
* 使用给定的context来创建一个新的配置。这个配置依赖于context里面不同的参数,例如显示的尺寸或者密度
* @param context 用来初始化这个view配置的应用上下文环境
*
* @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);
mMinimumFlingVelocity = (int) (density * MINIMUM_FLING_VELOCITY + 0.5f);
mMaximumFlingVelocity = (int) (density * MAXIMUM_FLING_VELOCITY + 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) {
IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
try {
sHasPermanentMenuKey = !wm.hasNavigationBar();
sHasPermanentMenuKeySet = true;
} catch (RemoteException ex) {
sHasPermanentMenuKey = false;
}
}
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;
}
/**
* 跟上面一个函数一样,只不过上面一个是创建一个ViewConfiguration对象,这里是直接通过这个静态方法返回一个对象
*/
public static ViewConfiguration get(Context context) {
final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
final int density = (int) (100.0f * metrics.density);
ViewConfiguration configuration = sConfigurations.get(density);
if (configuration == null) {
configuration = new ViewConfiguration(context);
sConfigurations.put(density, configuration);
}
return configuration;
}
/**
* @return 获取水平滚动条的宽带和垂直滚动条的高度
*
* 这个函数被废除,使用getScaledScrollBarSize()来代替
*/
@Deprecated
public static int getScrollBarSize() {
return SCROLL_BAR_SIZE;
}
/**
* @return 获取水平滚动条的宽带和垂直滚动条的高度
*/
public int getScaledScrollBarSize() {
return mScrollbarSize;
}
/**
* @return 滚动条褪去的持续时间
*/
public static int getScrollBarFadeDuration() {
return SCROLL_BAR_FADE_DURATION;
}
/**
* @return 滚动条褪去的延迟时间
*/
public static int getScrollDefaultDelay() {
return SCROLL_BAR_DEFAULT_DELAY;
}
/**
* @return 褪去边缘的长度
*
* 这个方法已经废弃,用getScaledFadingEdgeLength()替代.
*/
@Deprecated
public static int getFadingEdgeLength() {
return FADING_EDGE_LENGTH;
}
/**
* @return 褪去边缘的长度,单位:pixels
*/
public int getScaledFadingEdgeLength() {
return mFadingEdgeLength;
}
/**
* @return 在子控件上按住状态的持续时间
*/
public static int getPressedStateDuration() {
return PRESSED_STATE_DURATION;
}
/**
* @return 按住状态转变为长按状态需要的时间
*/
public static int getLongPressTimeout() {
return AppGlobals.getIntCoreSetting(Settings.Secure.LONG_PRESS_TIMEOUT,
DEFAULT_LONG_PRESS_TIMEOUT);
}
/**
* @return 重新按键时间
*/
public static int getKeyRepeatTimeout() {
return getLongPressTimeout();
}
/**
* @return 重复按键延迟时间
*/
public static int getKeyRepeatDelay() {
return KEY_REPEAT_DELAY;
}
/**
* @return 判断用户是单击还是滚动的时间,在这个时间内没有移动则是单击,否则是滚动
*/
public static int getTapTimeout() {
return TAP_TIMEOUT;
}
/**
* @return the duration in milliseconds we will wait to see if a touch event
* is a jump tap. If the user does not move within this interval, it is
* considered to be a tap.
*/
public static int getJumpTapTimeout() {
return JUMP_TAP_TIMEOUT;
}
/**
* @return 得到双击间隔时间,在这个时间内,则是双击,否则就是单击
*/
public static int getDoubleTapTimeout() {
return DOUBLE_TAP_TIMEOUT;
}
/**
* @return the minimum duration in milliseconds between the first tap's
* up event and the second tap's down event for an interaction to be considered a
* double-tap.
*
* @hide
*/
public static int getDoubleTapMinTime() {
return DOUBLE_TAP_MIN_TIME;
}
/**
* @return the maximum duration in milliseconds between a touch pad
* touch and release for a given touch to be considered a tap (click) as
* opposed to a hover movement gesture.
* @hide
*/
public static int getHoverTapTimeout() {
return HOVER_TAP_TIMEOUT;
}
/**
* @return the maximum distance in pixels that a touch pad touch can move
* before being released for it to be considered a tap (click) as opposed
* to a hover movement gesture.
* @hide
*/
public static int getHoverTapSlop() {
return HOVER_TAP_SLOP;
}
/**
* @return Inset in dips to look for touchable content when the user touches the edge of the
* screen
*
* @deprecated Use {@link #getScaledEdgeSlop()} instead.
*/
@Deprecated
public static int getEdgeSlop() {
return EDGE_SLOP;
}
/**
* @return Inset in pixels to look for touchable content when the user touches the edge of the
* screen
*/
public int getScaledEdgeSlop() {
return mEdgeSlop;
}
/**
* @return Distance in dips a touch can wander before we think the user is scrolling
*
* @deprecated Use {@link #getScaledTouchSlop()} instead.
*/
@Deprecated
public static int getTouchSlop() {
return TOUCH_SLOP;
}
/**
* @return Distance in pixels a touch can wander before we think the user is scrolling
*/
public int getScaledTouchSlop() {
return mTouchSlop;
}
/**
* @return Distance in pixels the first touch can wander before we do not consider this a
* potential double tap event
* @hide
*/
public int getScaledDoubleTapTouchSlop() {
return mDoubleTapTouchSlop;
}
/**
* @return Distance in pixels a touch can wander before we think the user is scrolling a full
* page
*/
public int getScaledPagingTouchSlop() {
return mPagingTouchSlop;
}
/**
* @return Distance in dips between the first touch and second touch to still be
* considered a double tap
* @deprecated Use {@link #getScaledDoubleTapSlop()} instead.
* @hide The only client of this should be GestureDetector, which needs this
* for clients that still use its deprecated constructor.
*/
@Deprecated
public static int getDoubleTapSlop() {
return DOUBLE_TAP_SLOP;
}
/**
* @return Distance in pixels between the first touch and second touch to still be
* considered a double tap
*/
public int getScaledDoubleTapSlop() {
return mDoubleTapSlop;
}
/**
* Interval for dispatching a recurring accessibility event in milliseconds.
* This interval guarantees that a recurring event will be send at most once
* during the {@link #getSendRecurringAccessibilityEventsInterval()} time frame.
*
* @return The delay in milliseconds.
*
* @hide
*/
public static long getSendRecurringAccessibilityEventsInterval() {
return SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS;
}
/**
* @return Distance in dips a touch must be outside the bounds of a window for it
* to be counted as outside the window for purposes of dismissing that
* window.
*
* @deprecated Use {@link #getScaledWindowTouchSlop()} instead.
*/
@Deprecated
public static int getWindowTouchSlop() {
return WINDOW_TOUCH_SLOP;
}
/**
* @return Distance in pixels a touch must be outside the bounds of a window for it
* to be counted as outside the window for purposes of dismissing that window.
*/
public int getScaledWindowTouchSlop() {
return mWindowTouchSlop;
}
/**
* @return Minimum velocity to initiate a fling, as measured in dips per second.
*
* @deprecated Use {@link #getScaledMinimumFlingVelocity()} instead.
*/
@Deprecated
public static int getMinimumFlingVelocity() {
return MINIMUM_FLING_VELOCITY;
}
/**
* @return 得到滑动的最小速度, 以像素/每秒来进行计算
*/
public int getScaledMinimumFlingVelocity() {
return mMinimumFlingVelocity;
}
/**
* @return Maximum velocity to initiate a fling, as measured in dips per second.
*
* @deprecated Use {@link #getScaledMaximumFlingVelocity()} instead.
*/
@Deprecated
public static int getMaximumFlingVelocity() {
return MAXIMUM_FLING_VELOCITY;
}
/**
* @return 得到滑动的最大速度, 以像素/每秒来进行计算
*/
public int getScaledMaximumFlingVelocity() {
return mMaximumFlingVelocity;
}
/**
* The maximum drawing cache size expressed in bytes.
*
* @return the maximum size of View's drawing cache expressed in bytes
*
* @deprecated Use {@link #getScaledMaximumDrawingCacheSize()} instead.
*/
@Deprecated
public static int getMaximumDrawingCacheSize() {
//noinspection deprecation
return MAXIMUM_DRAWING_CACHE_SIZE;
}
/**
* The maximum drawing cache size expressed in bytes.
*
* @return the maximum size of View's drawing cache expressed in bytes
*/
public int getScaledMaximumDrawingCacheSize() {
return mMaximumDrawingCacheSize;
}
/**
* @return The maximum distance a View should overscroll by when showing edge effects (in
* pixels).
*/
public int getScaledOverscrollDistance() {
return mOverscrollDistance;
}
/**
* @return The maximum distance a View should overfling by when showing edge effects (in
* pixels).
*/
public int getScaledOverflingDistance() {
return mOverflingDistance;
}
/**
* The amount of time that the zoom controls should be
* displayed on the screen expressed in milliseconds.
*
* @return the time the zoom controls should be visible expressed
* in milliseconds.
*/
public static long getZoomControlsTimeout() {
return ZOOM_CONTROLS_TIMEOUT;
}
/**
* The amount of time a user needs to press the relevant key to bring up
* the global actions dialog.
*
* @return how long a user needs to press the relevant key to bring up
* the global actions dialog.
*/
public static long getGlobalActionKeyTimeout() {
return GLOBAL_ACTIONS_KEY_TIMEOUT;
}
/**
* The amount of friction applied to scrolls and flings.
*
* @return A scalar dimensionless value representing the coefficient of
* friction.
*/
public static float getScrollFriction() {
return SCROLL_FRICTION;
}
/**
* Report if the device has a permanent menu key available to the user.
*
*
As of Android 3.0, devices may not have a permanent menu key available.
* Apps should use the action bar to present menu options to users.
* However, there are some apps where the action bar is inappropriate
* or undesirable. This method may be used to detect if a menu key is present.
* If not, applications should provide another on-screen affordance to access
* functionality.
*
* @return true if a permanent menu key is present, false otherwise.
*/
public boolean hasPermanentMenuKey() {
return sHasPermanentMenuKey;
}
/**
* @hide
* @return Whether or not marquee should use fading edges.
*/
public boolean isFadingMarqueeEnabled() {
return mFadingMarqueeEnabled;
}
}