在Android中怎么获得控件宽高呢?第一反应是使用View.getWIdht()或View.getHeight()来获得。好,敲好代码如下

<span style="font-size:18px;">private LinearLayout layout;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);layout = (LinearLayout) findViewById(R.id.layout);int width = layout.getWidth();int height = layout.getHeight();Log.i("man", "width=" + width + ";height=" + height);</span>

可是结果确实这样

01-08 23:22:20.256: W/ApplicationPackageManager(13371): getCSCPackageItemText()
01-08 23:22:20.296: E/MoreInfoHPW_ViewGroup(13371): Parent view is not a TextView
01-08 23:22:20.306: I/man(13371): width=0;height=0
咦!怎么回事?接着在onStart()和onResume()方法中试验了下,

01-08 23:25:26.046: I/man onStart(15544): width=0;height=0
01-08 23:25:26.046: I/man onResume(15544): width=0;height=0

有没有很奇怪?原来Android程序的运行机制决定了无法再组件类外部使用getWidth()和getHeight()来获得宽度和高度(在自定义组件类的内容可以通过这两个方法获取当前组件的宽度和高度,如在onSizeChanged方法中可以使用这两个方法获得宽度和高度),必须使用View.getMeasuredWidth()和View.getMeasuredHeight()。当然,光有这两个方法还是不够的,在这之前还必须调用View.measure方法先测量组件的宽度和高度。好,现在加上了这些方法再试下:

<span style="font-size:18px;">private LinearLayout layout;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);layout = (LinearLayout) findViewById(R.id.layout);int width = layout.getWidth();int height = layout.getHeight();Log.i("man", "width=" + width + ";height=" + height);layout.measure(0, 0);width = layout.getMeasuredWidth();height = layout.getMeasuredHeight();Log.i("man", "width=" + width + ";height=" + height);</span>

01-08 23:36:50.856: I/man(16487): width=0;height=0
01-08 23:36:50.856: I/man(16487): width=462;height=240
好像是获取到了,不为0了,但是我又发现了个问题,先看我的布局文件:

<LinearLayout 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"    android:id="@+id/layout"    tools:context="com.huxq.screenshot.MainActivity" >    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/hello_world" />    <ImageView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:src="@drawable/ic_launcher" /></LinearLayout>
明明LInearLayout是全屏的啊,而且我用的测试机是Galaxy Note3,分辨率是1920x1080像素的,怎么只有462x240呢?

后来发现,如果控件的宽度或高度设为fill_parent或match_parent,使用getMeasuredWidth或getMeasuredHeight方法获取组件宽度或高度时,当组建中包含其他子组件时,所获得的实际值是这鞋组件所占的最小宽度和最小高度。

还有一种方法也可以获取在布局文件中定义的组件的宽度和高度,直接使用View.getLayoutParams().width和View.getLayoutParams().height。但是当宽度和高度被设为match_parent或wrap_content时,这两个变量返回的是MATCH_PARENT和WRAP_CONTENT常量的值,这并不是我们想要的。

接下来介绍在Android中实现截屏功能的一种很简单却实用的方法。

Android允许直接将布局中的View存在图片,因此在Android SDK中提供了API直接将可视组件绘制到bitmap上。绘制可视组件主要涉及到View.setDrawingCacheEnabled方法和View.getDrawingCache方法。下面看代码:

private LinearLayout layout;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);layout = (LinearLayout) findViewById(R.id.layout);int width = layout.getWidth();int height = layout.getHeight();Log.i("man", "width=" + width + ";height=" + height);//打开图像缓存layout.setDrawingCacheEnabled(true);//测量Linearlayout的大小layout.measure(0, 0);width = layout.getMeasuredWidth();height = layout.getMeasuredHeight();Log.i("man", "width=" + width + ";height=" + height);//发送位置和尺寸到LienarLayout及其所有的子View//简单地说,就是我们截取的屏幕区域,注意是以Linearlayout左上角为基准的,而不是屏幕左上角layout.layout(0, 0, width, height);//拿到截取图像的bitmapBitmap bitmap = layout.getDrawingCache();FileOutputStream fos = null;//获得sd卡路径String rootPath = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) ? Environment.getExternalStorageDirectory().getAbsolutePath() : null;//不存在文件夹就新建一个try {File file = new File(rootPath + "/screenShot/");if (!file.exists()) {file.mkdirs();}fos = new FileOutputStream(rootPath + "/screenShot/"+ System.currentTimeMillis() + ".png");//把bitmap压缩成png格式,并通过fos写入到目标文件bitmap.compress(CompressFormat.PNG, 100, fos);} catch (FileNotFoundException e) {e.printStackTrace();} finally {if (fos != null) {try {fos.close();} catch (IOException e) {e.printStackTrace();}}}

最后要提醒大家一点就是manifest文件中不要忘了添加读写sd卡的权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

所有的代码都在demo里了

点击下载DEMO






更多相关文章

  1. android发展计划,技术栈
  2. Android(安卓)组件动画
  3. Android(安卓)Handler 通信 - 彻底了解 Handler 的通信过程
  4. Android新线程中更新主线程UI中的View方法汇总
  5. Java super关键字(android中常见)
  6. Service简析
  7. android应用程序最小化的处理方法
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. Android中attr自定义标签详解
  2. Android练手小项目(KTReader)基于mvp架构(三
  3. 使用Android(安卓)Studio为系统级的app签
  4. android 设置布局为无标题样式
  5. android 通过 button 弹出menu
  6. 【技术直通车】ArcGIS for Android地图控
  7. android stuido中修改最低sdk
  8. Android AIDL 理解及开发要点
  9. android ndk 入门3 - log实现
  10. 布局(2、相对布局)