Add a floating desktop window for android

Source: Internet
Author: User

New android 360 mobile assistants are all envious of the display of only a small floating window on the desktop in android 360?
In fact, there are two steps to implement this function:
1. Determine whether the current display is a desktop. I have already introduced this content in my previous post. If you haven't read it, please take a quick and steady look.
2. Use windowManager to add a View to the top layer
This knowledge point is the main content of this article. In this article, we will also talk about the following knowledge points:
A. If the height of the status bar is obtained
B. Drag the floating window
C. Click events in the floating window
Before getting started, let's take a look:

Next let's take a look at the code of FloatView: Copy codeThe Code is as follows: public class FloatView extends ImageView {
Private float mTouchX;
Private float mTouchY;
Private float x;
Private float y;
Private float mStartX;
Private float mStartY;
Private OnClickListener mClickListener;
Private WindowManager windowManager = (WindowManager) getContext ()
. GetApplicationContext (). getSystemService (Context. WINDOW_SERVICE );
// The windowManagerParams variable is the obtained global variable used to save the properties of the floating window.
Private WindowManager. LayoutParams windowManagerParams = (FloatApplication) getContext ()
. GetApplicationContext (). getWindowParams ();
Public FloatView (Context context ){
Super (context );
}
@ Override
Public boolean onTouchEvent (MotionEvent event ){
// Obtain the height of the status bar
Rect frame = new Rect ();
GetWindowVisibleDisplayFrame (frame );
Int statusBarHeight = frame. top;
System. out. println ("statusBarHeight:" + statusBarHeight );
// Obtain the coordinates of the relative screen, that is, starting from the upper-left corner of the screen
X = event. getRawX ();
Y = event. getRawY ()-statusBarHeight; // statusBarHeight indicates the height of the system status bar.
Log. I ("tag", "currX" + x + "=== currY" + y );
Switch (event. getAction ()){
Case MotionEvent. ACTION_DOWN: // capture the finger touch and press the action
// Obtain the coordinates of the relative View, that is, the upper-left corner of the View is the origin.
MTouchX = event. getX ();
MTouchY = event. getY ();
MStartX = x;
MStartY = y;
Log. I ("tag", "startX" + mTouchX + "=== startY"
+ MTouchY );
Break;
Case MotionEvent. ACTION_MOVE: // capture the finger movement
UpdateViewPosition ();
Break;
Case MotionEvent. ACTION_UP: // capture the finger touch and exit action
UpdateViewPosition ();
MTouchX = mTouchY = 0;
If (x-mStartX) <5 & (y-mStartY) <5 ){
If (mClickListener! = Null ){
MClickListener. onClick (this );
}
}
Break;
}
Return true;
}
@ Override
Public void setOnClickListener (OnClickListener l ){
This. mClickListener = l;
}
Private void updateViewPosition (){
// Update the floating window position Parameter
WindowManagerParams. x = (int) (x-mTouchX );
WindowManagerParams. y = (int) (y-mTouchY );
WindowManager. updateViewLayout (this, windowManagerParams); // refresh the display
}
}

Code explanation:
Int statusBarHeight = frame. top;
Why is the height of the status bar subtracted from event. getRawY () to obtain the height of the status bar?
Because our floating window cannot be displayed in the status bar, and then getRawY is the distance to obtain the screen origin. When the screen is in full screen mode, the height of the obtained status bar changes to 0.
(X-mStartX) <5 & (y-mStartY) <5
If the movement distance is less than 5 During the touch process, it is regarded as a click, triggering the click callback.
In addition, we need to customize an application:Copy codeThe Code is as follows: public class FloatApplication extends Application {
Private WindowManager. LayoutParams windowParams = new WindowManager. LayoutParams ();
Public WindowManager. LayoutParams getWindowParams (){
Return windowParams;
}
}

Code explanation:
The purpose of the custom application is to save the windowParams value, because when we drag the floating window, if we re-create a layoutParams each time
Will be found in the exception.
WindowParams values do not have to be saved in the custom application, as long as they are global.
Finally, let's take a look at the implementation in Activity.Copy codeThe Code is as follows: public class MainActivity extends Activity implements OnClickListener {
Private WindowManager windowManager = null;
Private WindowManager. LayoutParams windowManagerParams = null;
Private FloatView floatView = null;
@ Override
Public void onCreate (Bundle savedInstanceState ){
Super. onCreate (savedInstanceState );
RequestWindowFeature (Window. FEATURE_NO_TITLE); // cancel the title bar
GetWindow (). setFlags (WindowManager. LayoutParams. FLAG_FULLSCREEN,
WindowManager. LayoutParams. FLAG_FULLSCREEN); // full screen
SetContentView (R. layout. activity_main );
CreateView ();
}
@ Override
Public boolean onCreateOptionsMenu (Menu menu ){
GetMenuInflater (). inflate (R. menu. activity_main, menu );
Return true;
}
Public void onDestroy (){
Super. onDestroy ();
// Destroy the floating window when the program exits (Activity destruction)
WindowManager. removeView (floatView );
}
Private void createView (){
FloatView = new FloatView (getApplicationContext ());
FloatView. setOnClickListener (this );
FloatView. setImageResource (R. drawable. ic_launcher); // here, the self-built icon is used for demonstration.
// Obtain WindowManager
WindowManager = (WindowManager) getApplicationContext (). getSystemService (Context. WINDOW_SERVICE );
// Set parameters related to LayoutParams
WindowManagerParams = (FloatApplication) getApplication (). getWindowParams ();
WindowManagerParams. type = LayoutParams. TYPE_PHONE; // you can specify the window type.
WindowManagerParams. format = PixelFormat. RGBA_8888; // set the image format. The effect is transparent to the background.
// Set Window flag
WindowManagerParams. flags = LayoutParams. FLAG_NOT_TOUCH_MODAL
| LayoutParams. FLAG_NOT_FOCUSABLE;
/*
* Note that the flag value can be:
* LayoutParams. FLAG_NOT_TOUCH_MODAL does not affect subsequent events.
* LayoutParams. FLAG_NOT_FOCUSABLE cannot be focused
* LayoutParams. FLAG_NOT_TOUCHABLE cannot be touched.
*/
// Adjust the floating window to the upper left corner to adjust the coordinates
WindowManagerParams. gravity = Gravity. LEFT | Gravity. TOP;
// Set the starting value of x and y in the upper left corner of the screen
WindowManagerParams. x = 0;
WindowManagerParams. y = 0;
// Set the long and wide data of the floating window
WindowManagerParams. width = LayoutParams. WRAP_CONTENT;
WindowManagerParams. height = LayoutParams. WRAP_CONTENT;
// Display the myFloatView Image
WindowManager. addView (floatView, windowManagerParams );
}
Public void onClick (View v ){
Toast. makeText (this, "Clicked", Toast. LENGTH_SHORT). show ();
}
}

Code explanation:
In activity, we mainly add a floating window and set its position. In addition, pay attention to the flags application:
LayoutParams. FLAG_NOT_TOUCH_MODAL does not affect subsequent events.
LayoutParams. FLAG_NOT_FOCUSABLE cannot be focused
LayoutParams. FLAG_NOT_TOUCHABLE cannot be touched
Finally, the floating window is removed from onDestroy. Therefore, during the test, remember to press the Home Key to switch to the desktop.
Remember to declare the android. permission. SYSTEM_ALERT_WINDOW permission in androidManifest. xml.
And remember to declare our custom application.
The AndroidManifest. xml Code is as follows::Copy codeThe Code is as follows: <manifest xmlns: android = "http://schemas.android.com/apk/res/android"
Package = "com. krisscsi. floating"
Android: versionCode = "1"
Android: versionName = "1.0" type = "codeph" text = "/codeph">
<Uses-sdk
Android: minSdkVersion = "8"
Android: targetSdkVersion = "15"/>
<Uses-permission android: name = "android. permission. SYSTEM_ALERT_WINDOW"/>
<Application
Android: icon = "@ drawable/ic_launcher"
Android: label = "@ string/app_name"
Android: theme = "@ style/AppTheme" android: name = "FloatApplication">
<Activity
Android: name = ". MainActivity"
Android: label = "@ string/title_activity_main">
<Intent-filter>
<Action android: name = "android. intent. action. MAIN"/>
<Category android: name = "android. intent. category. LAUNCHER"/>
</Intent-filter>
</Activity>
</Application>
</Manifest>

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.