Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Whoa, Views can do that? WindowManager ideas an...

Whoa, Views can do that? WindowManager ideas and tricks!

https://youtu.be/ujfe_IF1O4A
Android WindowManager Ideas and Floating Views

Eric Cochran

August 28, 2015

Transcript

20 slides
  1. ERIC COCHRAN WHOA, VIEWS CAN DO THAT? WINDOWMANAGER IDEAS AND

    TRICKS! @ERIC_COCHRAN DROIDCON NYC AUGUST 28, 2015
  2. BEYOND SCREENS • VIEWS THAT ARE NOT ATTACHED TO AN

    ACTIVITY’S WINDOW • REAL, FULL-FLEDGED VIEWS
  3. PERMISSION <uses-permission android:name=“android.permission.SYSTEM_ALERT_WINDOW"/> Android M: hidden setting if (!Settings.canDrawOverlays(this)) {


    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
 Uri.parse("package:" + activity.getPackageName()));
 activity.startActivityForResult(intent, REQUEST_CODE_PERMISION_SYSTEM_ALERT_WINDOW);
 } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 if (requestCode == REQUEST_CODE_PERMISION_SYSTEM_ALERT_WINDOW) {
 if (Settings.canDrawOverlays(this)) {
 // yay!
 } else {
 // denied
 }
 }
 }
  4. ADDING THE VIEWS 
 WindowManager windowManager =
 (WindowManager) context.getSystemService(WINDOW_SERVICE);
 View

    floatingView = new View(context);
 // background to see View
 floatingView.setBackgroundColor(Color.RED);
 WindowManager.LayoutParams floatingLayoutParams =
 new WindowManager.LayoutParams(floatingViewWidth, floatingViewHeight,
 WindowManager.LayoutParams.TYPE_PHONE,
 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
 PixelFormat.TRANSPARENT);
 floatingLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
 windowManager.addView(floatingView, floatingLayoutParams);
  5. FLAG_NOT_FOCUSABLE Views will not receive focus. No EditTexts. WI FLAG_NOT_TOUCHABLE

    No touch listeners will work. FLAG_NOT_TOUCH_MODAL Will allow touch events to pass to outside Views FLAG_LAYOUT_NO_LIMITS Views are free to move offscreen. FLAG_LAYOUT_IN_SCREEN Keep Views bounded by the screen’s dimensions.
  6. TO A SERVICE @Override public int onStartCommand(Intent intent, int flags,

    int startId) {
 // addView code
 Notification notification = // valid notification
 startForeground(id, notification);
 return START_STICKY;
 }
  7. GET MOVING floatingView.setOnTouchListener(new View.OnTouchListener() {
 
 private int downX;
 private

    int downY;
 private float touchDownX;
 private float touchDownY;
 
 @Override public boolean onTouch(View v, MotionEvent event) {
 
 switch (event.getActionMasked()) {
 case MotionEvent.ACTION_DOWN:
 downX = floatingLayoutParams.x;
 downY = floatingLayoutParams.y;
 touchDownX = event.getRawX();
 touchDownY = event.getRawY();
 break;
 case MotionEvent.ACTION_MOVE:
 floatingLayoutParams.x = (int) (downX + event.getRawX() - touchDownX);
 floatingLayoutParams.y = (int) (downY + event.getRawY() - touchDownY);
 windowManager.updateViewLayout(floatingView, floatingLayoutParams);
 break;
 default:
 break;
 }
 return true;
 }
 });
  8. FIRST IDEA (NOT-SO-GREAT) • MAKE THE ROOT VIEW THAT IS

    ATTACHED TO THE WINDOW MANAGER ALWAYS LARGE ENOUGH TO ACCOMMODATE THE MAXIMUM SCALE THAT THE CORE VIEW WILL EVER ACHIEVE. • ADD A MARGIN TO THE CORE VIEW THAT FILLS THE SPACE. • WHEN THE CORE VIEW SCALES, THE MARGIN WILL BE THE ONLY PART CLIPPED.
  9. • DISADVANTAGE OF A LARGER ROOT VIEW THAT WILL NOW

    BLOCK MORE UI FROM THE USER. • WORSE, THIS ADDED MARGIN IS INVISIBLE AND COULD LEAD TO THE USER NOT UNDERSTANDING WHY OUR FLOATING VIEW IS INTERCEPTING TOUCH EVENTS OUTSIDE OF THE VISIBLE UI. FIRST IDEA (NOT-SO-GREAT)
  10. FIRST IDEA (NOT-SO-GREAT) • ROOT VIEW ACCOUNTS FOR THE CORE

    VIEW (THE RED DOT) SCALING TO TWICE AS LARGE • BUT, THE ROOT VIEW IS NOW OBSTRUCTING OTHER TOUCH EVENTS WITHOUT THE USER REALIZING IT.
  11. • DYNAMICALLY SCALE THE ROOT VIEW BETTER METHOD 
 floatingLayoutParams.width

    *= scaleFactorX;
 floatingLayoutParams.height *= scaleFactorY;
 windowManager.updateViewLayout(floatingView, floatingLayoutParams);
  12. BETTER IDEA • WE HAVE JUST SCALED THE WIDTH AND

    THE HEIGHT WHILE LEAVING THE X AND Y FIELDS IN PLACE. PROBABLY NOT IDEAL. • TO SCALE RADIALLY: 
 floatingLayoutParams.x -= (int) ((scaleFactorX - 1f) * floatingLayoutParams.width / 2f);
 floatingLayoutParams.y -= (int) ((scaleFactorY - 1f) * floatingLayoutParams.height / 2f);
  13. REMOVE WINDOW VIEWS • REMOVE VIEWS WHERE APPROPRIATE TO PREVENT

    LEAKS • (PROBABLY IN ONDESTROY() OF A SERVICE)
  14. • DEFINE YOUR BOUNDS • WITH INSETS, CHECK AGAINST BOUNDS

    BEFORE MOVING IN TOUCH LISTENER • VIEW.GETLOCATIONONSCREEN • ADD A VELOCITY TRACKER TIPS

More Decks by Eric Cochran

Other Decks in Programming