转载

Viewconfiguration和configuration类使用

ViewConfiguration类

ViewConfiguration是系统中关于视图的各种特性的常量记录对象。其中包含各种基础数据,在编写自定义控件时会用经常用到。

下面介绍几个常用的方法:

1.在可滑动的控件中用于区别单击子控件和滑动操作的一个伐值。

mTouchSlop = configuration.getScaledTouchSlop();

2.用于设置最小加速率和最大速率.

mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();

3.滚动距离

mOverscrollDistance = configuration.getScaledOverscrollDistance();

4.fling距离

mOverflingDistance = configuration.getScaledOverflingDistance();

5.摩擦力,用来计算减速度

mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction());

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   //flings和scrolls摩擦力度大小的系数   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;   } 

API:14以后提供了方法判断是否有物理按键:ViewConfiguration.hasPermanentMenuKey(). 一般来说物理按键和虚拟按键只会有一种。可以用这个方法来判断是否有导航栏NavigationBar和计算NavigationBar的高度。

判断是否有导航栏NavigationBar:

public static boolean checkDeviceHasNavigationBar(Context activity) {    //通过判断设备是否有返回键、菜单键(不是虚拟键,是手机屏幕外的按键)来确定是否有navigation bar    boolean hasMenuKey = ViewConfiguration.get(activity)      .hasPermanentMenuKey();    boolean hasBackKey = KeyCharacterMap      .deviceHasKey(KeyEvent.KEYCODE_BACK);    if (!hasMenuKey && !hasBackKey) {     // 做任何你需要做的,这个设备有一个导航栏     return true;    }    return false;   } 

计算NavigationBar的高度:

public int getNavigationBarHeight(Context c) {  int result = 0;  boolean hasMenuKey = ViewConfiguration.get(c).hasPermanentMenuKey();  boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);  if (!hasMenuKey && !hasBackKey) {   //The device has a navigation bar   Resources resources = c.getResources();   int orientation = getResources().getConfiguration().orientation;   int resourceId;   if (isTablet(c)) {    resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape", "dimen", "android");   } else {    resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_width", "dimen", "android");   }   if (resourceId > 0) {    return getResources().getDimensionPixelSize(resourceId);   }  }  return result; } 

Configuration类

Configuration类虽然和ViewConfiguration类名字之差一个“view”,但是二者并无继承关系,也没有共同的父类。 Configuration类是专门用来描述手机设备上的配置信息。这些配置信息包括用户特定的配置项,也包括系统的动态设备配置。

程序中可调用Activity的如下方法来获取Configuration对象

//获取系统的Configuration对象 Configuration cfg = getResources().getConfiguration();

其中以下的参数代表的配置信息:

  • fontScale:获取当前用户设置的字体的缩放因子。

  • keyboard:获取当前设备所关联的键盘类型。该属性的返回值:KEYBOARD_12KEY(只有12个键的小键盘)、KEYBOARD_NOKEYS、KEYBOARD_QWERTY(普通键盘)

  • keyboardHidden:该属性返回一个boolean值用于标识当前键盘是否可用。该属性不仅会判断系统的硬件键盘,也会判断系统的软键盘(位于屏幕)。

  • locale:获取用户当前的Locale.

  • mcc:获取移动信号的国家码

  • mnc:获取移动信号的网络码

  • navigation:判断系统上方向导航设备的类型。该属性的返回值:NAVIGATION_NONAV(无导航)、NAVIGATION_DPAD(DPAD导航) NAVIGATION_TRACKBALL(轨迹球导航)、NAVIGATION_WHEEL(滚轮导航)

  • orientation:获取系统屏幕的方向。该属性的返回值:ORIENTATION_LANDSCAPE(横向屏幕)、ORIENTATION_PORTRAIT(竖向屏幕)

  • touchscreen:获取系统触摸屏的触摸方式。该属性的返回值:TOUCHSCREEN_NOTOUCH(无触摸屏)、TOUCHSCREEN_STYLUS(触摸笔式触摸屏)、

  • TOUCHSCREEN_FINGER(接收手指的触摸屏)

下面写一个监听屏幕旋转的demo:

MainActivity如下:

public class MainActivity extends Activity {  private Button mButton;  @Override  protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);   setContentView(R.layout.activity_main);   System.out.println("---> onCreate()");   init();  }  private void init(){   mButton=(Button) findViewById(R.id.button);   mButton.setOnClickListener(new ClickListenerImpl());  }  private class ClickListenerImpl implements View.OnClickListener {   @Override   public void onClick(View v) {    getConfigurationInfo();   }  }  private void getConfigurationInfo(){   Configuration configuration=getResources().getConfiguration();   //获取屏幕方向   int l=configuration.ORIENTATION_LANDSCAPE;   int p=configuration.ORIENTATION_PORTRAIT;   if (configuration.orientation==l) {    System.out.println("现在是横屏");   }   if (configuration.orientation==p) {    System.out.println("现在是竖屏");   }   //获取国家码和网络码   int countryNum=configuration.mcc;   int netNum=configuration.mnc;   System.out.println("国家码="+countryNum+",网络码="+netNum);  }  @Override  public void onConfigurationChanged(Configuration newConfig) {   super.onConfigurationChanged(newConfig);   System.out.println("---> onConfigurationChanged()");  }  @Override  protected void onSaveInstanceState(Bundle outState) {   super.onSaveInstanceState(outState);   outState.putString("name", "mxn");   outState.putInt("id", 21);   System.out.println("---> onSaveInstanceState()");  }  @Override  protected void onRestoreInstanceState(Bundle savedInstanceState) {   super.onRestoreInstanceState(savedInstanceState);   String name=savedInstanceState.getString("name");   int id=savedInstanceState.getInt("id");   System.out.println("---> onRestoreInstanceState()");   System.out.println("名字="+name+",编号="+id);  } } 

main.xml如下:

<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:tools="http://schemas.android.com/tools"  android:layout_width="match_parent"  android:layout_height="match_parent"  >  <Button   android:id="@+id/button"   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:text="获取Configuration信息"   android:textSize="25sp"   android:layout_marginTop="80dip"   android:layout_centerHorizontal="true"   />  <TextView   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:text="测试ConfigurationChange"   android:textSize="25sp"   android:layout_centerInParent="true"   /> </RelativeLayout> 

AndroidManifest.xml如下:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"  package="com.mxn.soul.demo" >  <application   android:allowBackup="true"   android:icon="@mipmap/icon"   android:label="@string/app_name"   android:name=".BaseApplication"   android:theme="@style/AppTheme" >   <activity    android:name=".MainActivity"    android:configChanges="keyboardHidden|orientation|screenSize"    android:label="@string/app_name" >    <intent-filter>     <action android:name="android.intent.action.MAIN" />     <category android:name="android.intent.category.LAUNCHER" />    </intent-filter>   </activity>  </application> </manifest> 

1.点击Button利用Configuration查看手机上的配置信息

11-27 11:56:41.763 4093-4093/com.mxn.soul.demo I/System.out: 现在是横屏 11-27 11:56:41.763 4093-4093/com.mxn.soul.demo I/System.out: 国家码=0,网络码=0

2.在manifest为Activity配置configChanges时,旋转屏幕,输出如下:

11-27 11:59:26.827 8684-8684/com.mxn.soul.demo I/System.out: ---> onCreate() 11-27 11:59:31.110 8684-8684/com.mxn.soul.demo I/System.out: ---> onConfigurationChanged()

由于设备和系统版本的差异,少数情况下设置android:configChanges="orientation" 无效, 建议设置为:android:configChanges="keyboardHidden|orientation|screenSize" ,表示当前Activity可以对屏幕是否旋转进行监听 (当然也可对其他系统信息进行监听) 配置后屏幕旋转时会调用onConfigurationChanged()方法.

注意:当onConfigurationChanged发生之后,并不会对activiyt的生命周期有影响的,也就是说当横竖修改之后,android 并不会有任何生命周期的变化。同理还有(键盘显示或者隐藏、用户的语言设置、用户字体修改、对键盘类型修改、键盘导航修改) 这些都可以触发相关的activity的事件产生。

android:configChanges配置说明:

Android通过终止、重启应用程序来重新加载资源文件,以做到对语言、区域和硬件实时变化的支持。它的默认的行为不是总是方便和令人满意的, 尤其当配置变化(如屏幕方向和键盘可视)、用户旋转设备或划出键盘等。你可以通过监测和响应定制你的应用程序来对这些变化作出响应。 为了能让Activity能监听实时的配置变化,需要在manifest节点里添加“android:configChanges”特性,指定你要处理的配置变化事件。 接下来的列表给出了你可以指定的配置变化的事件值:

orientation 屏幕在纵向和横向间旋转。 keyboardHidden 键盘显示或隐藏。 fontScale 用户变更了首选的字体大小。 locale 用户选择了不同的语言设定。 keyboard 键盘类型变更,例如手机从12键盘切换到全键盘 ouchscreen或navigation 键盘或导航方式变化,一般不会发生这样的事件。

你可以选择捕获多个事件,通过在各事件值间使用“|”。 override onConfigurationChanged这个方法去捕获配置变化,通过传入的Configuration 对象的值进行合适的处理。 需要提醒的是需要调用父类的方法super.onConfigurationChanged(newConfig);并且要重新加载Activity使用的资源,以防有变更。

当onConfigurationChanged 被调用时,Activity的资源变量都已经用新的值进行了更新,所以它们是安全的。任何你没有显式指明的配置变化事件, 都将由应用程序捕获,而且仍然会引起应用程序的重启,而不会调用onConfigurationChanged 方法。

3.若不配置android:configChanges,那么每次屏幕旋转的时候都会调用Activity的onCreate()方法 而不会调用onConfigurationChanged()。取消在2中的设置 .此时每次旋转屏幕都会调用onCreate(),并在屏幕旋转前调用onSaveInstanceState()保存现场状态,在选中后调用onRestoreInstanceState() 恢复现场. 所以此时调用顺序为: onSaveInstanceState->onCreate()->onRestoreInstanceState()。除此以外: 当系统内存紧张时可暂时杀死该Activity,内存允许时重启该Activity.在这样情况下也是该调用顺序,原理亦类似.

输出如下:

11-27 12:04:07.508 13914-13914/com.mxn.soul.demo I/System.out: ---> onCreate() 11-27 12:04:11.400 13914-13914/com.mxn.soul.demo I/System.out: ---> onSaveInstanceState() 11-27 12:04:11.464 13914-13914/com.mxn.soul.demo I/System.out: ---> onCreate() 11-27 12:04:11.465 13914-13914/com.mxn.soul.demo I/System.out: ---> onRestoreInstanceState() 11-27 12:04:11.465 13914-13914/com.mxn.soul.demo I/System.out: 名字=mxn,编号=21

另外还有一个判断是否是平板的方法如下(官方用法):

public static boolean isTablet(Context context) {         return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;     }
正文到此结束
Loading...