android小火箭案例

案例描述: 经常看到清理内存用到这个动画,本质上是一个自定义的toast,绑定在服务中。
原理: 飞机喷火效果是两个图片不停的切换形成了喷火效果。那个喷气的效果 是一个单独的activity,背景色设置为透明,渐变的动画效果,并且在1s后自动结束该activity。

素材地址

素材地址
https://github.com/MrITzhongzi/materialLibrary/tree/master/rocketManImage

效果展示

项目结构

android小火箭案例_第1张图片

代码示例:
  • MainActivity
package com.example.rocket;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(!Settings.canDrawOverlays(this)) {
            startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 101);
        }
    }

    public void startRocket(View view) {
        startService(new Intent(getApplicationContext(), RocketService.class));
        finish();
    }

    public void endRocket(View view) {
        stopService(new Intent(getApplicationContext(), RocketService.class));
        finish();
    }
}
  • RocketService
package com.example.rocket;

import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.view.Display;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;

public class RocketService extends Service {

    private WindowManager mWindowManager;
    private int mScreenHeight;
    private int mScreenWidth;
    private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
    private View mMRocketView;
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            mParams.y = (Integer) msg.obj;
            mWindowManager.updateViewLayout(mMRocketView, mParams);
        }
    };

    public RocketService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        Display defaultDisplay = mWindowManager.getDefaultDisplay();
        Point point = new Point();
        defaultDisplay.getSize(point);
        mScreenWidth = point.x;
        mScreenHeight = point.y;

        showRocket();

        super.onCreate();
    }

    private void showRocket() {

        final WindowManager.LayoutParams params = mParams;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
        params.format = PixelFormat.TRANSPARENT;
        params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        params.setTitle("Toast");
        params.gravity = Gravity.LEFT + Gravity.TOP;

        mMRocketView = View.inflate(this, R.layout.rocket_view, null);
        //开启动画
        final ImageView mRocketView = (ImageView) mMRocketView.findViewById(R.id.iv_rocket);
        AnimationDrawable animationDrawable = (AnimationDrawable) mRocketView.getBackground();
        animationDrawable.start();

        // 挂在到window窗口
        mWindowManager.addView(mMRocketView, params);

        mRocketView.setOnTouchListener(new View.OnTouchListener() {

            private int startX;
            private int startY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        //获取按下的xy坐标
                        startX = (int) event.getRawX();
                        startY = (int) event.getRawY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        //获取移动xy坐标和按下的xy坐标做差,做差得到的值小火箭移动的距离
                        //移动过程中做容错处理
                        //第一次移动到的位置,作为第二次移动的初始位置
                        int moveX = (int) event.getRawX();
                        int moveY = (int) event.getRawY();

                        int disX = moveX - startX;
                        int disY = moveY - startY;

                        params.x = params.x + disX;
                        params.y = params.y + disY;

                        //在窗体中仅仅告知吐司的左上角的坐标
                        if (params.x < 0) {
                            params.x = 0;
                        }
                        if (params.y < 0) {
                            params.y = 0;
                        }

                        if (params.x > mScreenWidth - mRocketView.getWidth()) {
                            params.x = mScreenWidth - mRocketView.getWidth();
                        }

                        if (params.y > mScreenHeight - 22 - mRocketView.getHeight()) {
                            params.y = mScreenHeight - 22 - mRocketView.getHeight();
                        }

                        //告知吐司在窗体上刷新
                        mWindowManager.updateViewLayout(mMRocketView, params);

                        //在第一次移动完成后,将最终坐标作为第二次移动的起始坐标
                        startX = (int) event.getRawX();
                        startY = (int) event.getRawY();
                        break;
                    case MotionEvent.ACTION_UP:
                        WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
                        Display defaultDisplay = windowManager.getDefaultDisplay();
                        Point point = new Point();
                        defaultDisplay.getSize(point);
                        //手指放开的时候,如果放手坐标,则指定区域内
                        if (params.x > point.x/2 - 120 && params.x < point.x/2 - 20 && params.y > 300) {
                            //火箭的发射
                            sendRocket();
                            //在开启火箭过程中,去开启一个新的activity,activity透明,在此activity中放置两张图片(淡入淡出效果)
                            Intent intent = new Intent(getApplicationContext(), BackgroundActivity.class);
                            //指定开启新的activity任务栈
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivity(intent);
                        }
                        break;
                }
                return true;
            }


        });
    }

    private void sendRocket() {
        new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 11; i++) {
                    int y = 350 - i * 35;
                    try {
                        Thread.sleep(20);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    Message msg = Message.obtain();
                    msg.obj = y;
                    mHandler.sendMessage(msg);
                }
            }
        }.start();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        if (mWindowManager != null && mMRocketView != null) {
            mWindowManager.removeView(mMRocketView);
        }
        super.onDestroy();
    }
}

  • BackgroundActivity
package com.example.rocket;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.widget.ImageView;

public class BackgroundActivity extends AppCompatActivity {

    private ImageView mIvTop;
    private ImageView mIvBottm;
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            finish();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_background);

        hideStatusBar();

        mIvTop = (ImageView) findViewById(R.id.iv_top);
        mIvBottm = (ImageView) findViewById(R.id.iv_bottom);

        AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
        alphaAnimation.setDuration(500);
        mIvTop.startAnimation(alphaAnimation);
        mIvBottm.startAnimation(alphaAnimation);


        mHandler.sendEmptyMessageDelayed(0, 1000);
    }

    private void hideStatusBar() {
        View decorView = getWindow().getDecorView();
        // Hide both the navigation bar and the status bar.
        // SYSTEM_UI_FLAG_FULLSCREEN is only available on Android 4.1 and higher, but as
        // a general rule, you should design your app to hide the status bar whenever you
        // hide the navigation bar.
        int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_FULLSCREEN;
        decorView.setSystemUiVisibility(uiOptions);

    }


}

  • drawable 动画

<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/desktop_rocket_launch_1"
        android:duration="200"/>
    <item android:drawable="@drawable/desktop_rocket_launch_2"
        android:duration="200"/>
animation-list>
  • activity_background.xml

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".BackgroundActivity">

    <ImageView
        android:id="@+id/iv_bottom"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:srcCompat="@drawable/desktop_smoke_m" />

    <ImageView
        android:id="@+id/iv_top"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@+id/iv_bottom"
        app:layout_constraintEnd_toEndOf="@+id/iv_bottom"
        app:srcCompat="@drawable/desktop_smoke_t" />
android.support.constraint.ConstraintLayout>
  • activity_main.xml

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/bt_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="80dp"
        android:layout_marginLeft="80dp"
        android:layout_marginTop="68dp"
        android:text="开启火箭人"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:onClick="startRocket"/>

    <Button
        android:id="@+id/bt_stop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="80dp"
        android:layout_marginLeft="80dp"
        android:layout_marginTop="72dp"
        android:text="关闭火箭人"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/bt_start"
        android:onClick="endRocket"/>
android.support.constraint.ConstraintLayout>
  • rocket_view.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv_rocket"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/rocket_bg" />
LinearLayout>
  • values文件夹下的colors.xml


<resources>
    <color name="colorPrimary">#008577color>
    <color name="colorPrimaryDark">#00574Bcolor>
    <color name="colorAccent">#D81B60color>
    <color name="transparent">#0000color>
resources>

  • values下的styles.xml
<resources>

    
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        
        "colorPrimary">@color/colorPrimary
        "colorPrimaryDark">@color/colorPrimaryDark
        "colorAccent">@color/colorAccent
    style>
    <style name="MyActivityTheme" parent="Theme.AppCompat.Light.NoActionBar">
        "android:windowNoTitle">true
        "android:windowBackground">@color/transparent
        "android:windowIsTranslucent">true
    style>

resources>

  • AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.rocket">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".BackgroundActivity" android:theme="@style/MyActivityTheme">activity>

        <service
            android:name=".RocketService"
            android:enabled="true"
            android:exported="true" />

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

manifest>

你可能感兴趣的:(Android学习笔记)