在安卓上实现一个桌面宠物APP

在安卓上实现一个桌面宠物APP

1 桌面宠物APP需求分析1.1 项目简介使用安卓开发实现一个类似QQ宠物的桌面宠物APP。

1.2 灵感来源之前看到360安全卫士在安卓桌面实现悬浮窗的功能,我想利用悬浮窗这个想法来实现一个全局安卓桌面宠物APP。

1.3 实现功能• 宠物成长功能:根据手机使用时长实现宠物进化升级的功能,主要是宠物形态的变化;• 随意移动宠物;• 点击宠物打开功能菜单:包括照相、购物和回家功能;• 打开APP首页;• 打开淘宝首页;• 打开照相机;• 未完待续。

2 桌面宠物APP实现分析2.1 悬浮窗的实现基于Android开发四大组件之一的Service实现悬浮窗。• 定义PetWindowService类继承Service类

1public class PetWindowService extends Service{...}

• 用WindowManager类来实现悬浮窗的窗体参数的设置。

1wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);

1234567891011121314151617181920212223242526272829303132private void showPetView() { //获取屏幕宽度和高度 winWidth = wm.getDefaultDisplay().getWidth(); winHeight = wm.getDefaultDisplay().getHeight(); params = new WindowManager.LayoutParams(); int LAYOUT_FLAG; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; } else { LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; } // 自定义宠物窗体params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; // 屏幕左上角对齐 params.gravity = Gravity.LEFT + Gravity.TOP; params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; params.format = PixelFormat.TRANSLUCENT; params.type = LAYOUT_FLAG; // 加入宠物窗体 petView = View.inflate(this, R.layout.activity_pet, null); // 悬浮窗功能菜单控件 imageView = petView.findViewById(R.id.petView); imgHome = petView.findViewById(R.id.imgHome); imgCart = petView.findViewById(R.id.imgCart); imgCamera = petView.findViewById(R.id.imgCamera); petNameView = petView.findViewById(R.id.petName); wm.addView(petView, params);}

• 实现宠物拖拽。

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748// 实现拖拽宠物imageView.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 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 > winWidth - petView.getWidth()) { params.x = winWidth - petView.getWidth(); } if (params.y > winHeight - petView.getHeight()) { params.y = winHeight - petView.getHeight(); } wm.updateViewLayout(petView, params); startX = (int) event.getRawX(); startY = (int) event.getRawY(); break; case MotionEvent.ACTION_UP: break; } return false; }});

2.2 宠物功能菜单栏的实现• 实现功能菜单栏,主要是ImageView的监听事件实现菜单开关:使用count计数来判断奇数单击还是偶数单击对应打开菜单和关闭菜单。控制菜单可见方法:ImageView控件的setVisibility方法包括三个属性:VISIBLE、GONE、INVISIBLE,分别表示控件可见、不可见且不占位、不可见且占位。

123456789101112131415161718// 实现单击打开菜单,第二次关闭菜单imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { count++; if(count % 2 == 1){ imgHome.setVisibility(View.VISIBLE); imgCamera.setVisibility(View.VISIBLE); imgCart.setVisibility(View.VISIBLE); } else { imgHome.setVisibility(View.GONE); imgCamera.setVisibility(View.GONE); imgCart.setVisibility(View.GONE); count = 0; } }});

• 跳转到APP主页,从Service跳转到Activity需要设置intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);,跳转到其他APP也要用到这行代码。

123456789// 点击imgHome打开主页面imgHome.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(PetWindowService.this, MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); }});

• 跳转到相机。

12345678910// 点击imgCamera打开相机imgCamera.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setAction("android.media.action.STILL_IMAGE_CAMERA"); startActivity(intent); }});

• 跳转到淘宝。

1234567891011// 点击imgCart打开淘宝imgCart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setAction("Android.intent.action.VIEW"); intent.setClassName("com.taobao.taobao", "com.taobao.tao.welcome.Welcome"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); }});

2.3 APP主页显示宠物信息主页实现功能主要包括:宠物取名,选择宠物类型,领养新宠物,选择已有宠物进行展示,宠物名字展示,宠物类型展示,宠物年龄展示,释放宠物,收回宠物,删除宠物。• 第一部分:创建宠物选择宠物类型,Spinner控件监听事件。

1234567891011 // 选择宠物类型petMode.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { mode = modeArray[position]; } @Override public void onNothingSelected(AdapterView parent) { }});

创建宠物类型,Button控件监听事件,将宠物名字一并记录。

12345678910111213141516171819202122232425262728293031// 创建宠物bn_createPet.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 取名 petName = editName.getText().toString(); boolean sameName = false; for (int i = 0; i < petNameAdapter.getCount(); i++) { if (petName.equals(petNameAdapter.getItem(i))) { sameName = true; break; } } if (!editName.getText().toString().equals("") && !sameName){ // 创建宠物 createPet(mode, petName, petAgeSeconds); Toast.makeText(MainActivity.this, "恭喜你拥有了一只" + mode + "类宠物," + "它的名字叫" + petName, Toast.LENGTH_LONG).show(); petNameAdapter.add(petName); } else { Toast.makeText(MainActivity.this, "名字不能为空或重复,请再次输入!", Toast.LENGTH_LONG).show(); } }});

• 第二部分:展示宠物信息首先从数据库中选择已有宠物进行展示。

123456789101112131415161718192021222324252627// 从数据库中选择一只宠物petNameList.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { tmp_name = (String) petNameList.getSelectedItem(); // 上一个宠物名字 if (!last_name.equals("")){ last_name = showPetName.getText().toString(); } else { last_name = tmp_name; } // 显示宠物名字 showPetName.setText(tmp_name); // 显示宠物类型 showPetMode.setText(getPetMode(tmp_name)); // 显示宠物图像 showPetImg.setImageResource(changePet(showPetMode.getText().toString())); // 显示宠物年龄 petAgeView.setText(showPetAge(getPetAge(tmp_name))); } @Override public void onNothingSelected(AdapterView parent) { }});

释放宠物,即生成悬浮窗。

1234567891011121314 // 释放宠物bn_showPet.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 传宠物参数到Service Intent intent = new Intent(MainActivity.this, PetWindowService.class); intent.putExtra("pet_name", showPetName.getText().toString()) .putExtra("pet_mode", showPetMode.getText().toString()) .putExtra("pet_age", String.valueOf(getPetAge(showPetName.getText().toString()))); startService(intent); // finish(); Log.d(TAG, "onClick: 成功释放"); }});

收回宠物。

12345678// 收回宠物bn_backPet.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, PetWindowService.class); stopService(intent); }});

删除宠物:删除适配器和数据库对应宠物。

1234567public void removePet(String name) { // 删除适配器对应宠物对象 petNameAdapter.remove(name); // 删除数据库对应宠物数据 usePetDB.removePet(name);}

详细代码见github。

谢谢大爷的打赏~

相关画作

《辐射4》狙击枪在哪获得 狙击枪获取位置分享
365bet体育注册开户

《辐射4》狙击枪在哪获得 狙击枪获取位置分享

📅 08-03 👁️ 4688
电脑网页字体大小怎么调 网页字体大小设置教程【详解】
最命苦的生肖是什么
365电竞比分

最命苦的生肖是什么

📅 08-12 👁️ 1815