android自定义控件 悬浮小火箭 (类似腾讯手机卫士)

效果图 : 





这种效果类似腾讯安全卫士的小火箭.. ps:图也是在那里盗的= ,=

小火箭 是常驻在后台的. 所以我们在服务里面写逻辑,

要实现这种效果. 我们要知道火箭 是悬浮在窗体上的. 这时我们需要WindowManager服务的addView 来实现


需注意 弹出窗体 需要系统权限.

 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />


下面贴代码  主Activity : 用于开启 服务 和关闭服务


public class RocketFly extends Activity {

    Intent intent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rocket_fly);
        // open rocket service

        intent = new Intent(this, RocketService.class);
        startService(intent);
//        finish();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopService(intent);
    }


}

下面是服务内 代码:

  @Override
    public void onCreate() {
        super.onCreate();
        mWM = (WindowManager) getSystemService(WINDOW_SERVICE);
        iv = new ImageView(getApplicationContext());
        iv.setBackgroundResource(R.drawable.rocket_list);
        AnimationDrawable ad = (AnimationDrawable) iv.getBackground();
        ad.start();
        params = mParams;
        // window manager 坐标系和普通的不同. 它是以自己view 的左上角为0进行计算
        // ,为了方便坐标计算. 我们把它对齐方式设置在左上角
        params.gravity = Gravity.LEFT + Gravity.TOP;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        // get the screen width and height
        DisplayMetrics displayMetrics = new DisplayMetrics();
        mWM.getDefaultDisplay().getMetrics(displayMetrics);
        // default display position
        // should be judge whether the first to enter
        screenWidth = displayMetrics.widthPixels ;
        screenHeight = displayMetrics.heightPixels ;

        params.x = screenWidth /2;
        params.y = screenHeight /2;

        params.format = PixelFormat.TRANSLUCENT ; // 窗体透明
        params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        params.setTitle("Toast");
        // TYPE_PRIORITY_PHONE 可以被触摸 需权限. Type_Toast 天生不可以被触摸
        params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;

        mWM.addView(iv, mParams);
        //  相应 rocket 滑动
        setTouchEvent(iv, params);

上面代码所需要注意的是: 我们需要设置这种 可以被触摸的类型

    params.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;

在源码中 params.type的类型是 , 这种类型 天生不可以被触摸.

 params.type = WindowManager.LayoutParams.Toast;
还需要注意 对齐方式. 与屏幕左上角对齐
   params.gravity = Gravity.LEFT + Gravity.TOP;

上面的代码写完. 一个小火箭就会显示在屏幕中间了



下面我们贴手指触摸移动的代码:

<strong> </strong> private void setTouchEvent(final ImageView iv, final WindowManager.LayoutParams params) {
        if (iv != null) {
            iv.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN:
                            startX = (int) event.getRawX();
                            startY = (int) event.getRawY();
                            break;
                        case MotionEvent.ACTION_MOVE:

                            int lastX = (int) event.getRawX();
                            int lastY = (int) event.getRawY();

                            int dx = lastX - startX;
                            int dy = lastY - startY;

                            params.x += dx;
                            params.y += dy;
<span style="white-space:pre">			</span>   //如果小火箭 在最左面 不让它在往左滑动了
                            if (params.x < 0) {
                                params.x = 0;
                            }
<span style="white-space:pre">			</span>  //同上
                            if (params.x > screenWidth  - iv.getWidth()) {
                                params.x = screenWidth  - iv.getWidth();
                            }
<span style="white-space:pre">			</span>  //....
                            if (params.y < 0) {
                                params.y = 0;
                            }
<span style="white-space:pre">			</span>  //....
                            if (params.y > screenHeight  - iv.getHeight()) {
                                params.y = screenHeight  - iv.getHeight();
                            }
                            // 更新 window manager
                            mWM.updateViewLayout(iv, params);
<span style="white-space:pre">			</span>    // 记录上次的点.
                            startX = lastX;
                            startY = lastY;
                            break;
                        case MotionEvent.ACTION_UP:
                            int upX = (int) event.getRawX();
                            int upY = (int) event.getRawY();
                            //满足条件  发射小火箭
                            if (upX > screenWidth /2 - iv.getWidth() / 2 && upX < screenWidth /2 + iv.getWidth() && upY > 600) {
                                Intent intent = new Intent(RocketService.this, Smoke.class);
                                // 在服务里开启activity 需要 设置标记
                                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                startActivity(intent);
                                new Thread() {

                                    @Override
                                    public void run() {
                                        for (int i = 0; i < 360; i++) { //这里的360是随便写的. 只要能到顶部就可以
                                            handler.sendEmptyMessage(0);
                                            try {
                                                Thread.sleep(2);
                                            } catch (InterruptedException e) {
                                                e.printStackTrace();
                                            }
                                        }
                                    }
                                }.start();
                            }
                            break;
                    }
                    return true;
                }

            });
        }
    }


烟雾效果的Activity代码:

public class Smoke extends Activity {

    private ImageView smoke1;
    private ImageView smoke2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_smoke);

        smoke1 = (ImageView) findViewById(R.id.smoke1); // 下方大烟雾
        smoke2 = (ImageView) findViewById(R.id.smoke2); // 小烟雾



        AlphaAnimation aa = new AlphaAnimation(0.0f, 1.0f);

        aa.setFillAfter(true);
        aa.setDuration(500);
        smoke1.setAnimation(aa);
        aa.setDuration(700);
        smoke2.startAnimation(aa);

        new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            finish(); // 过两秒 让烟雾消失.
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

}

布局文件就是几个ImageView 这里就不贴了.


还有必须要设置Activity 为透明的. 需要在AndroidManifest.xml 中添加  主题


 <activity
            android:name=".RocketFly"
            android:label="@string/title_activity_rocket_fly"
            android:theme="@android:style/Theme.Translucent.NoTitleBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>





  以上就是 实现小火箭喷烟雾的效果了..  有些细节没有处理.. 因为都比较好实现了嘛..

   写的不好望见谅 = ,=

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值