工作记录:工作中有时需要将屏幕中的控件现实成图片并显示在屏幕上,比如在百度地图中自定义marker可能是一个带有进度条的图片,进度条随时更新进度,那就需要我们有这样的实现了。
这里记录两种实现方式:
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="match_parent"
android:text="button"
android:id="@+id/btn"
android:layout_height="wrap_content" />
<ImageView
android:layout_width="match_parent"
android:layout_height="100dp"
android:id="@+id/image"
android:layout_below="@id/btn"
android:layout_centerHorizontal="true"
android:background="@color/colorAccent"
/>
</RelativeLayout>
java代码:
package com.xuganwen.colorfullimage;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.Button;
import android.widget.ImageView;
import com.xuganwen.colorfullphoto.R;
public class FourthActivity extends AppCompatActivity {
private Button btn;
private ImageView image;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_fourth);
btn=(Button)findViewById(R.id.btn);
image=(ImageView)findViewById(R.id.image);
}
@Override
protected void onResume() {
super.onResume();
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setImageBitmap();
}
});
setImageBitmapOne();
}
/*
* 方法二
* */
private void setImageBitmapOne() {
btn.setDrawingCacheEnabled(true);
btn.buildDrawingCache(true);
ViewTreeObserver viewTreeObserver=btn.getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
btn.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Bitmap bitmap= Bitmap.createBitmap(btn.getMeasuredWidth(),btn.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas=new Canvas(bitmap);
btn.draw(canvas);
image.setImageBitmap(bitmap);
}
});
}
/*方法一
* */
private void setImageBitmap() {
btn.setDrawingCacheEnabled(true);
btn.buildDrawingCache(true);
Bitmap bitmap=btn.getDrawingCache();
image.setImageBitmap(bitmap);
}
}
注意:以上两种方法稍有不同,其实第二种方法是第一种方法的升级版,在第一中方法中,添加viewtreeobserver监听之后就可以不需要等到控件获取焦点(或者说界面完全绘制完成之后)才去获取到btn的长宽,可以直接在非交互代码中调用。
关于viewtreeobserver推荐一篇博客,想了解的可以去看看:viewtreeobserver的简单了解
引申:ScrollView的控件截屏:
/**
* 截取scrollview的屏幕
* **/
public static Bitmap getScrollViewBitmap(ScrollView scrollView) {
int h = 0;
Bitmap bitmap;
for (int i = 0; i < scrollView.getChildCount(); i++) {
h += scrollView.getChildAt(i).getHeight();
}
// 创建对应大小的bitmap
bitmap = Bitmap.createBitmap(scrollView.getWidth(), h,
Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
scrollView.draw(canvas);
return bitmap;
}
截屏获取屏幕截图:
View dView = getWindow().getDecorView();
dView.setDrawingCacheEnabled(true);
dView.buildDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(dView.getDrawingCache());
if (bitmap != null) {
try {
// 获取内置SD卡路径
String sdCardPath = Environment.getExternalStorageDirectory().getPath();
// 图片文件路径
String filePath = sdCardPath + File.separator + "screenshot.png";
File file = new File(filePath);
FileOutputStream os = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
os.flush();
os.close();
DebugLog.d("a7888", "存储完成");
} catch (Exception e) {
}
}