view到图片共三步:1.初始化布局;2.布局转bitmap;3.bitmap存本地
将当前展示的布局生成图片
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.name);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
catchScreen();
}
});
}
private void catchScreen() {
// 1. 初始化布局:
View decorView = this.getWindow().getDecorView();
decorView.setDrawingCacheEnabled(true);
decorView.buildDrawingCache();
// decorView.measure(View.MeasureSpec.makeMeasureSpec(decorView.getWidth(), View.MeasureSpec.EXACTLY),
// View.MeasureSpec.makeMeasureSpec(decorView.getHeight(), View.MeasureSpec.EXACTLY));
// decorView.layout((int) decorView.getX(), (int) decorView.getY(), (int) decorView.getX() + decorView.getMeasuredWidth(), (int) decorView.getY() + decorView.getMeasuredHeight());
createPicture(decorView);
}
// 2. 将布局转成bitmap
private void createPicture(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache(), 33, 91, 686, 938);
view.setDrawingCacheEnabled(false);
view.destroyDrawingCache();
//3. 将bitmap存入本地
String strPath = "/testSaveView/" + UUID.randomUUID().toString() + ".png";
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File sdCardDir = Environment.getExternalStorageDirectory();
FileOutputStream fos = null;
try {
File file = new File(sdCardDir, strPath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
fos = new FileOutputStream(file);
//当指定压缩格式为PNG时保存下来的图片显示正常
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
Log.e("MainActivity", "图片生成:" + file.getAbsolutePath());
fos.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
if (!bitmap.isRecycled()) {
bitmap.recycle();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
动态的xml布局,没有父布局
这种情况比较难处理,我的布局属于这种,但是这样加载的布局,容易显示不全,延迟操作,不能根本解决,数据无法更新,看代码吧!
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.beauty);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
saveImage();
}
});
}
// 1. 初始化布局:
private void saveImage() {
LayoutInflater from = LayoutInflater.from(MyApplication.context);
WindowManager manager = this.getWindowManager();
DisplayMetrics outMetrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(outMetrics);
int width = outMetrics.widthPixels;
int height = outMetrics.heightPixels;
View viewById = from.inflate(R.layout.poster_layout, null);
LinearLayout ll_poster = viewById.findViewById(R.id.ll_poster);
viewById.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
viewById.layout(0, 0, viewById.getMeasuredWidth(), viewById.getMeasuredHeight());
ImageView imageView = viewById.findViewById(R.id.im_head_portrait);
imageView.setImageResource(R.mipmap.wx_default_male);
TextView textView = viewById.findViewById(R.id.name);
textView.setText("张三");
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.width = width;
params.height = height;
params.gravity = Gravity.CENTER;
ll_poster.setLayoutParams(params);
// viewById.setLayoutParams(params);
// manager.addView(viewById, params);
// View viewById = findViewById(R.id.ll_poster);
viewById.setDrawingCacheEnabled(true);
viewById.buildDrawingCache();
// 2. 将布局转成bitmap
createPicture(viewById);
}
private void createPicture(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
view.destroyDrawingCache();
//3.bitmap存本地
String strPath = "/testSaveView/" + UUID.randomUUID().toString() + ".png";
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File sdCardDir = Environment.getExternalStorageDirectory();
FileOutputStream fos = null;
try {
File file = new File(sdCardDir, strPath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
fos = new FileOutputStream(file);
//当指定压缩格式为PNG时保存下来的图片显示正常
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
Log.e("MainActivity", "图片生成:" + file.getAbsolutePath());
//当指定压缩格式为JPEG时保存下来的图片背景为黑色
// bitmap.compress(CompressFormat.JPEG, 100, fos);
fos.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
if (!bitmap.isRecycled()) {
bitmap.recycle();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
主要参考了这几篇文章:
android生成将布局生成海报保存并分享
Android 布局生成分享图片
Android笔记:将布局转换成图片
手写View实现
这样不会担心布局不全,数据赋不上,看代码
LinearLayout weexSharePoster = new LinearLayout(activity);
weexSharePoster.setPadding(ScreenUtil.dip2px(16), ScreenUtil.dip2px(16), ScreenUtil.dip2px(21.5f), 0);
weexSharePoster.setBackground(activity.getDrawable(R.drawable.weex_share_bg));
weexSharePoster.setOrientation(LinearLayout.VERTICAL);
之后就不断到添加各种view进去就好了,有个课表分享的,类似,可以参考一下
Android 合并生成分享图片(View截图)
终于搞定!
之后就直接拿file或者bitmap分享到微信就好了。
– 还遇到个问题,在手写view的时候,因为我们底层都是用px测量大小,所有dp2px,然后我把sp2px,发现文字大了好多,最后看源码发现,textview.setTextSize(float value);默认就是按照sp的模式定义的,底层自动转px,所以我们不需要操作。拿走不谢~~