After the 4.0 version of Android Press the Power key and volume key can intercept the current screen, there will be a transition animation effect, here extract the effect of this section extracted, can be used for the application sharing function.
The location of the function in the source code is com.android.systemui.screenshot, there are four classes below
The main work is in Globalscreenshot, including the post-animation effect, save to local and display to the notification bar. For simplicity, the following code retains only the transition animation part
Class Globalscreenshot {private static final String TAG = "Globalscreenshot"; private static final int screenshot_flash_to_peak_duration = 130; private static final int screenshot_drop_in_duration = 430; private static final int screenshot_drop_out_delay = 500; private static final int screenshot_drop_out_duration = 430; private static final int screenshot_drop_out_scale_duration = 370; private static final int screenshot_fast_drop_out_duration = 320; Private static final float Background_alpha = 0.5f; Private static final float Screenshot_scale = 1f; Private static final Float Screenshot_drop_in_min_scale = Screenshot_scale * 0.725f; Private static final Float Screenshot_drop_out_min_scale = Screenshot_scale * 0.45f; Private static final Float Screenshot_fast_drop_out_min_scale = Screenshot_scale * 0.6f; Private static final float screenshot_drop_out_min_scale_offset = 0f; Private Context Mcontext; Private WindowManager Mwindowmanager;Private Windowmanager.layoutparams Mwindowlayoutparams; Private Display Mdisplay; Private Displaymetrics mdisplaymetrics; Private Bitmap Mscreenbitmap; Private View mscreenshotlayout; Private ImageView Mbackgroundview; Private ImageView Mscreenshotview; Private ImageView Mscreenshotflash; Private Animatorset mscreenshotanimation; private float mbgpadding; private float Mbgpaddingscale; Private Mediaactionsound Mcamerasound; /** * @param context everything needs a context:(*/public globalscreenshot (context context) {RESOURC Es r = context.getresources (); Mcontext = context; Layoutinflater Layoutinflater = (layoutinflater) context.getsystemservice (Context.layout_inflater_service); Inflate the screenshot layout mscreenshotlayout = Layoutinflater.inflate (R.layout.global_screenshot, nul L); Mbackgroundview = (ImageView) Mscreenshotlayout.findviewbyid (r.id.global_screenshot_background); Mscreenshotview = (ImageView) Mscreenshotlayout.findviewbyid (r.id.global_screenshot); Mscreenshotflash = (ImageView) Mscreenshotlayout.findviewbyid (R.id.global_screenshot_flash); Mscreenshotlayout.setfocusable (TRUE); Mscreenshotlayout.setontouchlistener (New View.ontouchlistener () {@Override public boolean OnTouch (V Iew V, motionevent event) {//Intercept and Ignore All touch events return true; } }); Setup The window that we is going to use Mwindowlayoutparams = new Windowmanager.layoutparams (V IewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0, WINDOWMANAGER.LAYOUTPARAMS.T Ype_system_alert, WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED, pixelformat.translucent); Mwindowlayoutparams.settitle ("Screenshotanimation"); Mwindowmanager = (WindowManager) context.getsystemservice (Context.window_service); Mdisplay = Mwindowmanager.getdefaultdisplay (); Mdisplaymetrics = new Displaymetrics (); Mdisplay.getrealmetrics (Mdisplaymetrics); Scale have to account for both sides of the BG mbgpadding = (float) r.getdimensionpixelsize (r.dimen.global_screen shot_bg_padding); Mbgpaddingscale = Mbgpadding/mdisplaymetrics.widthpixels; Setup the Camera shutter sound mcamerasound = new Mediaactionsound (); Mcamerasound.load (Mediaactionsound.shutter_click); }/** * Takes A screenshot of the current display and shows an animation. */void Takescreenshot (View view, Runnable Finisher, Boolean statusbarvisible, Boolean navbarvisible) {//Take The screenshot MscreenbItmap = Surfacecontrol.screenshot (view); if (Mscreenbitmap = = null) {notifyscreenshoterror (mcontext); Finisher.run (); Return }//Optimizations Mscreenbitmap.sethasalpha (FALSE); Mscreenbitmap.preparetodraw (); Start the Post-screenshot animation startanimation (finisher, Mdisplaymetrics.widthpixels, Mdisplaymetrics.height Pixels, statusbarvisible, navbarvisible); }/** * Starts the animation after taking the screenshot * * private void Startanimation (final Runnable Finis Her, int w, int h, Boolean statusbarvisible, Boolean navbarvisible) {//ADD the Vie W for the animation Mscreenshotview.setimagebitmap (MSCREENBITMAP); Mscreenshotlayout.requestfocus (); Setup the animation with the screenshot just taken if (mscreenshotanimation! = null) {Mscreenshotani Mation.end (); MscreenshotanimatioN.removealllisteners (); } mwindowmanager.addview (Mscreenshotlayout, mwindowlayoutparams); Valueanimator Screenshotdropinanim = Createscreenshotdropinanimation (); Valueanimator Screenshotfadeoutanim = createscreenshotdropoutanimation (W, H, statusbarvisible, NavBarVisibl e); Mscreenshotanimation = new Animatorset (); Mscreenshotanimation.playsequentially (Screenshotdropinanim, Screenshotfadeoutanim); Mscreenshotanimation.addlistener (New Animatorlisteneradapter () {@Override public void Onanimationen D (Animator animation) {//Save The screenshot Once we have a bit of time now Savescreenshot Inworkerthread (finisher); Mwindowmanager.removeview (mscreenshotlayout); Clear any references to the bitmap mscreenbitmap = null; Mscreenshotview.setimagebitmap (NULL); } }); Mscreenshotlayout.post (New Runnable () {@Override public void run () {//Play the shutter-notify that we ve Taken a screenshot mcamerasound.play (Mediaactionsound.shutter_click); Mscreenshotview.setlayertype (view.layer_type_hardware, NULL); Mscreenshotview.buildlayer (); Mscreenshotanimation.start (); } }); } private Valueanimator Createscreenshotdropinanimation () {final float flashpeakdurationpct = ((float) (SCREENS hot_flash_to_peak_duration)/screenshot_drop_in_duration); Final float flashdurationpct = 2f * FLASHPEAKDURATIONPCT; Final Interpolator flashalphainterpolator = new Interpolator () {@Override public float Getinterpola tion (float x) {//flash the Flash view in and out quickly if (x <= flashdurationpct) { return (float) Math.sin (Math.PI * (x/flashdurationpct)); } return 0; } }; Final Interpolator scaleinterpolator = new Interpolator () {@Override public float getinterpolation ( float x) {//We start scaling when the flash was at it ' s peak if (x < FLASHPEAKDURATIONPC T) {return 0; } return (x-flashdurationpct)/(1f-flashdurationpct); } }; Valueanimator anim = Valueanimator.offloat (0f, 1f); Anim.setduration (screenshot_drop_in_duration); Anim.addlistener (New Animatorlisteneradapter () {@Override public void Onanimationstart (Animator ani mation) {Mbackgroundview.setalpha (0f); Mbackgroundview.setvisibility (view.visible); Mscreenshotview.setalpha (0f); Mscreenshotview.settranslationx (0f); Mscreenshotview.settranslationy (0f); Mscreenshotview.setscalex (Screenshot_scale + Mbgpaddingscale); Mscreenshotview.setscaley (Screenshot_scale + mbgpaddingscale); Mscreenshotview.setvisibility (view.visible); Mscreenshotflash.setalpha (0f); Mscreenshotflash.setvisibility (view.visible); } @Override public void Onanimationend (Android.animation.Animator animation) {Mscree Nshotflash.setvisibility (View.gone); } }); Anim.addupdatelistener (New Animatorupdatelistener () {@Override public void onanimationupdate (Valuea Nimator animation) {Float t = (float) animation.getanimatedvalue (); float Scalet = (Screenshot_scale + mbgpaddingscale)-scaleinterpolator.getinterpolation (t) * (Screenshot_scale-screenshot_drop_in_min_scale); Mbackgroundview.setalpha (scaleinterpolator.getinterpolation (t) * background_alpha); Mscreenshotview.setalpha (t); Mscreenshotview.setscalex (Scalet); Mscreenshotview.setscaley (Scalet); Mscreenshotflash.setalpha (Flashalphainterpolator.getinterpolation (t)); } }); return anim; } private Valueanimator createscreenshotdropoutanimation (int w, int h, Boolean statusbarvisible, Boolean navbarvisible) {valueanimator anim = valueanimator.offloat (0f, 1f); Anim.setstartdelay (Screenshot_drop_out_delay); Anim.addlistener (New Animatorlisteneradapter () {@Override public void Onanimationend (Animator anima tion) {mbackgroundview.setvisibility (view.gone); Mscreenshotview.setvisibility (View.gone); Mscreenshotview.setlayertype (View.layer_type_none, NULL); } }); if (!statusbarvisible | |!navbarvisible) {//There is no status BAR/nav bar, so just fade the screenshot away in place Anim.setduration (screenshot_fast_drop_out_duration); Anim.addupdatelistener (New Animatorupdatelistener () {@Override public void Onanimati OnUpdate (Valueanimator animation) {Float t = (float) animation.getanimatedvalue (); float Scalet = (Screenshot_drop_in_min_scale + mbgpaddingscale)-T * (screenshot_drop_in_min_ Scale-screenshot_fast_drop_out_min_scale); Mbackgroundview.setalpha ((1f-t) * background_alpha); Mscreenshotview.setalpha (1F-T); Mscreenshotview.setscalex (Scalet); Mscreenshotview.setscaley (Scalet); } }); } else {//In the case where there are a status bar, animate to the origin of the bar (Top-left) fin Al float scaledurationpct = (float) screenshot_drop_out_scale_duration /screenshot_drop_out_duration; Final Interpolator scaleinterpolator = new Interpolator () {@Override public float GETINTERP Olation (float x) {if (x < scaledurationpct) {//decelerate, and scale the I Nput accordingly return (float) (1f-math.pow (1f-(x/scaledurationpct), 2f)); } return 1f; } }; Determine the bounds of how to scale float Halfscreenwidth = (w-2f * mbgpadding)/2f; float Halfscreenheight = (h-2f * mbgpadding)/2f; Final float offsetpct = Screenshot_drop_out_min_scale_offset; Final PointF Finalpos = new PointF (-halfscreenwidth + (Screenshot_drop_out_min_scale + offsetpct) * ha Lfscreenwidth,-halfscreenheight + (Screenshot_drop_out_min_scale + offsetpct) * halfscreenheight); Animate the screenshot to the status bar Anim.setduration (screenshot_drop_out_duration); Anim.addupdatelistener (New Animatorupdatelistener () {@Override public void Onanimationupdat E (valueanimator animation) {Float t = (float) animation.getanimatedvalue (); float Scalet = (Screenshot_drop_in_min_scale + mbgpaddingscale)-Scaleinterpolator.getinterpol ation (t) * (Screenshot_drop_in_min_scale-screenshot_drop_out_min_scale); Mbackgroundview.setalpha ((1f-t) * background_alpha); Mscreenshotview.setalpha (1f-scaleinterpolator.getinterpolation (t)); Mscreenshotview.setscalex (Scalet); Mscreenshotview.setscaley (Scalet); Mscreenshotview.settranslationx (T * finalpos.x); Mscreenshotview.settranslationy (T * finalpos.y); } }); } return anim; private void Notifyscreenshoterror (context context) {} private void Savescreenshotinworkerthread (Runnable Runn able) {}}
Take a look at the effect
Here is the following analysis of the relevant principles:
1. How to display
Back to the corresponding bitmap, with WindowManager directly on the screen to display the bitmap, that is, bitmap put into a imageview, WindowManager AddView can be displayed.
To have a shadow effect, an additional layout:global_screenshot.xml is defined here, as follows
<framelayout xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width= "Match_parent" android:layout_height= "Match_parent" > <imageview android:id= "@+id/global_screenshot_background" Android:la Yout_width= "Match_parent" android:layout_height= "match_parent" android:src= "@android: Color/black" and roid:visibility= "Gone"/> <imageview android:id= "@+id/global_screenshot" android:layout_width= "Wrap_conten T "android:layout_height=" wrap_content "android:layout_gravity=" center "android:background=" @drawable /screenshot_panel "android:visibility=" Gone "android:adjustviewbounds=" true "/> <imageview android: Id= "@+id/global_screenshot_flash" android:layout_width= "match_parent" android:layout_height= "Match_parent" Android:src= "@android: Color/white" android:visibility= "Gone"/></framelayout>
Above the layout of a total of three layers, the bottom of the background for the cover, the middle of the screenshot used to put, the top also has a layer of flash, mainly used to make a reflective effect.
Bitmap is placed in the ImageView of Global_screenshot. The corresponding code
Mscreenshotview.setimagebitmap (MSCREENBITMAP); Mscreenshotlayout.requestfocus (); Setup the animation with the screenshot just taken if (mscreenshotanimation! = null) { mscreenshotanimation.end (); Mscreenshotanimation.removealllisteners (); } Mwindowmanager.addview (Mscreenshotlayout, mwindowlayoutparams);
So you can see it on the screen, and then there's a transition animation effect, respectively
Valueanimator Screenshotdropinanim = Createscreenshotdropinanimation (); Valueanimator Screenshotfadeoutanim = createscreenshotdropoutanimation (W, H, statusbarvisible, navBarVisible);
These two properties animate the display-zoom-disappear process, specifically to transform the above three-layer view.
Called in activity
protected void OnCreate (Bundle savedinstancestate) { super.oncreate (savedinstancestate); Setcontentview (r.layout.activity_main); Final Globalscreenshot screenshot = new Globalscreenshot (this); Findviewbyid (R.ID.MAIN_BTN). Setonclicklistener (New View.onclicklistener () { @Override public void OnClick ( View v) { screenshot.takescreenshot (GetWindow (). Getdecorview (), new Runnable () { @Override public Void Run () { } }, True, true);}} );
The two Boolean arguments that follow indicate whether there is a status bar for displaying different fade animations, and if one is false, it will fade out without being offset upward to the status bar.
Screenshot feature extraction for Android system