Activity界面区域划分
如图:最大的红色区域是屏幕界面,绿色次大区域我们称之为“应用界面区域”,蓝色的区域我们称之为“View绘制区域”;屏幕顶端、应用界面区之外的那部分显示手机电池网络运营商信息的为“状态栏”,应用区域顶端、View绘制区外部显示Activity名称的部分我们称为“标题栏”。
获取状态栏高度
获取状态栏一般常用的有三种方法:
-
通过系统资源尺寸获取
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); if(resourceId > 0){ int statusBarHeight = getResources().getDimensionPixelSize(resourceId); }
使用getIdentifier()方法
方法一
Resources resources = context.getResources();
int resourceId = resources.getIdentifier(com.test.androidtest:drawable/icon",null,null);
第一个参数格式是:包名 + : + 资源文件夹名 + / +资源名,然后其他的可以为null #####方法二
Resources resources = context.getResources();
int resourceId = getResources().getIdentifier("icon", "drawable", "com.test.androidtest");第一个参数为ID名,第二个为资源属性是ID或者是Drawable,第三个为包名。 一般来讲是推荐第二种方法
在获取状态栏高度时, 因为状态栏高度定义在Android系统尺寸资源中status_bar_height
,但并不能公开使用,一般会像这样使用:android.R.dimen.status_bar_height
,由于系统为我们提供了一个Resource类,所以我们可以通过这个类来获取资源 status_bar_height
.
因此代码的写法是
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
可对照getIdentifier()的方法二进行比对
-
使用屏幕和应用区域高度的差值确定
// 获取状态栏高度 Rect frame = new Rect(); // 测量屏幕宽和高 view.getWindowVisibleDisplayFrame(frame); int stautsHeight = frame.top;
如果单单获取statusBar高度而不获取titleBar高度时,这种方法并不推荐大家使用,因为这种方法依赖于WMS(窗口管理服务的回调)。正是因为窗口回调机制,所以在Activity初始化时执行此方法得到的高度是0,这就是很多人获取到statusBar高度为0的原因。这个方法推荐在回调方法onWindowFocusChanged()中执行,才能得到预期结果。
-
使用应用区域的top属性
//屏幕 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); //应用区域 Rect outRect1 = new Rect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect1); int statusBar = dm.heightPixels - outRect1.height(); //状态栏高度=屏幕高度-应用区域高度
获取标题栏高度
- 通过View提供的方法获取高度
int viewTop = activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
通过Activity的getWindow().findViewById(Window.ID_ANDROID_CONTENT)获取系统当前显示的view根(是一个framelayout对象),android绘制会将要绘制的view放置在framelayout中绘制。
- 通过屏幕获取高度
int statusHeight = -1;
//屏幕
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusHeight = activity.getResources().getDimensionPixelSize(resourceId);
}
//View绘制区域,//viewtop方法一
Rect outRect2 = new Rect();
activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(outRect2);
int viewTop = dm.heightPixels - statusHeight - outRect2.height();
写入SD卡
private static boolean savePic(Bitmap pBitmap, File strName) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(strName);
if (null != fos) {
pBitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.flush();
fos.close();
return true;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
关于flush()方法,api中有如下描述
刷新此输出流并强制写出所有缓冲的输出字节(刷新数据并将数据转交给操作系统 )
实现截图
/**
* 截图
*
* @param activity
* @return 截图并且保存sdcard成功返回true,否则返回false
*/
public static boolean shotBitmap(Activity activity) {
String sdCardDir = Environment.getExternalStorageDirectory() + "/jietu/";
File dirFile = new File(sdCardDir); //目录转化成文件夹
if (!dirFile.exists()) { //如果不存在,那就建立这个文件夹
dirFile.mkdirs();
}
//指定目录
File file = new File(sdCardDir, System.currentTimeMillis() + ".png");
return ScreenShotUtils.savePic(takeScreenShot(activity), file);
}
Environment.getExternalStorageDirectory()是获得根目录,System.currentTimeMillis()是获得系统时间
File file = new File(sdCardDir, System.currentTimeMillis() + ".png");
这句话的意思就是,截下来的图以 ==当前系统时间戳.png== 的形式存到根目录下的 ==jietu== 文件夹下。
终极代码
MainActivity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
boolean result = ScreenShotUtils.shotBitmap(MainActivity.this);
if (result) {
Toast.makeText(MainActivity.this, "截图成功.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "截图失败.", Toast.LENGTH_SHORT).show();
}
}
});
}
}
ScreenShotUtils:
/**
* 进行截屏工具类
*/
public class ScreenShotUtils {
/**
* 进行截取屏幕
*
* @param activity
* @return bitmap
*/
public static Bitmap takeScreenShot(Activity activity) {
Bitmap bitmap = null;
int statusHeight = -1;
View view = activity.getWindow().getDecorView();
// 设置是否可以进行绘图缓存
view.setDrawingCacheEnabled(true);
// 如果绘图缓存无法,强制构建绘图缓存
view.buildDrawingCache();
// 返回这个缓存视图
bitmap = view.getDrawingCache();
Log.d("123", "bitmap.getHeight():" + bitmap.getHeight());
int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusHeight = activity.getResources().getDimensionPixelSize(resourceId);
}
int viewTop = activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
int width = activity.getWindowManager().getDefaultDisplay().getWidth();
int height = activity.getWindowManager().getDefaultDisplay().getHeight();
// 根据坐标点和需要的宽和高创建bitmap
bitmap = Bitmap.createBitmap(bitmap, 0, statusHeight + viewTop, width, height - statusHeight - viewTop);
return bitmap;
}
/**
* 保存图片到sdcard中
*
* @param pBitmap
*/
private static boolean savePic(Bitmap pBitmap, File strName) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(strName);
if (null != fos) {
pBitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.flush();
fos.close();
return true;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
/**
* 截图
*
* @param activity
* @return 截图并且保存sdcard成功返回true,否则返回false
*/
public static boolean shotBitmap(Activity activity) {
String sdCardDir = Environment.getExternalStorageDirectory() + "/wurenji/";
File dirFile = new File(sdCardDir); //目录转化成文件夹
if (!dirFile.exists()) { //如果不存在,那就建立这个文件夹
dirFile.mkdirs();
}
//指定目录
File file = new File(sdCardDir, System.currentTimeMillis() + ".png");
return ScreenShotUtils.savePic(takeScreenShot(activity), file);
}
}
activity_main.xml
参考博客