开发文章

Android仿iphone快速导航悬浮球

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

仿iphone快速导航悬浮球.png

拖动小圆球

拖动小圆球.png

 

点击弹出pop窗口:

点击弹出pop窗口.png

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

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

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

 

工程目录结构:

工程目录结构.jpg

部分代码解析:

MyApplication.Java:

复制内容到剪贴板
  1. package com.tyd.floatball.util;      
  2. import android.app.Application;      
  3. import android.view.WindowManager;      
  4. public class MyApplication extends Application {      
  5.     private WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();      
  6.     public WindowManager.LayoutParams getMywmParams() {      
  7.         return wmParams;      
  8.     }         
  9. }      

MainActivity.java:

复制内容到剪贴板
  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:

复制内容到剪贴板
  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, 00);      
  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:

复制内容到剪贴板
  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:

复制内容到剪贴板
  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:

复制内容到剪贴板
  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

感谢 jack_me8 支持 磐实编程网 原文地址:
blog.csdn.net/xiangzhihong8/article/details/43758333

文章信息

发布时间:2016-11-20

作者:jack_me8

发布者:aquwcw

浏览次数: