如何实现Android的圆形悬浮球

穷得只剩下快乐 2017-02-05 12:00:39
想自己做一个悬浮球,点击悬浮球,弹出一个界面,该界面可以调节手机的音量,包括系统音量,媒体音量等等各种音量。悬浮球是自定义的View子类,通过WindowManager添加到窗口中,WindowManager默认的背景是方形的且是黑色背景,这导致悬浮球显示在屏幕上时是方形的,而不是圆的。想通过设置背景为透明,从而让悬浮球看起来是圆的,在网上找了方法,网上说可以通过设置WindowManager.LayoutParams对象的format属性的值为PixelFormat.RGBA_8888,从而设置背景是透明的。但是试了还是不行,求各位大神求教!!!怎么实现圆形的悬浮球???
...全文
1413 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
我终于找到方法了,设置LayoutParams.format=PixelFormat.RGBA_8888,就可以设置floatBall的背景是透明的。然后通过查阅资料我也觉得通过设置floatBall的背景为透明也同样可以达到相同的效果,即通过getBackground().setAlpha(0),但是遇到了上面我说过的异常,而且不知道为什么会出项这样的异常。
  • 打赏
  • 举报
回复
引用 6 楼 qiguangyaolove 的回复:
你这个控件肯定是方的,把View背景设置成透明的就可以了 在floatBall的ondraw末尾加上getBackground().setAlpha(0); 或者在floatBall完成完全实例化以后进行操作floatBall.getBackground().setAlpha(0);
我今天试了你这个方法,但是提示NullPointerException,就是getBackground()方法返回的是null,至今也还是不知道为什么,你之前见过这样的错误吗?求指教~
  • 打赏
  • 举报
回复
引用 5 楼 ganshenml 的回复:
[quote=引用 4 楼 qq_24041497 的回复:] 主要是FloatBall类的onDraw方法以及ViewManager的show方法
你的FloatBall是圆形的,然后你把它添加进了WindowManager.LayoutParams,但是这个父布局layoutparams却是矩形的,所以就多了那些边角——>想办法把这些边角去掉[/quote] 嗯嗯,我之前想的是将这些边角设置成透明的。但是苦于找不到方法。
ganshenml 2017-02-07
  • 打赏
  • 举报
回复
引用 7 楼 qq_24041497 的回复:
[quote=引用 5 楼 ganshenml 的回复:] [quote=引用 4 楼 qq_24041497 的回复:] 主要是FloatBall类的onDraw方法以及ViewManager的show方法
你的FloatBall是圆形的,然后你把它添加进了WindowManager.LayoutParams,但是这个父布局layoutparams却是矩形的,所以就多了那些边角——>想办法把这些边角去掉[/quote] 嗯嗯,我之前想的是将这些边角设置成透明的。但是苦于找不到方法。[/quote] Android 使用WindowManager实现悬浮窗及源码解析
  • 打赏
  • 举报
回复
主要是FloatBall类的onDraw方法以及ViewManager的show方法
  • 打赏
  • 举报
回复
一共涉及四个类 自定义的悬浮球: Service类:由于要一直悬浮球要一直显示在屏幕上,所以要使用Service显示悬浮球。 ViewManager类:用于添加悬浮球和删除悬浮球 public class ViewManager { private static ViewManager viewManager; private WindowManager windowManager; private FloatBall floatBall; private ViewManager() {} public static ViewManager getViewManagerInstance() { if(viewManager == null) viewManager = new ViewManager(); return viewManager; } public void show(final Context context) { windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); floatBall = new FloatBall(context); floatBall.setBackgroundColor(Color.parseColor("#ffdddddd")); layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE; layoutParams.width = floatBall.width; layoutParams.height = floatBall.height; layoutParams.flags = 40; layoutParams.format = PixelFormat.RGBA_8888 | PixelFormat.TRANSLUCENT; //floatBall.setLayoutParams(layoutParams); windowManager.addView(floatBall, layoutParams); floatBall.setOnTouchListener(new View.OnTouchListener() { float startX; float startY; // 原位置 @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); float x = event.getRawX(); float y = event.getRawY(); // 新位置 if(action == MotionEvent.ACTION_DOWN) { startX = x; startY = y; } else if(action == MotionEvent.ACTION_MOVE) { x = event.getRawX(); y = event.getRawY(); layoutParams.x += (int)(x - startX); layoutParams.y += (int)(y - startY); windowManager.updateViewLayout(floatBall, layoutParams); startX = x; startY = y; } else if(action == MotionEvent.ACTION_UP) { startX = x; startY = y; } return false; } }); floatBall.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final View view = LayoutInflater.from(context).inflate(R.layout.streamvolume, null); view.setBackgroundColor(Color.parseColor("#ffdddddd")); WindowManager.LayoutParams layoutParams1 = new WindowManager.LayoutParams(); layoutParams1.width = 800; layoutParams1.height = 950; layoutParams1.type = WindowManager.LayoutParams.TYPE_PHONE; layoutParams1.flags = 40; windowManager.addView(view, layoutParams1); final AudioManager am = (AudioManager)view.getContext().getSystemService(Context.AUDIO_SERVICE); SeekBar sysVolume = (SeekBar)view.findViewById(R.id.sysVolume); SeekBar callVolume = (SeekBar)view.findViewById(R.id.callVolume); SeekBar ringVolume = (SeekBar)view.findViewById(R.id.ringVolume); SeekBar musicVolume = (SeekBar)view.findViewById(R.id.musicVolume); SeekBar notifyVolume = (SeekBar)view.findViewById(R.id.notifyVolume); SeekBar alarmVolume = (SeekBar)view.findViewById(R.id.alarmVolume); // 1 系统音量 sysVolume.setMax(am.getStreamMaxVolume(AudioManager.STREAM_SYSTEM)); sysVolume.setProgress(am.getStreamVolume(AudioManager.STREAM_SYSTEM)); sysVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { am.setStreamVolume(AudioManager.STREAM_SYSTEM, progress, AudioManager.FLAG_PLAY_SOUND); } @Override public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onStopTrackingTouch(SeekBar seekBar) {} }); // 2 通话音量 callVolume.setMax(am.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL)); callVolume.setProgress(am.getStreamVolume(AudioManager.STREAM_VOICE_CALL)); callVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { am.setStreamVolume(AudioManager.STREAM_VOICE_CALL, progress, AudioManager.FLAG_PLAY_SOUND); } @Override public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onStopTrackingTouch(SeekBar seekBar) {} }); // 3 铃声音量 ringVolume.setMax(am.getStreamMaxVolume(AudioManager.STREAM_RING)); ringVolume.setProgress(am.getStreamVolume(AudioManager.STREAM_RING)); ringVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { am.setStreamVolume(AudioManager.STREAM_RING, progress, AudioManager.FLAG_PLAY_SOUND); } @Override public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onStopTrackingTouch(SeekBar seekBar) {} }); // 4 媒体音量 musicVolume.setMax(am.getStreamMaxVolume(AudioManager.STREAM_MUSIC)); musicVolume.setProgress(am.getStreamVolume(AudioManager.STREAM_MUSIC)); musicVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { am.setStreamVolume(AudioManager.STREAM_MUSIC, progress, AudioManager.FLAG_PLAY_SOUND); } @Override public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onStopTrackingTouch(SeekBar seekBar) {} }); // 5 通知音量 notifyVolume.setMax(am.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION)); notifyVolume.setProgress(am.getStreamVolume(AudioManager.STREAM_NOTIFICATION)); notifyVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { am.setStreamVolume(AudioManager.STREAM_NOTIFICATION, progress, AudioManager.FLAG_PLAY_SOUND); } @Override public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onStopTrackingTouch(SeekBar seekBar) {} }); // 6 警报音量 alarmVolume.setMax(am.getStreamMaxVolume(AudioManager.STREAM_ALARM)); alarmVolume.setProgress(am.getStreamVolume(AudioManager.STREAM_ALARM)); alarmVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { am.setStreamVolume(AudioManager.STREAM_ALARM, progress, AudioManager.FLAG_PLAY_SOUND); } @Override public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onStopTrackingTouch(SeekBar seekBar) {} }); ImageView c = (ImageView)view.findViewById(R.id.close); c.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { windowManager.removeView(view); } }); } }); } public void close() { windowManager.removeView(floatBall); } } 另外是一个MainAcitivity类,定义两个按钮,点击它们可以启动Service和关闭Servcie。
ganshenml 2017-02-06
  • 打赏
  • 举报
回复
把代码贴出来看看
qiguangyaolove 2017-02-06
  • 打赏
  • 举报
回复
你这个控件肯定是方的,把View背景设置成透明的就可以了 在floatBall的ondraw末尾加上getBackground().setAlpha(0); 或者在floatBall完成完全实例化以后进行操作floatBall.getBackground().setAlpha(0);
ganshenml 2017-02-06
  • 打赏
  • 举报
回复
引用 4 楼 qq_24041497 的回复:
主要是FloatBall类的onDraw方法以及ViewManager的show方法
你的FloatBall是圆形的,然后你把它添加进了WindowManager.LayoutParams,但是这个父布局layoutparams却是矩形的,所以就多了那些边角——>想办法把这些边角去掉
  • 打赏
  • 举报
回复

补充一下,自己实现的悬浮球如图所示,可以看到背景色是黑色且是方形的。中间是真正要的悬浮球。要怎么实现圆形的悬浮球呢?

80,492

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧