此次分享的功能比較簡單,是osc的截屏模塊,效果以下 java
這個功能用戶體驗仍是不錯的,在不少軟件都也都內置了這個功能 canvas
這個功能的原理是: 函數
1.在須要截屏的activity的window上覆蓋一個ScreenShotView this
2.用戶選定了截屏區域並雙擊後,ScreenShotView就會把當前activity的Decview畫到一個canvas上,並進行裁剪圖片和保存 url
具體實現過程: spa
時序圖以下: code
1.因爲這些操做都是在UIHelper中完成的,因此這裏從UIHelper開始,以前是在新聞詳情頁面點擊分享按鈕就調用UIHelper來生成contextmenu了 若是此時用戶選擇了截屏分享,那麼就會開始上圖的流程了首先是addScreenShot函數的執行 圖片
addScreenShot(context, new OnScreenShotListener() { @SuppressLint("NewApi") public void onComplete(Bitmap bm) { Intent intent = new Intent(context,ScreenShotShare.class); intent.putExtra("title", title); intent.putExtra("url", url); intent.putExtra("cut_image_tmp_path",ScreenShotView.TEMP_SHARE_FILE_NAME); try { ImageUtils.saveImageToSD(context,ScreenShotView.TEMP_SHARE_FILE_NAME,bm, 100); } catch (IOException e) { e.printStackTrace(); } context.startActivity(intent); } });很簡單,就是傳入了context 並實現了一個listener,這個listener用來處理ScreenShotview的回調,addScreenShot函數以下:咱們來一步步分析:
/** * 添加截屏功能 */ @SuppressLint("NewApi") public static void addScreenShot(Activity context, OnScreenShotListener mScreenShotListener) { BaseActivity cxt = null; if (context instanceof BaseActivity) { cxt = (BaseActivity) context; cxt.setAllowFullScreen(false); ScreenShotView screenShot = new ScreenShotView(cxt, mScreenShotListener); LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); context.getWindow().addContentView(screenShot, lp); } }
2.初始化ScreenShotView 這個構造函數主要是給當前的ScreenShotView添加了一個遮罩,也就是咱們點擊截屏後會顯示爲灰色而後讓用戶滑動選擇截屏區域 ip
@SuppressLint("NewApi") public ScreenShotView(BaseActivity context, OnScreenShotListener listener) { super(context); mListener = listener; mContext = context; mContext.setAllowDestroy(false, this); Point p = getDisplaySize(context.getWindowManager().getDefaultDisplay()); screenWidth = p.x; screeenHeight = p.y; mGrayPaint = new Paint(); mGrayPaint.setARGB(100, 0, 0, 0); topRect = new Rect(); rightRect = new Rect(); bottomRect = new Rect(); leftRect = new Rect(); topRect.set(0, 0, screenWidth, screeenHeight); setOnTouchListener(this); if(bmDoubleClickTip==null){ bmDoubleClickTip = BitmapFactory.decodeStream(getResources().openRawResource(R.drawable._pointer)); } UIHelper.ToastMessage(mContext, "請滑動手指肯定選區!"); }ScreenShotView的其餘處理也是圍繞怎麼跟隨用戶畫出選區展開的,這裏就不一一描述了
3.初始化完畢了ScreenShotView只會 會調用 開發
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); context.getWindow().addContentView(screenShot, lp);這樣就把ScreenShotView添加到了當前的activity的window中去了.
4.若是用戶操做完以後,雙擊了屏幕,通過一系列的判斷,就會執行回調了,代碼以下:
mListener.onComplete(getCutImage());
5-8 咱們看一下getCutImage函數,原來是先獲取當前decorview的bitmap,而後按照用戶操做界面計算出來的模板進行裁剪 就獲得截圖區域的bitmap了
/** * 截取內層邊框中的View. */ private Bitmap getCutImage() { View view = mContext.getWindow().getDecorView(); Bitmap bmp = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bmp); view.draw(canvas); return imageCrop(bmp); } /** * 裁剪圖片 */ private Bitmap imageCrop(Bitmap bitmap) { int x = left<0?0:left; int y = top + getStatusHeight(); int width = right- left; int height = bottom - top; if((width+x)>bitmap.getWidth()){ width = bitmap.getWidth()-x; } if((y+height)>bitmap.getHeight()){ height = bitmap.getHeight()-y; } return Bitmap.createBitmap(bitmap,x,y,width,height , null, false); }
9.拿到這個bitmap ,就能夠在UIHelper中進行分享和保存了
addScreenShot(context, new OnScreenShotListener() { @SuppressLint("NewApi") public void onComplete(Bitmap bm) { Intent intent = new Intent(context,ScreenShotShare.class); intent.putExtra("title", title); intent.putExtra("url", url); intent.putExtra("cut_image_tmp_path",ScreenShotView.TEMP_SHARE_FILE_NAME); try { ImageUtils.saveImageToSD(context,ScreenShotView.TEMP_SHARE_FILE_NAME,bm, 100); } catch (IOException e) { e.printStackTrace(); } context.startActivity(intent); } });
固然,其實在實際開發中,咱們只須要調用這個ScreenShotView就能夠了.