【Android】手机蜘蛛魔术的简易app例子

手机画面内容结合魔术手法在魔术表演中可以达到一种很强的视觉场景冲击,比如手机里的蜘蛛爬出来的魔术,这里做一个简易的app,

首先找到蜘蛛的png图片,多做几张可以实现更好的爬动效果,这里用一张来试验,把图片中的白色背景转换为透明颜色,

python 复制代码
from PIL import Image
# 打开图片
img = Image.open('spider0.png')
img = img.convert("RGBA")
datas = img.getdata()

newData = []
for item in datas:
    # 如果像素的颜色接近白色,则将其改为完全透明
    if item[0] > 240 and item[1] > 240 and item[2] > 240:
        newData.append((255, 255, 255, 0))
    else:
        newData.append(item)

img.putdata(newData)
img.save("spider.png", "PNG")

app例子

java 复制代码
package com.example.magic;

import androidx.appcompat.app.AppCompatActivity;

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.os.Bundle;

// app/src/main/java/com/example/spiderphoto/MainActivity.java

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_CAMERA_PERMISSION = 100;
    private static final int REQUEST_IMAGE_CAPTURE = 101;

    private ImageView imageView;
    private View spiderView;
    private Button btnTakePhoto;

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

        imageView = findViewById(R.id.imageView);
        spiderView = findViewById(R.id.spiderView);
        btnTakePhoto = findViewById(R.id.btnTakePhoto);

        btnTakePhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (checkCameraPermission()) {
                    dispatchTakePictureIntent();
                } else {
                    requestCameraPermission();
                }
            }
        });
    }

    private boolean checkCameraPermission() {
        return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                == PackageManager.PERMISSION_GRANTED;
    }

    private void requestCameraPermission() {
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.CAMERA},
                REQUEST_CAMERA_PERMISSION);
    }

    private void dispatchTakePictureIntent() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CAMERA_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                dispatchTakePictureIntent();
            } else {
                Toast.makeText(this, "需要相机权限才能拍照", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            Bundle extras = data.getExtras();
            Bitmap imageBitmap = (Bitmap) extras.get("data");

            // 显示照片
            imageView.setImageBitmap(imageBitmap);
            imageView.setVisibility(View.VISIBLE);
            btnTakePhoto.setVisibility(View.GONE);

            // 启动蜘蛛动画
            startSpiderCrawl();
        }
    }

    private void startSpiderCrawl00() {
        ImageView spider = findViewById(R.id.spiderView);
        spider.setVisibility(View.VISIBLE);

        // 获取屏幕高度(用于计算移动距离)
        int screenHeight = getResources().getDisplayMetrics().heightPixels;

        // 1. 主动画:垂直向上移动(从底部到顶部外)
        ObjectAnimator moveUp = ObjectAnimator.ofFloat(
                spider, "translationY",
                screenHeight - spider.getHeight(),   // 起点:底部(减去自身高度)
                -spider.getHeight() * 1.2f           // 终点:顶部上方完全消失
        );
        moveUp.setDuration(8000);

        // 2. 辅助动画:左右轻微晃动(模拟爬行时的身体摆动)
        ObjectAnimator sway = ObjectAnimator.ofFloat(spider, "translationX", 0f, -20f, 0f, 20f, 0f);
        sway.setDuration(8000);
        sway.setRepeatCount(ObjectAnimator.INFINITE); // 循环晃动

        // 3. 轻微缩放(模拟腿部蹬地的弹跳感)
        ObjectAnimator bounce = ObjectAnimator.ofFloat(spider, "scaleY", 1.0f, 1.1f, 1.0f, 0.95f, 1.0f);
        bounce.setDuration(800);
        bounce.setRepeatCount(ObjectAnimator.INFINITE);
        bounce.setRepeatMode(ObjectAnimator.REVERSE);

        // 同时播放三个动画
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playTogether(moveUp, sway, bounce);
        animatorSet.start();

        // 动画结束后清理
        moveUp.addListener(new android.animation.AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(android.animation.Animator animation) {
                spider.setVisibility(View.INVISIBLE);
                sway.cancel();
                bounce.cancel();
                btnTakePhoto.setVisibility(View.VISIBLE);
            }
        });
    }

    private void startSpiderCrawl() {
        spiderView.setVisibility(View.VISIBLE);

        // 创建从底部到顶部的平移动画
        TranslateAnimation animation = new TranslateAnimation(
                Animation.RELATIVE_TO_PARENT, 0f,
                Animation.RELATIVE_TO_PARENT, 0f,
                Animation.RELATIVE_TO_PARENT, 0.5f,   // 起点:底部
                Animation.RELATIVE_TO_PARENT, -1.2f // 终点:顶部上方(完全消失)
        );
        animation.setDuration(8000); // 8秒
        animation.setFillAfter(true);

        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {}

            @Override
            public void onAnimationEnd(Animation animation) {
                spiderView.setVisibility(View.INVISIBLE);
                btnTakePhoto.setVisibility(View.VISIBLE); // 恢复按钮
            }

            @Override
            public void onAnimationRepeat(Animation animation) {}
        });

        spiderView.startAnimation(animation);
    }
}
相关推荐
qw102482 小时前
MySQL-mysql zip安装包配置教程
android·mysql·adb
小飞学编程...2 小时前
【Java相关八股文(一)】
android·java·开发语言
QCzblack2 小时前
第五周作业
android
c***03232 小时前
Mysql之主从复制
android·数据库·mysql
火焰中舞蹈的小孩2 小时前
Unity和Android Studio相互调用 CH340在unity中调用
android·ide·android studio
不是AI2 小时前
【Unity开发】一、在安卓设备上运行Unity项目
android·unity·游戏引擎
p***19942 小时前
MySQL Workbench菜单汉化为中文
android·数据库·mysql
wsfk12342 小时前
MySQL 数据库连接池爆满问题排查与解决
android·数据库·mysql
撩得Android一次心动2 小时前
Android DataBinding 全面解析【使用篇】
android·jetpack·databinding