本文共 11571 字,大约阅读时间需要 38 分钟。
Android CircularFloatingActionMenu:作为系统级按钮悬浮桌面弹出菜单使用(3)
Android CircularFloatingActionMenu另外一个不同寻常的地方是,Android CircularFloatingActionMenu可以写在服务Service里面,然后通过上层一个Activity启动这个服务,然后就可以作为Android系统级悬浮按钮悬浮在系统的桌面上使用,这在一些常见的安全软件中很常见,比如,一些安全软件常驻桌面,为用户实时提供流量监控等等这些数据检测或者开关按钮。
现在使用Android CircularFloatingActionMenu实现该功能。 Java代码,其实这里只是写一个后台Service即可,该Service将被其他组件调用:import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;//import android.util.Log;import android.view.View;import android.view.WindowManager;import android.widget.FrameLayout;import android.widget.ImageView;//import android.widget.TextView;import com.oguzdev.circularfloatingactionmenu.library.FloatingActionButton;import com.oguzdev.circularfloatingactionmenu.library.FloatingActionMenu;import com.oguzdev.circularfloatingactionmenu.library.SubActionButton;public class SystemOverlayMenuService extends Service { private final IBinder mBinder = new LocalBinder(); //下方白色+号小按钮 private FloatingActionButton rightLowerButton; //顶部中心位置的大红色星号按钮 private FloatingActionButton topCenterButton; private FloatingActionMenu rightLowerMenu; private FloatingActionMenu topCenterMenu; private boolean serviceWillBeDismissed; public SystemOverlayMenuService() { } public class LocalBinder extends Binder { SystemOverlayMenuService getService() { // Return this instance of LocalService so clients can call public methods return SystemOverlayMenuService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public void onCreate() { super.onCreate(); serviceWillBeDismissed = false; // Set up the white button on the lower right corner // more or less with default parameter ImageView fabIconNew = new ImageView(this); fabIconNew.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_new_light)); WindowManager.LayoutParams params = FloatingActionButton.Builder.getDefaultSystemWindowParams(this); //右边下方小按钮 rightLowerButton = new FloatingActionButton.Builder(this) .setContentView(fabIconNew) .setSystemOverlay(true) //使该按钮作为系统悬浮按钮显示在设备屏幕上 .setLayoutParams(params) .build(); SubActionButton.Builder rLSubBuilder = new SubActionButton.Builder(this); ImageView rlIcon1 = new ImageView(this); ImageView rlIcon2 = new ImageView(this); ImageView rlIcon3 = new ImageView(this); ImageView rlIcon4 = new ImageView(this); rlIcon1.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_chat_light)); rlIcon2.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_camera_light)); rlIcon3.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_video_light)); rlIcon4.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_place_light)); // Build the menu with default options: light theme, 90 degrees, 72dp radius. // Set 4 default SubActionButtons SubActionButton rlSub1 = rLSubBuilder.setContentView(rlIcon1).build(); SubActionButton rlSub2 = rLSubBuilder.setContentView(rlIcon2).build(); SubActionButton rlSub3 = rLSubBuilder.setContentView(rlIcon3).build(); SubActionButton rlSub4 = rLSubBuilder.setContentView(rlIcon4).build(); rightLowerMenu = new FloatingActionMenu.Builder(this, true) .addSubActionView(rlSub1, rlSub1.getLayoutParams().width, rlSub1.getLayoutParams().height) .addSubActionView(rlSub2, rlSub2.getLayoutParams().width, rlSub2.getLayoutParams().height) .addSubActionView(rlSub3, rlSub3.getLayoutParams().width, rlSub3.getLayoutParams().height) .addSubActionView(rlSub4, rlSub4.getLayoutParams().width, rlSub4.getLayoutParams().height) .setStartAngle(180) .setEndAngle(270) .attachTo(rightLowerButton) .build(); //创建居于设备顶部居中的大红色按钮 // Set up the large red button on the top center side // With custom button and content sizes and margins int redActionButtonSize = getResources().getDimensionPixelSize(R.dimen.red_action_button_size); int redActionButtonMargin = getResources().getDimensionPixelOffset(R.dimen.action_button_margin); int redActionButtonContentSize = getResources().getDimensionPixelSize(R.dimen.red_action_button_content_size); int redActionButtonContentMargin = getResources().getDimensionPixelSize(R.dimen.red_action_button_content_margin); int redActionMenuRadius = getResources().getDimensionPixelSize(R.dimen.red_action_menu_radius); int blueSubActionButtonSize = getResources().getDimensionPixelSize(R.dimen.blue_sub_action_button_size); int blueSubActionButtonContentMargin = getResources().getDimensionPixelSize(R.dimen.blue_sub_action_button_content_margin); ImageView fabIconStar = new ImageView(this); fabIconStar.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_important)); FloatingActionButton.LayoutParams fabIconStarParams = new FloatingActionButton.LayoutParams(redActionButtonContentSize, redActionButtonContentSize); fabIconStarParams.setMargins(redActionButtonContentMargin, redActionButtonContentMargin, redActionButtonContentMargin, redActionButtonContentMargin); WindowManager.LayoutParams params2 = FloatingActionButton.Builder.getDefaultSystemWindowParams(this); params2.width = redActionButtonSize; params2.height = redActionButtonSize; topCenterButton = new FloatingActionButton.Builder(this) .setSystemOverlay(true) .setContentView(fabIconStar, fabIconStarParams) .setBackgroundDrawable(R.drawable.button_action_red_selector) .setPosition(FloatingActionButton.POSITION_TOP_CENTER) //顶部中心位置 .setLayoutParams(params2) .build(); //为顶部中心位置的大红色按钮增加弹出的子菜单 // Set up customized SubActionButtons for the right center menu SubActionButton.Builder tCSubBuilder = new SubActionButton.Builder(this); tCSubBuilder.setBackgroundDrawable(getResources().getDrawable(R.drawable.button_action_blue_selector)); //小红色关闭叉子那个按钮Builder SubActionButton.Builder tCRedBuilder = new SubActionButton.Builder(this); tCRedBuilder.setBackgroundDrawable(getResources().getDrawable(R.drawable.button_action_red_selector)); FrameLayout.LayoutParams blueContentParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); blueContentParams.setMargins(blueSubActionButtonContentMargin, blueSubActionButtonContentMargin, blueSubActionButtonContentMargin, blueSubActionButtonContentMargin); // Set custom layout params FrameLayout.LayoutParams blueParams = new FrameLayout.LayoutParams(blueSubActionButtonSize, blueSubActionButtonSize); tCSubBuilder.setLayoutParams(blueParams); tCRedBuilder.setLayoutParams(blueParams); ImageView tcIcon1 = new ImageView(this); ImageView tcIcon2 = new ImageView(this); ImageView tcIcon3 = new ImageView(this); ImageView tcIcon4 = new ImageView(this); ImageView tcIcon5 = new ImageView(this); ImageView tcIcon6 = new ImageView(this); tcIcon1.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_camera)); tcIcon2.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_picture)); tcIcon3.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_video)); tcIcon4.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_location_found)); tcIcon5.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_headphones)); tcIcon6.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_cancel)); SubActionButton tcSub1 = tCSubBuilder.setContentView(tcIcon1, blueContentParams).build(); SubActionButton tcSub2 = tCSubBuilder.setContentView(tcIcon2, blueContentParams).build(); SubActionButton tcSub3 = tCSubBuilder.setContentView(tcIcon3, blueContentParams).build(); SubActionButton tcSub4 = tCSubBuilder.setContentView(tcIcon4, blueContentParams).build(); SubActionButton tcSub5 = tCSubBuilder.setContentView(tcIcon5, blueContentParams).build(); SubActionButton tcSub6 = tCRedBuilder.setContentView(tcIcon6, blueContentParams).build(); // Build another menu with custom options topCenterMenu = new FloatingActionMenu.Builder(this, true) .addSubActionView(tcSub1, tcSub1.getLayoutParams().width, tcSub1.getLayoutParams().height) .addSubActionView(tcSub2, tcSub2.getLayoutParams().width, tcSub2.getLayoutParams().height) .addSubActionView(tcSub3, tcSub3.getLayoutParams().width, tcSub3.getLayoutParams().height) .addSubActionView(tcSub4, tcSub4.getLayoutParams().width, tcSub4.getLayoutParams().height) .addSubActionView(tcSub5, tcSub5.getLayoutParams().width, tcSub5.getLayoutParams().height) .addSubActionView(tcSub6, tcSub6.getLayoutParams().width, tcSub6.getLayoutParams().height) .setRadius(redActionMenuRadius) .setStartAngle(0) .setEndAngle(180) .attachTo(topCenterButton) .build(); topCenterMenu.setStateChangeListener(new FloatingActionMenu.MenuStateChangeListener() { @Override public void onMenuOpened(FloatingActionMenu menu) { } @Override public void onMenuClosed(FloatingActionMenu menu) { if(serviceWillBeDismissed) { SystemOverlayMenuService.this.stopSelf(); serviceWillBeDismissed = false; } } }); // make the red button terminate the service tcSub6.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { serviceWillBeDismissed = true; // the order is important topCenterMenu.close(true); } }); } @Override public void onDestroy() { if(rightLowerMenu != null && rightLowerMenu.isOpen()) rightLowerMenu.close(false); if(topCenterMenu != null && topCenterMenu.isOpen()) topCenterMenu.close(false); if(rightLowerButton != null) rightLowerButton.detach(); if(topCenterButton != null) topCenterButton.detach(); super.onDestroy(); }}
代码运行效果(作为Service启动),此时Activity已经退出,但Service启动后的这两个按钮一直常驻设备桌面,如动图展示:
代码中涉及到的更多自定义属性可以在该项目的代码包里具体查看。
附录相关文章:
A、《Android CircularFloatingActionMenu (1)》链接地址: B、《Android CircularFloatingActionMenu在ScrollView这样的滚动View中使用(2)》链接地址:C、《Android第三方开源FloatingActionButton(com.getbase.floatingactionbutton)【1】》链接地址:
D、《Android第三方开源FloatingActionButton(com.getbase.floatingactionbutton)【2】》链接地址: E、《Android第三方开源FloatingActionButton(com.getbase.floatingactionbutton): FloatingActionsMenu【3】》链接地址: F、《Android FloatingActionButton: FloatingActionsMenu向下伸展弹出及删除包含的FloatingActionButton【4】》链接地址: G、《Android Material Design的FloatingActionButton,Snackbar和CoordinatorLayout》链接地址: H、《Android第三方FloatingActionButton:伴随ListView、RecyclerView、ScrollView滚动滑入滑出》链接地址:I,Android CircularFloatingActionMenu在github上的项目主页: