在Android中怎么获得控件宽高呢?第一反应是使用View.getWIdht()或View.getHeight()来获得。好,敲好代码如下
<span style="font-size:18px;">private LinearLayout layout;
@Override
protected 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;
@Override
protected 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;
@Override
protected 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);
//拿到截取图像的bitmap
Bitmap 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里了