本文主要记录Android系统截屏一键分享开发,后续优化。 近期接到新需求,需要做截屏,然后弹出小窗口,显示一键分享与截屏小图预览。类似于同花顺app截图弹出框,点击后出现分享
近期接到新需求,需要做截屏,然后弹出小窗口,显示一键分享与截屏小图预览。类似于同花顺app截图弹出框,点击后出现分享界面.
效果图如下:
·一,分析该需求的整个流程,大致步骤如下
1,监听到截图的动作 2,获取当前图像 3,弹出提示框(显示截屏预览小图,带计时器自动隐藏) 4,点击分享后弹出分享窗,分享图片预览 5,点击某个平台后,生成自定义拼图分享到第三方其中监听截图动作,和图片展示与拼接是重点步骤。
二,实现方式,技术选择
1,目前兼容性较高的截图监听方案为ContentObserver,可以兼容到android9.0。android10目前还在调研中(目前未发现有效方法)
具体代码不多赘述,百度一大把,标准套路,记录几个核心问题,首先解决如何精准拿到截图问题。
String[] KEYWordS = { "screenshot", "screenshots", "screen_shot", "screen-shot", "screen shot", "screencapture", "screen_capture", "screen-capture", "screen capture", "screencap", "screen_cap", "screen-cap", "screen cap", "截屏" }
过滤拿到的路径是否包含上述关键词,此时,没必要继续拿图片,只是监听到有截图动作即可,调用view截图生成bitmap方式,这样,保证最准确。同时,可以排除无用信息提示框,Toast等窗口。
此方法生成当前窗口的截图
/ * 截取当前窗体的截图,根据[isshowStatusBar]判断是否包含当前窗体的状态栏
* 原理是获取当前窗体decorView的缓存生成图片
*/
public static Bitmap captureWindow(Activity activity) {
boolean isStatuBar = false;
// 获取当前窗体的View对象
View view = activity.getWindow().getDecorView();
view.setDrawinGCacheEnabled(true);
// 生成缓存
view.buildDrawingCache();
Bitmap bitmap = null;
if (isStatuBar) {
// 绘制整个窗体,包括状态栏
bitmap = Bitmap.createBitmap(view.getDrawingCache(), 0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
} else {
// 获取状态栏高度
Rect rect = new Rect();
view.getWindowVisibleDisplayFrame(rect);
Display display = activity.getWindowManager().getDefaultDisplay();
// 减去状态栏高度
bitmap = Bitmap.createBitmap(view.getDrawingCache(), 0,
rect.top, display.getWidth(), display.getHeight() - rect.top);
}
view.setDrawingCacheEnabled(false);
view.destroyDrawingCache();
return bitmap;
}
生成bitmap 之后,考虑如何添加到当前Activity。方式有三种Popuwindow, dialog,和直接addView 方式。综合考虑,直接addView添加小窗口最合适。考虑如下,PopuWindow 和dialog弹出后,会抢占焦点,这样无法继续与原界面交互,那么倒计时小时的功能也变的无用。
为了考虑通用型,每个Activity可以操作到的根布局为contentView ,为Framelayout。
//直接拿到contentView然后Inflate窗口view。设置好位置后,addView 到contentView,这样,使用倒计时销毁时,直接contentView.remove()即可。保证了每个界面添加的通用型,即使嵌套Fragment,也不用考虑焦点问题。
final ViewGroup viewById = mContext.findViewById(android.R.id.content);
final View view = View.inflate(mContext,R.layout.screen_shot_dialog,null);
FrameLayout.LayoutParams f = new FrameLayout.LayoutParams(width,height);
f.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;
f.rightMargin = DisplayUtil.dip2px(mContext,20);
view.setLayoutParams(f);
final Bitmap bitmap = Utils.captureWindow(mContext); //获取当前窗口影像图片 替代从文件库取
imageView.setImageDrawable(new BitmapDrawable(bitmap));
viewById.addView(view);//最终添加到当前Activity
2,自定义分享图片的拼接问题。
思路有二,一可以使用canvas绘制bitmap,拼接。方法主要难点在绘制位置,以及性能开销。(标准api,课自行百度)
二,可以同样借鉴View生成图片方案,先创建一个布局,在相关位置填好截屏图片,二维码,文字等。然后生成bitmap。注意,在调用以下方法,view必须添加到布局且重绘完毕,所以,可以使用view.postRunable()。在runalbe任务里面生成图片,以保证view准备完毕。
public static Bitmap captureView(View view) {
view.setDrawingCacheEnabled(true);
// 生成缓存
view.buildDrawingCache();
Bitmap bitmap = null;
// 绘制整个view
bitmap = Bitmap.createBitmap(view.getDrawingCache(), 0, 0,view.getWidth(), view.getHeight());
view.setDrawingCacheEnabled(false);
view.destroyDrawingCache();
return bitmap;
}
在此注意,可以先添加到contentview 中,设置为隐藏,待生成完毕后,再移除掉。以保证生成正确。
final View shareView = View.inflate(mContext,R.layout.share_view_splash,null);//用于生成分享图片的布局
final ImageView iv_shot_share = shareView.findViewById(R.id.iv_shot_share);
shareView.setVisibility(View.INVISIBLE);//设置为不可见,但是占用空间
contentView.addView(shareView);
contentView.requestLayout();
iv_shot_share.post(new Runnable() {//使用post方法,保证view绘制完毕
@Override
public void run() {
Bitmap shareImg = Utils.captureView(shareView);//生成图片
shareView.setVisibility(View.GoNE);
contentView.removeView(shareView);//移除
}
});
}
});
3,关于截屏预览裁剪。
Android ImageVIew中现有的适配模式,centerCrop 等,无法满足,宽度充满,从顶部往下,超出则截掉的需求。所以,在ImageView 设置预览图时,需要对生成窗口视图bitmap进行二次处理。思路,使用Matrix将窗口视图缩放到与要展示的容器宽度比例。然后重新生成图片,从顶部开始,截出新图片。
public static Bitmap reClip(Bitmap bitmapOri,int widthTarget,int heightTarget){//xxxTarget 为ImageView 容器宽高
int width = bitmapOri.getWidth();
int height = bitmapOri.getHeight();
Bitmap bitmap = null;
float scaleWidth = (float) (widthTarget/1.0/width);
//缩放
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth,scaleWidth);
Bitmap bitmapScale = Bitmap.createBitmap(bitmapOri,0,0,width,height,matrix,false);//按照缩放比例生成新图
//在此要做判断,新截图片不能大于原始图片高度。否则异常终止,尤其注意普通屏幕,一般没问题。全面屏,不做此判断,会出现崩 溃,具体和要展示的容器宽高有关
if(bitmapScale.getHeight()> heightTarget){
bitmap = Bitmap.createBitmap(bitmapScale,0,0,bitmapScale.getWidth(),heightTarget);
}else{
bitmap = Bitmap.createBitmap(bitmapScale,0,0,bitmapScale.getWidth(),bitmapScale.getHeight());
}
return bitmap;
}
使用bitmap 注意及时回收。
4,关于分享图片问题,生成的本地图片保存到公共空间,
Environment.getExternalStorageDirectory()//比如这里
开发中,保存到应用包名下(context.getCacheDir),微信可以,但是QQ会出现无反应问题,报错信息也不明显。原因是读取权限问题,之后android10 还会进一步限制,所以,涉及到第三方app传递文件时,注意存储位置。
--结束END--
本文标题: Android截屏一键分享开发与实现方式的反思和总结
本文链接: https://lsjlt.com/news/29180.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-01-21
2023-10-28
2023-10-28
2023-10-27
2023-10-27
2023-10-27
2023-10-27
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0