仿iphone快速导航悬浮球

简介: <p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; font-family:Arial; font-size:14px; line-height:26px"> 用过iphone的朋友都知道,iPhone有个圆球辅助工具,<span style="font-family:aria

用过iphone的朋友都知道,iPhone有个圆球辅助工具,它漂浮在你的手机屏幕(在任何APP之上),你可以将它移动到任何地方,它叫做AssistiveTouch,本篇模拟该软件实现一个小案例,主要是实现它的界面,首先来看看实现的效果吧:



拖动小圆球:



点击弹出pop窗口:



为了让辅助工具一直悬浮在窗口之上,这里使用的机制是通过在程序初始化是,启动一个service,在service的onCreate() 函数中使用LayoutInflater来加载一个view,而这个view就是辅助球的布局文件:floatball.xml,然后对它进行onclick事件的监听,setOnClickListener监听到辅助球点击事件之后,就创建一个PopupWindow,弹出如上的菜单界面,大体的实现就是这样。

其实,实现窗口悬浮于最前面的一个重要属性是:WindowManager.LayoutParams.TYPE_PHONE

我们只要将WindowManager.LayoutParams的type属性设置为 WindowManager.LayoutParams.TYPE_PHONE就可以实现悬浮最前面。


工程目录结构:



部分代码解析:

MyApplication.java:

[html]  view plain copy print ?
  1. package com.tyd.floatball.util;  
  2.   
  3. import android.app.Application;  
  4. import android.view.WindowManager;  
  5.   
  6. public class MyApplication extends Application {  
  7.   
  8.     private WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();  
  9.   
  10.     public WindowManager.LayoutParams getMywmParams() {  
  11.         return wmParams;  
  12.     }  
  13.       
  14. }  



MainActivity.java:

[html]  view plain copy print ?
  1. package com.tyd.floatball.ui;  
  2.   
  3. import com.tyd.floatball.R;  
  4. import com.tyd.floatball.R.layout;  
  5. import com.tyd.floatball.service.TopFloatService;  
  6. import android.app.Activity;  
  7. import android.content.Intent;  
  8. import android.os.Bundle;  
  9.   
  10. public class MainActivity extends Activity {  
  11.     @Override  
  12.     public void onCreate(Bundle savedInstanceState) {  
  13.         super.onCreate(savedInstanceState);  
  14.         setContentView(R.layout.main);  
  15.         Intent service = new Intent();  
  16.         service.setClass(this, TopFloatService.class);  
  17.         //启动服务  
  18.         startService(service);  
  19.     }  
  20. }  


TopFloatService.java:

[html]  view plain copy print ?
  1. package com.tyd.floatball.service;  
  2.   
  3. import android.app.Service;  
  4. import android.content.Intent;  
  5. import android.graphics.PixelFormat;  
  6. import android.graphics.Rect;  
  7. import android.graphics.drawable.BitmapDrawable;  
  8. import android.os.IBinder;  
  9. import android.util.DisplayMetrics;  
  10. import android.view.Gravity;  
  11. import android.view.KeyEvent;  
  12. import android.view.LayoutInflater;  
  13. import android.view.MotionEvent;  
  14. import android.view.View;  
  15. import android.view.View.OnClickListener;  
  16. import android.view.View.OnKeyListener;  
  17. import android.view.View.OnTouchListener;  
  18. import android.view.WindowManager;  
  19. import android.widget.Button;  
  20. import android.widget.LinearLayout;  
  21. import android.widget.PopupWindow;  
  22. import android.widget.RelativeLayout;  
  23. import android.widget.Toast;  
  24. import com.tyd.floatball.R;  
  25. import com.tyd.floatball.util.MyApplication;  
  26.   
  27. public class TopFloatService extends Service implements OnClickListener,OnKeyListener{  
  28.     WindowManager wm = null;  
  29.     WindowManager.LayoutParams ballWmParams = null;  
  30.     private View ballView;  
  31.     private View menuView;  
  32.     private float mTouchStartX;  
  33.     private float mTouchStartY;  
  34.     private float x;  
  35.     private float y;  
  36.     private RelativeLayout menuLayout;  
  37.     private Button floatImage;  
  38.     private PopupWindow pop;  
  39.     private RelativeLayout menuTop;  
  40.     private boolean ismoving = false;  
  41.       
  42.     @Override  
  43.     public void onCreate() {  
  44.         super.onCreate();  
  45.         //加载辅助球布局  
  46.         ballView = LayoutInflater.from(this).inflate(R.layout.floatball, null);  
  47.         floatImage = (Button)ballView.findViewById(R.id.float_image);  
  48.         setUpFloatMenuView();  
  49.         createView();  
  50.     }  
  51.       
  52.     /**  
  53.      * 窗口菜单初始化  
  54.      */  
  55.     private void setUpFloatMenuView(){  
  56.         menuView = LayoutInflater.from(this).inflate(R.layout.floatmenu, null);  
  57.         menuLayout = (RelativeLayout)menuView.findViewById(R.id.menu);  
  58.         menuTop = (RelativeLayout)menuView.findViewById(R.id.lay_main);  
  59.         menuLayout.setOnClickListener(this);  
  60.         menuLayout.setOnKeyListener(this);  
  61.         menuTop.setOnClickListener(this);  
  62.     }  
  63.   
  64.     /**  
  65.      * 通过MyApplication创建view,并初始化显示参数  
  66.      */  
  67.     private void createView() {  
  68.         wm = (WindowManager) getApplicationContext().getSystemService("window");  
  69.         ballWmParams =  ((MyApplication) getApplication()).getMywmParams();  
  70.         ballWmParams.type = WindowManager.LayoutParams.TYPE_PHONE;  
  71.         ballWmParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;  
  72.         ballWmParams.gravity = Gravity.LEFT | Gravity.TOP;  
  73.         ballWmParams.x = 0;  
  74.         ballWmParams.y = 0;  
  75.         ballWmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;  
  76.         ballWmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;  
  77.         ballWmParams.format = PixelFormat.RGBA_8888;  
  78.         //添加显示层  
  79.         wm.addView(ballView, ballWmParams);  
  80.         //注册触碰事件监听器  
  81.         floatImage.setOnTouchListener(new OnTouchListener() {  
  82.             public boolean onTouch(View v, MotionEvent event) {  
  83.                 x = event.getRawX();  
  84.                 y = event.getRawY();   
  85.                 switch (event.getAction()) {  
  86.                 case MotionEvent.ACTION_DOWN:  
  87.                     ismoving = false;  
  88.                     mTouchStartX = (int)event.getX();  
  89.                     mTouchStartY = (int)event.getY();  
  90.                     break;  
  91.                 case MotionEvent.ACTION_MOVE:  
  92.                     ismoving = true;  
  93.                     updateViewPosition();  
  94.                     break;  
  95.                 case MotionEvent.ACTION_UP:  
  96.                     mTouchStartX = mTouchStartY = 0;  
  97.                     break;  
  98.                 }  
  99.                 //如果拖动则返回false,否则返回true  
  100.                 if(ismoving == false){  
  101.                     return false;  
  102.                 }else{  
  103.                     return true;  
  104.                 }  
  105.             }  
  106.   
  107.         });  
  108.         //注册点击事件监听器  
  109.         floatImage.setOnClickListener(new View.OnClickListener() {  
  110.             @Override  
  111.             public void onClick(View v) {  
  112.                 DisplayMetrics dm = getResources().getDisplayMetrics();  
  113.                 pop = new PopupWindow(menuView, dm.widthPixels, dm.heightPixels);  
  114.                 pop.showAtLocation(ballView, Gravity.CENTER, 0, 0);  
  115.                 pop.update();  
  116.             }  
  117.         });  
  118.     }  
  119.       
  120.     /**  
  121.      * 更新view的显示位置  
  122.      */  
  123.     private void updateViewPosition() {  
  124.         ballWmParams.x = (int) (x - mTouchStartX);  
  125.         ballWmParams.y = (int) (y - mTouchStartY);  
  126.         wm.updateViewLayout(ballView, ballWmParams);  
  127.     }  
  128.   
  129.     @Override  
  130.     public IBinder onBind(Intent intent) {  
  131.         return null;  
  132.     }  
  133.   
  134.     @Override  
  135.     public void onClick(View v) {  
  136.         switch (v.getId()) {  
  137.         case R.id.lay_main:  
  138.             Toast.makeText(getApplicationContext(), "111", 1000).show();  
  139.             break;  
  140.   
  141.         default:  
  142.             if(pop!=null && pop.isShowing()){  
  143.                 pop.dismiss();  
  144.             }  
  145.             break;  
  146.         }  
  147.           
  148.     }  
  149.   
  150.     @Override  
  151.     public boolean onKey(View v, int keyCode, KeyEvent event) {  
  152.         Toast.makeText(getApplicationContext(), "keyCode:"+keyCode, 1000).show();  
  153.         switch (keyCode) {  
  154.         case KeyEvent.KEYCODE_HOME:  
  155.             pop.dismiss();  
  156.             break;  
  157.         default:  
  158.             break;  
  159.         }  
  160.         return true;  
  161.     }  
  162.       
  163. }  

辅助球的布局文件 floatball.xml:

[html]  view plain copy print ?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="wrap_content"  
  5.     android:orientation="vertical"  
  6.     android:layout_gravity="center_vertical">  
  7.       
  8.     <Button  
  9.         android:id="@+id/float_image"  
  10.         android:layout_width="50dp"  
  11.         android:layout_height="50dp"  
  12.         android:background="@drawable/selector_btn_assistive"   
  13.         />  
  14.   
  15. </FrameLayout>  

窗口菜单的布局文件floatmenu.xml:

[html]  view plain copy print ?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@+id/menu"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:background="@drawable/transparent" >  
  7.   
  8.     <LinearLayout  
  9.         android:layout_width="@dimen/size_dialog"  
  10.         android:layout_height="@dimen/size_dialog"  
  11.         android:layout_centerInParent="true"  
  12.         android:background="@drawable/shape_background_assistivetouch"  
  13.         android:orientation="vertical" >  
  14.   
  15.         <RelativeLayout  
  16.             android:id="@+id/lay_main"  
  17.             android:layout_width="fill_parent"  
  18.             android:layout_height="fill_parent"  
  19.             android:orientation="vertical"  
  20.             android:padding="4.0px"  
  21.             android:visibility="visible" >  
  22.   
  23.             <TextView  
  24.                 android:id="@+id/btn_apps"  
  25.                 style="@style/Icon"  
  26.                 android:layout_centerInParent="true"  
  27.                 android:drawableTop="@drawable/selector_ic_apps"  
  28.                 android:text="@string/apps" />  
  29.   
  30.             <TextView  
  31.                 android:id="@+id/btn_home_screen"  
  32.                 style="@style/Icon"  
  33.                 android:layout_alignParentBottom="true"  
  34.                 android:layout_centerHorizontal="true"  
  35.                 android:drawableTop="@drawable/selector_ic_home"  
  36.                 android:text="@string/home_screen" />  
  37.   
  38.             <TextView  
  39.                 android:id="@+id/btn_setting"  
  40.                 style="@style/Icon"  
  41.                 android:layout_alignParentRight="true"  
  42.                 android:layout_centerVertical="true"  
  43.                 android:drawableTop="@drawable/selector_ic_phone"  
  44.                 android:text="@string/setting" />  
  45.   
  46.             <TextView  
  47.                 android:id="@+id/btn_lock_screen"  
  48.                 style="@style/Icon"  
  49.                 android:layout_centerHorizontal="true"  
  50.                 android:drawableTop="@drawable/selector_ic_power_down"  
  51.                 android:text="@string/lock_screen" />  
  52.   
  53.             <TextView  
  54.                 android:id="@+id/btn_favor"  
  55.                 style="@style/Icon"  
  56.                 android:layout_alignParentLeft="true"  
  57.                 android:layout_centerVertical="true"  
  58.                 android:drawableTop="@drawable/selector_ic_star"  
  59.                 android:text="@string/favor" />  
  60.         </RelativeLayout>  
  61.     </LinearLayout>  
  62.   
  63. </RelativeLayout>  

AndroidManifest.xml:

[html]  view plain copy print ?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.tyd.floatball"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.     <uses-sdk android:minSdkVersion="14" />  
  7.   
  8.     <application  
  9.         android:icon="@drawable/ic_launcher"  
  10.         android:label="@string/app_name"   
  11.         android:name=".util.MyApplication">  
  12.         <activity  
  13.             android:label="@string/app_name"  
  14.             android:name=".ui.MainActivity" >  
  15.             <intent-filter >  
  16.                 <action android:name="android.intent.action.MAIN" />  
  17.   
  18.                 <category android:name="android.intent.category.LAUNCHER" />  
  19.             </intent-filter>  
  20.         </activity>  
  21.         <service   
  22.                 android:name=".service.TopFloatService"    
  23.                 android:enabled="true"  
  24.                 android:exported="true"  
  25.             />  
  26.     </application>  
  27.       
  28.     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />  
  29.     <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>  
  30. </manifest>  


该实例我已经将源码整理打包,进行了上传,下面是资源的下载地址:

http://download.csdn.net/detail/wulianghuan/5364129

目录
相关文章
|
7月前
|
前端开发
实现手机端的触屏滑动效果
实现手机端的触屏滑动效果
实现手机端的触屏滑动效果
|
9月前
Photoshop制作白色可爱音乐播放图标面板(一)
Photoshop制作白色可爱音乐播放图标面板
54 0
|
5月前
仿百度地图上拉下滑抽屉盒
仿百度地图上拉下滑抽屉盒
18 0
|
8月前
|
前端开发
【CSS动画05--闪亮的玻璃图标悬浮效果】
【CSS动画05--闪亮的玻璃图标悬浮效果】
|
8月前
|
C++ Python
|
8月前
|
存储 C++ Python
C++复刻:[流光按钮]+[悬浮波纹按钮]
[流光按钮]+[悬浮波纹按钮]
105 0
|
9月前
Photoshop制作白色可爱音乐播放图标面板(二)
Photoshop制作白色可爱音乐播放图标面板
41 0
|
9月前
|
iOS开发 开发者
iPhoneX-关于底部的那个一个横条的问题
作为一个iOS开发者,每一次苹果的推陈出新,都会为引用适配和开发过程带来新的挑战,最近刚入手了一个iPhone X。把玩的还是很舒适的,但是应用的适配总是有一定的过程的,这种阵痛还是要忍受的。但是有一个体验就不是很好了,在看视频的时候视频底部永远会有那么一个被苹果称之为“HomeIndicator”的横条。我是没有什么强迫症,但是也很烦。所以今天就打算研究一下怎么去掉这个讨人厌的横条。