网站设计的几大标准,wordpress插件按下载数,中英文 网站,wordpress xml rpc场景需求#xff1a;
在底部导航栏添加power案件#xff0c;单击息屏#xff0c;长按 关机
如下实现图
借此需求#xff0c;需要掌握技能#xff1a;
底部导航栏如何实现新增、修改、删除底部导航栏流程对底部导航栏部分样式如何修改。 比如放不下、顺序排列、坑点如…场景需求
在底部导航栏添加power案件单击息屏长按 关机
如下实现图
借此需求需要掌握技能
底部导航栏如何实现新增、修改、删除底部导航栏流程对底部导航栏部分样式如何修改。 比如放不下、顺序排列、坑点如何修改等
修改-新增文件:
新增
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\layout\power.xml [新增底部导航 power 功能按键布局文件]
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\drawable\ic_lock_power_off.xml [新增power按键icon图标]
修改
\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\navigationbar\NavigationBarView.java
\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\navigationbar\NavigationBar.java
\vendor\mediatek\proprietary\packages\apps\SystemUI\src\com\android\systemui\navigationbar\NavigationBarInflaterView.java需改新增 power 功能菜单
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\values\config.xml
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\values-sw900dp\config.xml
\vendor\mediatek\proprietary\packages\apps\SystemUI\res\values-sw600dp\config.xml//按键太多设置按键宽度让竖屏情况下多个功能虚拟按键能够正常显示出来我们对应的dimens 文件为values-sw600dp 故只修改这个文件即可
/vendor/mediatek/proprietary/packages/apps/SystemUI/res/values-sw600dp/dimens.xml
具体修改点
修改点 一 功能按键添加power
string nameconfig_navBarLayout translatablefalseleft;volume_sub,back,home,recent,wb_sunny,volume_add,power,screenshot;right/string修改点 二 虚拟按键宽度和padding 重写设置
dimen namenavigation_key_width90dp/dimen
修改点 三
NavigationBarView.java [设置按键图标、按键放到集合中便于封装操作]
NavigationBar.java [点触事件 长按、短按事件]
NavigationBarInflaterView.java [加载布局加载功能按键view]
见修改文件 wang 相关 add 和 end 结束位置
下文 详细说明参考资料
Android 8.1平台SystemUI 导航栏加载流程解析 Android 9.0 SystemUI NavigationBar Android13 关于SystemUI更新Nav Bar add volume button other button Android 导航栏功能项的显示与屏蔽 Android 12 自定义底部导航栏 Android11 底部导航栏添加虚拟按钮-问题合集
实现思路和具体方案
在实现方案之前一脸蒙蔽那是缺乏一定的知识储备实现后发现思路很清晰的理解流程一步一步实现即可。可以参考现有的实现方案比如home/back/recent 部分Android版本 本身就已经有的功能照葫芦画瓢。
主要思路如下
创建功能按键布局layout[对应 xml]:参考已有的功能按键配置文件中新增功能按键菜单只有有了默认的配置才会加载上面的布局ViewNavigationBar为系统加载的组件在组件中实现点击事件在关联的加载布局View 类 NavigationBarInflaterView.java 和 NavigationBarView.java 实现布局的功能按键View的添加和功能view 的获取/设置View背景等最终实现功能按键的加载。
布局创建
比如我们的power.xml
?xml version1.0 encodingutf-8?
com.android.systemui.navigationbar.buttons.KeyButtonViewxmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:systemuihttp://schemas.android.com/apk/res-autoandroid:idid/powerandroid:layout_widthdimen/navigation_key_widthandroid:layout_heightmatch_parentandroid:layout_weight0systemui:keyCode26android:scaleTypecenterandroid:contentDescriptionstring/accessibility_homeandroid:paddingStartdimen/navigation_key_paddingandroid:paddingEnddimen/navigation_key_padding/那为什么这么创建 找一下 已有的 功能按键 比如Home 按键
com.android.systemui.navigationbar.buttons.KeyButtonViewxmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:systemuihttp://schemas.android.com/apk/res-autoandroid:idid/homeandroid:layout_widthdimen/navigation_key_widthandroid:layout_heightmatch_parentandroid:layout_weight0systemui:keyCode3android:scaleTypecenterandroid:contentDescriptionstring/accessibility_homeandroid:paddingStartdimen/navigation_key_paddingandroid:paddingEnddimen/navigation_key_padding/这里有三个点需要注意
layout_width 值的设置底部导航栏功能按键过多会出现不会显示全的问题需要适配。keyCode有keyCode设置会根据KeyButtonView 监听到keyCode 按键值这样可以监听并执行对应逻辑。【此需求暂无用到】id 这个id 在NavigationBarView中的 mButtonDispatchers.put(R.id.power, new ButtonDispatcher(R.id.power)); 对应 匹配不然找不到id。
布局加载
添加到NavigationBarInflaterView中去NavigationBarInflaterView 见名知意。本身代码量不多的就是一个View加载功能按键子View
NavigationBarInflaterView extends FrameLayout 正常的一个FragmentLayout 如下举例几个简单方法
加载配置 protected String getDefaultLayout() {//wangfangchen add /*final int defaultResource QuickStepContract.isGesturalMode(mNavBarMode)? R.string.config_navBarLayoutHandle: mOverviewProxyService.shouldShowSwipeUpUI()? R.string.config_navBarLayoutQuickstep: R.string.config_navBarLayout;*/final int defaultResource R.string.config_navBarLayout;Log.d(TAG,getDefaultLayout getContext().getString(defaultResource));//wangfangchen end return getContext().getString(defaultResource);}所以我们需要新增功能按键就需要在配置 文件中添加功能按键power
string nameconfig_navBarLayout translatablefalseleft;volume_sub,back,home,recent,wb_sunny,volume_add,power,screenshot;right/string
加载子View
Overrideprotected void onFinishInflate() {super.onFinishInflate();inflateChildren();clearViews();inflateLayout(getDefaultLayout());}protected void inflateLayout(String newLayout) {mCurrentLayout newLayout;if (newLayout null) {newLayout getDefaultLayout();}String[] sets newLayout.split(GRAVITY_SEPARATOR, 3);Log.d(TAG, inflateLayout newLayout:newLayout);if (sets.length ! 3) {Log.d(TAG, Invalid layout.);newLayout getDefaultLayout();sets newLayout.split(GRAVITY_SEPARATOR, 3);}String[] start sets[0].split(BUTTON_SEPARATOR);String[] center sets[1].split(BUTTON_SEPARATOR);String[] end sets[2].split(BUTTON_SEPARATOR);// Inflate these in start to end order or accessibility traversal will be messed up.inflateButtons(start, mHorizontal.findViewById(R.id.ends_group),false /* landscape */, true /* start */);inflateButtons(start, mVertical.findViewById(R.id.ends_group),true /* landscape */, true /* start */);inflateButtons(center, mHorizontal.findViewById(R.id.center_group),false /* landscape */, false /* start */);inflateButtons(center, mVertical.findViewById(R.id.center_group),true /* landscape */, false /* start */);addGravitySpacer(mHorizontal.findViewById(R.id.ends_group));addGravitySpacer(mVertical.findViewById(R.id.ends_group));inflateButtons(end, mHorizontal.findViewById(R.id.ends_group),false /* landscape */, false /* start */);inflateButtons(end, mVertical.findViewById(R.id.ends_group),true /* landscape */, false /* start */);updateButtonDispatchersCurrentView();}private void inflateButtons(String[] buttons, ViewGroup parent, boolean landscape,boolean start) {for (int i 0; i buttons.length; i) {Log.d(TAG,inflateButtons buttons[i]:buttons[i] landscape:landscape start:start);inflateButton(buttons[i], parent, landscape, start);}}创建 子view:createView
Nullableprotected View inflateButton(String buttonSpec, ViewGroup parent, boolean landscape,boolean start) {LayoutInflater inflater landscape ? mLandscapeInflater : mLayoutInflater;View v createView(buttonSpec, parent, inflater);if (v null) return null;v applySize(v, buttonSpec, landscape, start);parent.addView(v);addToDispatchers(v);View lastView landscape ? mLastLandscape : mLastPortrait;View accessibilityView v;if (v instanceof ReverseRelativeLayout) {accessibilityView ((ReverseRelativeLayout) v).getChildAt(0);}if (lastView ! null) {accessibilityView.setAccessibilityTraversalAfter(lastView.getId());}if (landscape) {mLastLandscape accessibilityView;} else {mLastPortrait accessibilityView;}return v;}
根据配置中的功能按键 名字字符串加载对应的布局也就是加载了view 到 NavigationBarView
View createView(String buttonSpec, ViewGroup parent, LayoutInflater inflater) {Log.d(TAG,createView buttonSpec:buttonSpec);View v null;String button extractButton(buttonSpec);if (LEFT.equals(button)) {button extractButton(NAVSPACE);} else if (RIGHT.equals(button)) {button extractButton(MENU_IME_ROTATE);}if (HOME.equals(button)) {v inflater.inflate(R.layout.home, parent, false);} else if (BACK.equals(button)) {v inflater.inflate(R.layout.back, parent, false);} else if (RECENT.equals(button)) {v inflater.inflate(R.layout.recent_apps, parent, false);} else if (MENU_IME_ROTATE.equals(button)) {v inflater.inflate(R.layout.menu_ime, parent, false);} else if (NAVSPACE.equals(button)) {v inflater.inflate(R.layout.nav_key_space, parent, false);} else if (CLIPBOARD.equals(button)) {v inflater.inflate(R.layout.clipboard, parent, false);} else if (CONTEXTUAL.equals(button)) {v inflater.inflate(R.layout.contextual, parent, false);} else if (HOME_HANDLE.equals(button)) {v inflater.inflate(R.layout.home_handle, parent, false);} else if (IME_SWITCHER.equals(button)) {v inflater.inflate(R.layout.ime_switcher, parent, false);//huanghb add} else if (VOLUME_ADD.equals(button)) {v inflater.inflate(R.layout.volume_add, parent, false);} else if (VOLUME_SUB.equals(button)) {v inflater.inflate(R.layout.volume_sub, parent, false);} else if (SCREENSHOT.equals(button)) {v inflater.inflate(R.layout.screenshot, parent, false);} //wangfangchen add else if (POWER.equals(button)) {v inflater.inflate(R.layout.power, parent, false);} //wangfangchen end else if (WB_SUNNY.equals(button)) {v inflater.inflate(R.layout.wb_sunny, parent, false);} else if (button.startsWith(KEY)) {Log.d(TAG,createView buttonSpec:buttonSpec button:button KEY:KEY);String uri extractImage(button);int code extractKeycode(button);v inflater.inflate(R.layout.custom_key, parent, false);((KeyButtonView) v).setCode(code);if (uri ! null) {if (uri.contains(:)) {((KeyButtonView) v).loadAsync(Icon.createWithContentUri(uri));} else if (uri.contains(/)) {int index uri.indexOf(/);String pkg uri.substring(0, index);int id Integer.parseInt(uri.substring(index 1));((KeyButtonView) v).loadAsync(Icon.createWithResource(pkg, id));}}}return v;}
加载布局View NavigationBarInflaterView
上面已经分析了NavigationBarInflaterView 如何加载子功能按键那么这个View 是在哪里已经并初始化呢 看布局navigation_bar.xm ?xml version1.0 encodingutf-8?
com.android.systemui.navigationbar.NavigationBarViewxmlns:androidhttp://schemas.android.com/apk/res/androidandroid:idid/navigation_bar_viewandroid:layout_heightmatch_parentandroid:layout_widthmatch_parentandroid:clipChildrenfalseandroid:clipToPaddingfalseandroid:backgrounddrawable/system_bar_backgroundcom.android.systemui.navigationbar.NavigationBarInflaterViewandroid:idid/navigation_inflaterandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:clipChildrenfalseandroid:clipToPaddingfalse //com.android.systemui.navigationbar.NavigationBarView找navigation_bar.xml 加载地方 1NavigationBar.java oreateView 方法
备注NavigationBar 就暂时不分析了可以参考其它博客或自己的System UI加载流程。
NavigationBarView View的封装
上面分析 NavigationBarView 嵌套了 NavigationBarInflaterView也就是对NavigationBarInflaterView 的一层封装
private final SparseArrayButtonDispatcher mButtonDispatchers new SparseArray();
放置view 到数组//huanghb addmButtonDispatchers.put(R.id.volume_add, new ButtonDispatcher(R.id.volume_add));mButtonDispatchers.put(R.id.volume_sub, new ButtonDispatcher(R.id.volume_sub));mButtonDispatchers.put(R.id.screenshot, new ButtonDispatcher(R.id.screenshot));mButtonDispatchers.put(R.id.wb_sunny, new ButtonDispatcher(R.id.wb_sunny));//huanghb end//wangfangchen add mButtonDispatchers.put(R.id.power, new ButtonDispatcher(R.id.power));//wangfangchen end
从通过view 数组获取子view return mButtonDispatchers.get(R.id.recent_apps);}public ButtonDispatcher getBackButton() {return mButtonDispatchers.get(R.id.back);}public ButtonDispatcher getHomeButton() {return mButtonDispatchers.get(R.id.home);}public ButtonDispatcher getImeSwitchButton() {return mButtonDispatchers.get(R.id.ime_switcher);}public ButtonDispatcher getAccessibilityButton() {return mButtonDispatchers.get(R.id.accessibility_button);}这不就是对子菜单功能按键的一层封装吗
子布局显示并控制NavigationBar
在上面已经通过分析了布局反向关联了NavigationBarInflaterView 加载-NavigationBar 加载。就从这个角度来分析布局显示出来后如何控制。
看部分相关方法并分析
准备View prepareNavigationBarView() private void prepareNavigationBarView() {Log.d(TAG,prepareNavigationBarView);mNavigationBarView.reorient();ButtonDispatcher recentsButton mNavigationBarView.getRecentsButton();recentsButton.setOnClickListener(this::onRecentsClick);recentsButton.setOnTouchListener(this::onRecentsTouch);ButtonDispatcher homeButton mNavigationBarView.getHomeButton();homeButton.setOnTouchListener(this::onHomeTouch);reconfigureHomeLongClick();ButtonDispatcher accessibilityButton mNavigationBarView.getAccessibilityButton();accessibilityButton.setOnClickListener(this::onAccessibilityClick);accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick);updateAccessibilityServicesState(mAccessibilityManager);ButtonDispatcher imeSwitcherButton mNavigationBarView.getImeSwitchButton();imeSwitcherButton.setOnClickListener(this::onImeSwitcherClick);updateScreenPinningGestures();//huanghb add//Log.d(huanghb,prepareNavigationBarView);ShowVolumeButton();ShowScreenShotButton();ShowWbSunnyButton();//huanghb end//wangfangchen add ShowPowerButton();//wangfangchen end }设置点击事件 长按事件
//wangfangchen add private void ShowPowerButton(){Log.d(TAG,ShowPowerButton);ButtonDispatcher powerButton mNavigationBarView.getPowerButton();// String customScreenshot SystemProperties.get(persist.fise.screenshot.icon,0);powerButton.setOnClickListener(this::onPowerClick);//powerButton.setOnTouchListener(this::onScreenShotTouch);powerButton.setOnLongClickListener(this::onPowerLongClick);powerButton.setVisibility(View.VISIBLE); }//wangfangchen end //wangfangchen add private void onPowerClick(View v) {Log.d(TAG,onPowerClick);mHandler.removeCallbacks(mPower);mHandler.postDelayed(mPower , 200);}private boolean onPowerLongClick(View v) {Log.d(TAG,onPowerLongClick);setActionNavigationbar();mHandler.removeCallbacks(mPowerReboot);mHandler.postDelayed(mPowerReboot, 200);return true;}//wangfangchen end
在对应的线程里面执行逻辑即可
总结
上面分析就很明朗了需要搞清楚 1功能按键 布局如何加载 2配置 功能菜单 如何配置 2三个类NavigationBarView NavigationBar NavigationBarInflaterView 联系