zoukankan      html  css  js  c++  java
  • Android桌面悬浮窗仿QQ手机管家加速效果

    主要还是用到了WindowManager对桌面悬浮进行管理.
    需要一个火箭的悬浮窗 一个发射台悬浮窗  ,判断火箭是否放到了发射台,如果放上了,则使用AsyTask 慢慢将火箭的图片往上移.结束后., 返回原位.
     1.打开activity_main.xml
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.windowmanagerdemo1.MainActivity" >
     
        <Button 
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:id="@+id/btn_start"
            android:text="start"
            />
     
    </RelativeLayout> 
    就一个Button.
    2.新建一个小悬浮窗的视图small_view.xml
    <?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="match_parent"
        >
       
        <LinearLayout 
            android:layout_width="60dp"
            android:layout_height="20dp"
            android:id="@+id/ll_smallView"
            android:background="#000000"
            android:orientation="vertical"
            >
            <TextView 
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:id="@+id/tv_percent"
                android:textColor="#ffffff"
                />
        </LinearLayout>
     
        <ImageView 
            android:id="@+id/iv_recketImg"
            android:layout_width="45dp"
            android:layout_height="90dp"
            android:src="@drawable/rocket"
            android:visibility="gone"
            />
    </FrameLayout>
    在帧布局中放入一个LinearLayout,这个主要用来显示当前手机内存, 同时放入一个ImageView ,这个用于手指按下时显示出小火箭,平常小悬浮窗显示时则小火箭隐藏,当按住了小悬浮窗,则显示小火箭,隐藏悬浮窗.
    3.新建 大悬浮窗视图 big_view.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="200dp"
        android:layout_height="100dp"
        android:id="@+id/ll_bigView"
        android:background="#000000"
        android:orientation="vertical" >
        
        <Button 
            android:id="@+id/btn_close"
            android:layout_width="100dp"
            android:layout_height="40dp"
            android:layout_gravity="center_horizontal"
            android:text="关闭悬浮窗"
            android:textColor="#ffffff"
            />
        <Button 
            android:id="@+id/btn_back"
            android:layout_width="100dp"
            android:layout_height="40dp"
            android:layout_gravity="center_horizontal"
            android:text="返回"
            android:textColor="#ffffff"
            />
     
    </LinearLayout> 
    大悬浮窗 是在点击了小悬浮窗后显示的,里面就放了两个按钮.
    4.新建发射台的视图  luncher.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
        
        <ImageView 
            android:id="@+id/iv_luncher"
            android:layout_width="200dp"
            android:layout_height="88dp"
            android:src="@drawable/launcher_bg_hold"
            />
     
    </LinearLayout>
    发射台视图只有一个ImageView.
    5,新建一个FloatBigView.java 大悬浮窗的实体类
    public class FloatBigView extends LinearLayout {
     
        //记录大悬浮窗的高度
        public static int ViewHeight;
        //记录大悬浮窗的宽度
        public static int ViewWidth;
        
        public FloatBigView(final Context context) {
            super(context);
            LayoutInflater.from(context).inflate(R.layout.big_view, this);
            View view=findViewById(R.id.ll_bigView);
            ViewHeight=view.getLayoutParams().height;
            ViewWidth=view.getLayoutParams().width;
            Button btn_close=(Button) findViewById(R.id.btn_close);
            Button btn_back=(Button) findViewById(R.id.btn_back);
            btn_close.setOnClickListener(new OnClickListener() {
                
                @Override
                public void onClick(View v) {
                    MyWindowManager.removeBigView(context);
                    MyWindowManager.removeSmallWindow(context);
                    Intent intent=new Intent(getContext(), WindowService.class);
                    context.stopService(intent);
                }
            });
            
            btn_back.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    MyWindowManager.removeBigView(context);
                    MyWindowManager.createSmallWindow(context);
                }
            });
            
        }
     
    }
    大悬浮窗的实体类 里面就是绑定刚才的大悬浮窗视图,并找到两个按钮,监听一个 关闭 和一个 返回的事件,  MyWindowManager将在下面创建
    6,小悬浮窗的实体类
    public class FloatSmallView extends LinearLayout {
        
        public static int ViewHeight;
        public static int ViewWidth;
        //系统状态栏的高度
        private static int statusHeight;
        
        private WindowManager mWindowManager;
        
        //小悬浮窗布局
        private LinearLayout smallViewLayout;
        
        //小火箭
        private ImageView rocketImg;
        
        //小悬浮窗参数
        private WindowManager.LayoutParams mLayoutParams;
        
        //记录手指在屏幕按下时的横坐标
        private float xDown;
        //记录手指在屏幕按下时的纵坐标
        private float yDown;
        
        //记录手指在屏幕移动时的横坐标
        private float xMove;
        //记录手指在屏幕移动时的纵坐标
        private float yMove;
        
        //记录手指按下时在小悬浮窗的横坐标
        private float xInView;
        //记录手指按下时在小悬浮窗的纵坐标
        private float yInView;
        
        //记录小火箭的高度
        private int rocketHeight;
        //记录小火箭的宽度
        private int rocketWidth;
        
        //记录当前手指是否在悬浮窗按下
        private boolean isPressed;
        
        public FloatSmallView(Context context) {
            super(context);
            mWindowManager=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            LayoutInflater.from(context).inflate(R.layout.small_view,this);
            smallViewLayout=(LinearLayout) findViewById(R.id.ll_smallView);
            ViewHeight=smallViewLayout.getLayoutParams().height;
            ViewWidth=smallViewLayout.getLayoutParams().width;
            rocketImg=(ImageView) findViewById(R.id.iv_recketImg);
            rocketHeight=rocketImg.getLayoutParams().height;
            rocketWidth=rocketImg.getLayoutParams().width;
            
            TextView tv_percent=(TextView) findViewById(R.id.tv_percent);
            tv_percent.setText(MyWindowManager.getUsedPercentValue(context));
        }
        
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isPressed = true;
                // 手指按下时记录必要数据,纵坐标的值都需要减去状态栏高度
                xInView = event.getX();
                yInView = event.getY();
                xDown = event.getRawX();
                yDown= event.getRawY() - getStatusBarHeight();
                xMove = event.getRawX();
                yMove = event.getRawY() - getStatusBarHeight();
                break;
            case MotionEvent.ACTION_MOVE:
                xMove=event.getRawX();
                yMove=event.getRawY()-getStatusBarHeight();
                updateViewStatus();
                updateViewPosition();
                
                break;
            case MotionEvent.ACTION_UP:
                isPressed=false;
                if(MyWindowManager.isReadyToLuncher()){
                    luncherRocket();
                }
                else{
                    updateViewStatus();
                    if(xDown==xMove&&yDown==yMove){
                        Log.e("info","进入1");
                        openBigWindow();
                    }
                }
                break;
            }
            
            return true;
        }
        
        //打开大悬浮窗口,关闭小悬浮窗
        private void openBigWindow(){
            Log.e("info","进入2");
            MyWindowManager.createBigView(getContext());
            MyWindowManager.removeSmallWindow(getContext());
        }
        
        //开始发射小火箭
        private void luncherRocket(){
            MyWindowManager.removeRocketLuncher(getContext());
            new LuncherTask().execute();
        }
        
        //传入小悬浮窗的参数, 用于更新位置
        public void setParams(WindowManager.LayoutParams mParams){
            this.mLayoutParams=mParams;
        }
        
        
        //更新小悬浮窗的位置
        private void updateViewPosition(){
            mLayoutParams.x=(int) (xMove-xInView);
            mLayoutParams.y=(int) (yMove-yInView);
            mWindowManager.updateViewLayout(this, mLayoutParams);
            //检查小火箭是否到了发射台
            MyWindowManager.updateLuncher();
        }
        
        //更新悬浮窗的显示样式  ,如果是按下状态 则显示为小火箭 否则为普通悬浮窗
        private void updateViewStatus(){
            if(isPressed&&rocketImg.getVisibility()!=View.VISIBLE){
                mLayoutParams.width=rocketWidth;
                mLayoutParams.height=rocketHeight;
                mWindowManager.updateViewLayout(this, mLayoutParams);
                smallViewLayout.setVisibility(View.GONE);
                rocketImg.setVisibility(View.VISIBLE);
                MyWindowManager.createLuncher(getContext());
            }
            else if(!isPressed){
                mLayoutParams.width=ViewWidth;
                mLayoutParams.height=ViewHeight;
                mWindowManager.updateViewLayout(this, mLayoutParams);
                smallViewLayout.setVisibility(View.VISIBLE);
                rocketImg.setVisibility(View.GONE);
                MyWindowManager.removeRocketLuncher(getContext());
            }
            
        }
        
        //开始执行发射小火箭的任务
        class LuncherTask extends AsyncTask<Void,Void, Void>{
            @Override
            protected Void doInBackground(Void... arg0) {
                while(mLayoutParams.y>0){
                    mLayoutParams.y=mLayoutParams.y-20;
                    publishProgress();
                    try {
                        Thread.sleep(30);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                
                return null;
            }
            @Override
            protected void onProgressUpdate(Void... values) {
                mWindowManager.updateViewLayout(FloatSmallView.this, mLayoutParams);
            }
            
            @Override
            protected void onPostExecute(Void result) {
                //小火箭升空后 回归悬浮窗状态
                updateViewStatus();
                mLayoutParams.x=(int) (xDown-xInView);
                mLayoutParams.y=(int) (yDown-yInView);
                mWindowManager.updateViewLayout(FloatSmallView.this, mLayoutParams);
            }
        }
        
        
        //获取状态栏的高度
        private int getStatusBarHeight() {
            if (statusHeight == 0) {
                try {
                    Class<?> c = Class.forName("com.android.internal.R$dimen");
                    Object o = c.newInstance();
                    Field field = c.getField("status_bar_height");
                    int x = (Integer) field.get(o);
                    statusHeight = getResources().getDimensionPixelSize(x);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return statusHeight;
        }
    }
    小悬浮窗中方法较多,注释较多
    7.创建发射台实体类RocketLuncher.java
    //火箭发射台
    public class RocketLuncher extends LinearLayout {
        
        public static int width;
        public static int height;
        
        private ImageView luncherImg;
     
        public RocketLuncher(Context context) {
            super(context);
            LayoutInflater.from(context).inflate(R.layout.luncher, this);
            luncherImg=(ImageView) findViewById(R.id.iv_luncher);
            width=luncherImg.getLayoutParams().width;
            height=luncherImg.getLayoutParams().height;
        }
        
        //更新火箭发射台的显示状态
        public void updateLuncherState(boolean isReadyToLuncher){
            if(isReadyToLuncher){
                luncherImg.setImageResource(R.drawable.launcher_bg_fire);
            }
            else{
                luncherImg.setImageResource(R.drawable.launcher_bg_hold);
            }
        }
     
    } 
     

    8,新建一个MyWindowManager.java用来管理这几个悬浮窗

    public class MyWindowManager {
     
        //小悬浮窗的实例
        private static FloatSmallView mSmallView;
        //大悬浮窗的实例
        private static FloatBigView mBigView;
        
        //火箭发射台的实例
        private static RocketLuncher rocketLuncher;
        
        //小悬浮窗的参数
        private static LayoutParams mSmallViewParams;
        //大悬浮窗的参数
        private static LayoutParams mBigViewParams;
        //火箭发射台的参数
        private static LayoutParams rocketLuncherParams;
        
        //用于在屏幕上添加或移除窗口
        private static WindowManager mWindowManager;
        
        //获取手机可用内存
        private static ActivityManager mActivityManager;
        
        //创建小悬浮窗
        public static void createSmallWindow(Context context){
            WindowManager windowManager=getWindowManager(context);
            int screenWidth=windowManager.getDefaultDisplay().getWidth();
            int screenHeight=windowManager.getDefaultDisplay().getHeight();
            if(mSmallView==null){
                mSmallView=new FloatSmallView(context);
                if(mSmallViewParams==null){
                    mSmallViewParams=new LayoutParams();
                    mSmallViewParams.type=LayoutParams.TYPE_SYSTEM_ALERT;
                    mSmallViewParams.format=PixelFormat.RGBA_8888;
                    mSmallViewParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL
                            | LayoutParams.FLAG_NOT_FOCUSABLE;
                    mSmallViewParams.gravity=Gravity.LEFT|Gravity.TOP;
                    mSmallViewParams.width=FloatSmallView.ViewWidth;
                    mSmallViewParams.height=FloatSmallView.ViewHeight;
                    mSmallViewParams.x=screenWidth;
                    mSmallViewParams.y=screenHeight/2;
                }
                mSmallView.setParams(mSmallViewParams);
                windowManager.addView(mSmallView, mSmallViewParams);
            }
        }
        //将小悬浮窗从屏幕上移除
        public static void removeSmallWindow(Context context){
            if(mSmallView!=null){
                WindowManager windowManager=getWindowManager(context);
                windowManager.removeView(mSmallView);
                mSmallView=null;
            }
        }
        
        //创建大悬浮窗
        public static void createBigView(Context context){
            WindowManager windowManager=getWindowManager(context);
            int screenWidth=windowManager.getDefaultDisplay().getWidth();
            int screenHeight=windowManager.getDefaultDisplay().getHeight();
            if(mBigView==null){
                mBigView=new FloatBigView(context);
                if(mBigViewParams==null){
                    mBigViewParams=new LayoutParams();
                    mBigViewParams.x=screenWidth/2-FloatBigView.ViewWidth/2;
                    mBigViewParams.y=screenHeight/2-FloatBigView.ViewHeight/2;
                    mBigViewParams.type=LayoutParams.TYPE_PHONE;
                    mBigViewParams.format= PixelFormat.RGBA_8888;
                    mBigViewParams.gravity=Gravity.LEFT|Gravity.TOP;
                    mBigViewParams.width=FloatBigView.ViewWidth;
                    mBigViewParams.height=FloatBigView.ViewHeight;
                }
                windowManager.addView(mBigView, mBigViewParams);
            }
        }
        //将大悬浮窗移除
        public static void removeBigView(Context context){
            if(mBigView!=null){
                WindowManager windowManager=getWindowManager(context);
                windowManager.removeView(mBigView);
                mBigView=null;
            }
        }
        
        //创建一个火箭发射台
        public static void createLuncher(Context context){
            WindowManager windowManager=getWindowManager(context);
            int screenWidht=windowManager.getDefaultDisplay().getWidth();
            int screenHeight=windowManager.getDefaultDisplay().getHeight();
            if(rocketLuncher==null){
                rocketLuncher=new RocketLuncher(context);
                if(rocketLuncherParams==null){
                    rocketLuncherParams=new LayoutParams();
                    rocketLuncherParams.x=screenWidht/2-RocketLuncher.width/2;
                    rocketLuncherParams.y=screenHeight-RocketLuncher.height;
                    rocketLuncherParams.type=LayoutParams.TYPE_PHONE;
                    rocketLuncherParams.format=PixelFormat.RGBA_8888;
                    rocketLuncherParams.gravity=Gravity.LEFT|Gravity.TOP;
                    rocketLuncherParams.width=RocketLuncher.width;
                    rocketLuncherParams.height=RocketLuncher.height;
                }
                windowManager.addView(rocketLuncher, rocketLuncherParams);
            }
        }
        
        //移除火箭发射台
        public static void removeRocketLuncher(Context context){
            if(rocketLuncher!=null){
                WindowManager wm=getWindowManager(context);
                wm.removeView(rocketLuncher);
                rocketLuncher=null;
            }
        }
        
        //更新火箭发射台的显示状态
        public static void updateLuncher(){
            if(rocketLuncher!=null){
                rocketLuncher.updateLuncherState(isReadyToLuncher());
            }
        }
        
        //更新小悬浮窗TextView的内存占比
        public static void updateUserPercent(Context context){
            if(mSmallView!=null){
                TextView percent=(TextView) mSmallView.findViewById(R.id.tv_percent);
                percent.setText(getUsedPercentValue(context));
            }
            
        }
        
        //是否有悬浮窗
        public static boolean isWindowShow(){
            return mSmallView!=null||mBigView!=null;
        }
        
        
        
        /**
         * 计算已使用内存的百分比,并返回。
         * 
         * @param context
         *            可传入应用程序上下文。
         * @return 已使用内存的百分比,以字符串形式返回。
         */
        public static String getUsedPercentValue(Context context) {
            String dir = "/proc/meminfo";
            try {
                FileReader fr = new FileReader(dir);
                BufferedReader br = new BufferedReader(fr, 2048);
                String memoryLine = br.readLine();
                String subMemoryLine = memoryLine.substring(memoryLine
                        .indexOf("MemTotal:"));
                br.close();
                long totalMemorySize = Integer.parseInt(subMemoryLine.replaceAll(
                        "\D+", ""));
                long availableSize = getAvailableMemory(context) / 1024;
                int percent = (int) ((totalMemorySize - availableSize)
                        / (float) totalMemorySize * 100);
                return percent + "%";
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "悬浮窗";
        }
     
        /**
         * 获取当前可用内存,返回数据以字节为单位。
         * 
         * @param context
         *            可传入应用程序上下文。
         * @return 当前可用内存。
         */
        private static long getAvailableMemory(Context context) {
            ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
            getActivityManager(context).getMemoryInfo(mi);
            return mi.availMem;
        }
        
        
        //判断小火箭是否准备好发射
        public static boolean isReadyToLuncher(){
            if ((mSmallViewParams.x > rocketLuncherParams.x && mSmallViewParams.x
                    + mSmallViewParams.width < rocketLuncherParams.x
                    + rocketLuncherParams.width)
                    && (mSmallViewParams.y + mSmallViewParams.height > rocketLuncherParams.y)) {
                return true;
            }
            return false;
        }
        
        //得到WindowManager的单例
        private static WindowManager getWindowManager(Context context){
            if(mWindowManager==null){
                mWindowManager=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            }
            return mWindowManager;
        }
        //得到ActivityManager的单例
        private static ActivityManager getActivityManager(Context context){
            if(mActivityManager==null){
                mActivityManager=(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            }
            return mActivityManager;
        }
        
    }
     

    9.悬浮窗的服务WindowService.java,用来时刻检查当前视图是否该显示悬浮窗还是隐藏.

    public class WindowService extends Service {
     
        //在线程中创建或移除悬浮窗
        private Handler handler=new Handler();
        
        //定时器 检查当前是应该创建还是移除悬浮窗
        private Timer mTimer;
        
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            if(mTimer==null){
                mTimer=new Timer();
                mTimer.scheduleAtFixedRate(new RefreshTaks(), 0, 500);
            }
            return super.onStartCommand(intent, flags, startId);
        }
        
        @Override
        public void onDestroy() {
            super.onDestroy();
            mTimer.cancel();
            mTimer=null;
        }
        
        class RefreshTaks extends TimerTask{
            @Override
            public void run() {
                //如果当前是桌面且没有窗口显示,则创建小悬浮窗
                if(isHome()&&!MyWindowManager.isWindowShow()){
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            MyWindowManager.createSmallWindow(getApplicationContext());
                        }
                    });
                }
                //如果不是桌面,且有悬浮窗显示,则移除悬浮窗
                else if(!isHome()&&MyWindowManager.isWindowShow()){
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            MyWindowManager.removeBigView(getApplicationContext());
                            MyWindowManager.removeSmallWindow(getApplicationContext());
                        }
                    });
                }
                //当前是桌面 且有悬浮窗显示  则更新内存
                else if(isHome()&&MyWindowManager.isWindowShow()){
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            MyWindowManager.updateUserPercent(getApplicationContext());
                        }
                    });
                }
                
            }
            
        }
        
     
        /**
         * 判断当前界面是否是桌面
         */
        private boolean isHome() {
            ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
            List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);
            return getHomes().contains(rti.get(0).topActivity.getPackageName());
        }
     
        /**
         * 获得属于桌面的应用的应用包名称
         * 
         * @return 返回包含所有包名的字符串列表
         */
        private List<String> getHomes() {
            List<String> names = new ArrayList<String>();
            PackageManager packageManager = this.getPackageManager();
            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_HOME);
            List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent,
                    PackageManager.MATCH_DEFAULT_ONLY);
            for (ResolveInfo ri : resolveInfo) {
                names.add(ri.activityInfo.packageName);
            }
            return names;
        }
        
        @Override
        public IBinder onBind(Intent arg0) {
            return null;
        }
        
        
     
    }
     

    10.打开MainActivity.java

    public class MainActivity extends ActionBarActivity {
     
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button btn_start=(Button) findViewById(R.id.btn_start);
            btn_start.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent=new Intent(MainActivity.this, WindowService.class);
                    MainActivity.this.startService(intent);
                    MainActivity.this.finish();
                }
            });
            
        }
    }

    开启服务. 

  • 相关阅读:
    Junit单元测试
    点餐系统
    文件的横纵转换
    零碎知识--日积月累
    json校验
    程序员必须收藏的14个顶级开发社区!
    管理员权限
    Thinking In Java 读书笔记
    学生考试系统
    JeeSite开发笔记
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/9165705.html
Copyright © 2011-2022 走看看