在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 和 JS 交互时调用不成功解决方法
  2. Android 组件动画
  3. android应用程序最小化的处理方法
  4. Android新线程中更新主线程UI中的View方法汇总
  5. 彻底解决Android 应用方法数不能超过65536的问题
  6. android install faild insufficient storage错误的解决方法
  7. Android用户界面UI组件--AdapterView及其子类(三) ExpandableLis
  8. [Android]ListView & ViewPager & GridView 常见问题解决方法
  9. Android中数据存储的几种方法

随机推荐

  1. Android网络编程——https 不验证证书方
  2. [译文]移动应用开发,第1部分:在Android上应
  3. Android无法自动创建以usb开头的节点
  4. Android 3 使用 smartTable 表格工具 实
  5. [置顶] Android 的媒体路由功能应用与框
  6. Android 滑动切换页面 以及屏幕手势
  7. 在线自动生成.9png图的Android设计切图工
  8. Android花样loading进度条(四)-渐变色环形
  9. Android多分辨率多屏幕密度下UI适配方案
  10. Android 指纹识别(给应用添加指纹解锁)