仿iphone快速导航悬浮球

    xiaoxiao2025-12-02  10

    用过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 ? package com.tyd.floatball.util;      import android.app.Application;   import android.view.WindowManager;      public class MyApplication extends Application {          private WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();          public WindowManager.LayoutParams getMywmParams() {           return wmParams;       }          }  

    MainActivity.java:

    [html]  view plain copy print ? package com.tyd.floatball.ui;      import com.tyd.floatball.R;   import com.tyd.floatball.R.layout;   import com.tyd.floatball.service.TopFloatService;   import android.app.Activity;   import android.content.Intent;   import android.os.Bundle;      public class MainActivity extends Activity {       @Override       public void onCreate(Bundle savedInstanceState) {           super.onCreate(savedInstanceState);           setContentView(R.layout.main);           Intent service = new Intent();           service.setClass(this, TopFloatService.class);           //启动服务           startService(service);       }   }  

    TopFloatService.java:

    [html]  view plain copy print ? package com.tyd.floatball.service;      import android.app.Service;   import android.content.Intent;   import android.graphics.PixelFormat;   import android.graphics.Rect;   import android.graphics.drawable.BitmapDrawable;   import android.os.IBinder;   import android.util.DisplayMetrics;   import android.view.Gravity;   import android.view.KeyEvent;   import android.view.LayoutInflater;   import android.view.MotionEvent;   import android.view.View;   import android.view.View.OnClickListener;   import android.view.View.OnKeyListener;   import android.view.View.OnTouchListener;   import android.view.WindowManager;   import android.widget.Button;   import android.widget.LinearLayout;   import android.widget.PopupWindow;   import android.widget.RelativeLayout;   import android.widget.Toast;   import com.tyd.floatball.R;   import com.tyd.floatball.util.MyApplication;      public class TopFloatService extends Service implements OnClickListener,OnKeyListener{       WindowManager wm = null;       WindowManager.LayoutParams ballWmParams = null;       private View ballView;       private View menuView;       private float mTouchStartX;       private float mTouchStartY;       private float x;       private float y;       private RelativeLayout menuLayout;       private Button floatImage;       private PopupWindow pop;       private RelativeLayout menuTop;       private boolean ismoving = false;              @Override       public void onCreate() {           super.onCreate();           //加载辅助球布局           ballView = LayoutInflater.from(this).inflate(R.layout.floatball, null);           floatImage = (Button)ballView.findViewById(R.id.float_image);           setUpFloatMenuView();           createView();       }              /**        * 窗口菜单初始化        */       private void setUpFloatMenuView(){           menuView = LayoutInflater.from(this).inflate(R.layout.floatmenu, null);           menuLayout = (RelativeLayout)menuView.findViewById(R.id.menu);           menuTop = (RelativeLayout)menuView.findViewById(R.id.lay_main);           menuLayout.setOnClickListener(this);           menuLayout.setOnKeyListener(this);           menuTop.setOnClickListener(this);       }          /**        * 通过MyApplication创建view,并初始化显示参数        */       private void createView() {           wm = (WindowManager) getApplicationContext().getSystemService("window");           ballWmParams =  ((MyApplication) getApplication()).getMywmParams();           ballWmParams.type = WindowManager.LayoutParams.TYPE_PHONE;           ballWmParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;           ballWmParams.gravity = Gravity.LEFT | Gravity.TOP;           ballWmParams.x = 0;           ballWmParams.y = 0;           ballWmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;           ballWmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;           ballWmParams.format = PixelFormat.RGBA_8888;           //添加显示层           wm.addView(ballView, ballWmParams);           //注册触碰事件监听器           floatImage.setOnTouchListener(new OnTouchListener() {               public boolean onTouch(View v, MotionEvent event) {                   x = event.getRawX();                   y = event.getRawY();                    switch (event.getAction()) {                   case MotionEvent.ACTION_DOWN:                       ismoving = false;                       mTouchStartX = (int)event.getX();                       mTouchStartY = (int)event.getY();                       break;                   case MotionEvent.ACTION_MOVE:                       ismoving = true;                       updateViewPosition();                       break;                   case MotionEvent.ACTION_UP:                       mTouchStartX = mTouchStartY = 0;                       break;                   }                   //如果拖动则返回false,否则返回true                   if(ismoving == false){                       return false;                   }else{                       return true;                   }               }              });           //注册点击事件监听器           floatImage.setOnClickListener(new View.OnClickListener() {               @Override               public void onClick(View v) {                   DisplayMetrics dm = getResources().getDisplayMetrics();                   pop = new PopupWindow(menuView, dm.widthPixels, dm.heightPixels);                   pop.showAtLocation(ballView, Gravity.CENTER, 0, 0);                   pop.update();               }           });       }              /**        * 更新view的显示位置        */       private void updateViewPosition() {           ballWmParams.x = (int) (x - mTouchStartX);           ballWmParams.y = (int) (y - mTouchStartY);           wm.updateViewLayout(ballView, ballWmParams);       }          @Override       public IBinder onBind(Intent intent) {           return null;       }          @Override       public void onClick(View v) {           switch (v.getId()) {           case R.id.lay_main:               Toast.makeText(getApplicationContext(), "111", 1000).show();               break;              default:               if(pop!=null && pop.isShowing()){                   pop.dismiss();               }               break;           }                  }          @Override       public boolean onKey(View v, int keyCode, KeyEvent event) {           Toast.makeText(getApplicationContext(), "keyCode:"+keyCode, 1000).show();           switch (keyCode) {           case KeyEvent.KEYCODE_HOME:               pop.dismiss();               break;           default:               break;           }           return true;       }          }   辅助球的布局文件 floatball.xml:

    [html]  view plain copy print ? <?xml version="1.0" encoding="utf-8"?>   <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"       android:layout_width="match_parent"       android:layout_height="wrap_content"       android:orientation="vertical"       android:layout_gravity="center_vertical">              <Button           android:id="@+id/float_image"           android:layout_width="50dp"           android:layout_height="50dp"           android:background="@drawable/selector_btn_assistive"            />      </FrameLayout>   窗口菜单的布局文件floatmenu.xml:

    [html]  view plain copy print ? <?xml version="1.0" encoding="utf-8"?>   <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"       android:id="@+id/menu"       android:layout_width="fill_parent"       android:layout_height="fill_parent"       android:background="@drawable/transparent" >          <LinearLayout           android:layout_width="@dimen/size_dialog"           android:layout_height="@dimen/size_dialog"           android:layout_centerInParent="true"           android:background="@drawable/shape_background_assistivetouch"           android:orientation="vertical" >              <RelativeLayout               android:id="@+id/lay_main"               android:layout_width="fill_parent"               android:layout_height="fill_parent"               android:orientation="vertical"               android:padding="4.0px"               android:visibility="visible" >                  <TextView                   android:id="@+id/btn_apps"                   style="@style/Icon"                   android:layout_centerInParent="true"                   android:drawableTop="@drawable/selector_ic_apps"                   android:text="@string/apps" />                  <TextView                   android:id="@+id/btn_home_screen"                   style="@style/Icon"                   android:layout_alignParentBottom="true"                   android:layout_centerHorizontal="true"                   android:drawableTop="@drawable/selector_ic_home"                   android:text="@string/home_screen" />                  <TextView                   android:id="@+id/btn_setting"                   style="@style/Icon"                   android:layout_alignParentRight="true"                   android:layout_centerVertical="true"                   android:drawableTop="@drawable/selector_ic_phone"                   android:text="@string/setting" />                  <TextView                   android:id="@+id/btn_lock_screen"                   style="@style/Icon"                   android:layout_centerHorizontal="true"                   android:drawableTop="@drawable/selector_ic_power_down"                   android:text="@string/lock_screen" />                  <TextView                   android:id="@+id/btn_favor"                   style="@style/Icon"                   android:layout_alignParentLeft="true"                   android:layout_centerVertical="true"                   android:drawableTop="@drawable/selector_ic_star"                   android:text="@string/favor" />           </RelativeLayout>       </LinearLayout>      </RelativeLayout>   AndroidManifest.xml:

    [html]  view plain copy print ? <?xml version="1.0" encoding="utf-8"?>   <manifest xmlns:android="http://schemas.android.com/apk/res/android"       package="com.tyd.floatball"       android:versionCode="1"       android:versionName="1.0" >       <uses-sdk android:minSdkVersion="14" />          <application           android:icon="@drawable/ic_launcher"           android:label="@string/app_name"            android:name=".util.MyApplication">           <activity               android:label="@string/app_name"               android:name=".ui.MainActivity" >               <intent-filter >                   <action android:name="android.intent.action.MAIN" />                      <category android:name="android.intent.category.LAUNCHER" />               </intent-filter>           </activity>           <service                    android:name=".service.TopFloatService"                     android:enabled="true"                   android:exported="true"               />       </application>              <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />       <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>   </manifest>  

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

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

    相关资源:敏捷开发V1.0.pptx
    最新回复(0)