SystemUI下的快速设置面板显示异常
来源:互联网 发布:虚拟网络映射 编辑:程序博客网 时间:2024/06/10 01:36
前言:坚持自己能坚持的,成为自己想成为的,相信时间的累积是有效果的。
Step1复现
这个bug困扰了快一周了,今天终于突然来了灵感解决掉了,记录之。
测试:
General description: The notification bar display incorrect when edit quick settings. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Reproducibility: 10/10 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Precondition: Turn on auto-rotate - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Step: 1.Homescreen->Settings->Display->Rotate dut to landscape mode->View->Display size->Change size then change to default size->Back to home screen->Rotate dut to portrait mode->Pull down notification bar->EDIT 2.Check the screen display. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Actual result: The notification bar display incorrect when edit quick settings. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Expect result: The notification bar display correct when edit quick settings.
效果图如下:
Step2知识回顾
**A、横竖屏:**
通过这个bug的复现流程,横屏模式下设置 displaySize ,嗯,涉及到android横竖屏切换方面的知识,这方面的知识很薄弱,于是一边解bug一边网上查资料。感谢roserose0002,Cynthia&Sky二位的精彩分析,下面我结合他们的博客做个自己的理解和学习。
当我们在清单文件中不添加关于横竖屏的配置信息时,横竖屏切换时会有一个Activity的销毁和重新创建的过程,一般的项目都会通过在清单文件中配置相关的信息通过执行onConfigureChanged方法来做一些处理。
即:
<uses-permission Android:name="android.permission.CHANGE_CONFIGURATION"></uses-permission>
允许改变配置信息,系统允许我们通过重写activity中的onConfigurationChanged方法来捕获和修改某些配置信息。
另外在我们想配置的相关的Activity需要添加一个节点
<activity android:name=".recents.RecentsActivity" android:label="@string/accessibility_desc_recent_apps" android:exported="false" android:launchMode="singleInstance" android:excludeFromRecents="true" android:stateNotNeeded="true" android:resumeWhilePausing="true" android:screenOrientation="behind" android:resizeableActivity="true" android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout" android:theme="@style/RecentsTheme.Wallpaper"> <intent-filter> <action android:name="com.android.systemui.recents.TOGGLE_RECENTS" /> </intent-filter> </activity>
它规定了可以再程序中捕获的事件类型。实际上它有这些字段
修改字体时会调用fontScale,修改display size会调用densityDpi。
B、页面和源代码的对应(MTK)
这个不是什么干货,相当于自己加深印象了,
a、在SystemUI下的qs文件夹下,QSPanel.java(View that represents the quick settings tile panel)
/** View that represents the quick settings tile panel. **/public class QSPanel extends LinearLayout implements Tunable, Callback {......public QSPanel(Context context) { this(context, null); } public QSPanel(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; setOrientation(VERTICAL); mBrightnessView = LayoutInflater.from(context).inflate( R.layout.quick_settings_brightness_dialog, this, false); addView(mBrightnessView); mQuickSettingsPlugin = PluginManager.getQuickSettingsPlugin(mContext); mQuickSettingsPlugin.addOpViews(this); setupTileLayout(); mFooter = new QSFooter(this, context); addView(mFooter.getView()); updateResources(); mBrightnessController = new BrightnessController(getContext(), (ImageView) findViewById(R.id.brightness_icon), (ToggleSlider) findViewById(R.id.brightness_slider)); }......}
再看看哪里调用了这个控件,在Qs_panel.xml
<com.android.systemui.qs.QSContainer xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/quick_settings_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/qs_background_primary" android:clipToPadding="false" android:clipChildren="false" android:elevation="4dp"> <com.android.systemui.qs.QSPanel android:id="@+id/quick_settings_panel" android:background="#0000" android:layout_marginTop="@dimen/status_bar_header_height" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="8dp" /> <include layout="@layout/quick_status_bar_expanded_header" /> <include android:id="@+id/qs_detail" layout="@layout/qs_detail" /> <include android:id="@+id/qs_customize" layout="@layout/qs_customize_panel" android:visibility="gone" /></com.android.systemui.qs.QSContainer>
QSPanel属于QSContainer的子控件。效果图是这样的:
QSPanel,点击edit
mEditText = (TextView) findViewById(android.R.id.edit); mEditText.setOnClickListener(view -> mHost.startRunnableDismissingKeyguard(() -> showEdit(view)));private void showEdit(final View v) { v.post(new Runnable() { @Override public void run() { if (mCustomizePanel != null) { if (!mCustomizePanel.isCustomizing()) { int[] loc = new int[2]; v.getLocationInWindow(loc); int x = loc[0]; int y = loc[1]; mCustomizePanel.show(x, y); } } } }); }
执行mCustomizePanel.show(x, y);方法,这个类的描述是
/** * Allows full-screen customization of QS, through show() and hide(). * * This adds itself to the status bar window, so it can appear on top of quick settings and * *someday* do fancy animations to get into/out of it.
show 或者 hide详情,是不是这个类的configuration变化,导致quicksetting显示异常
protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); View navBackdrop = findViewById(R.id.nav_bar_background); if (navBackdrop != null) { boolean shouldShow = newConfig.smallestScreenWidthDp >= 600 || newConfig.orientation != Configuration.ORIENTATION_LANDSCAPE; navBackdrop.setVisibility(shouldShow ? View.VISIBLE : View.GONE); } }
事实上QSCustomizer.java的这个方法比较简单,就是在实现父类的同时加上了自己navBackdrop 视图。
在这里里面我尝试reloadwitdth是没用的
private void reloadWidth(View view) { LayoutParams params = (LayoutParams) view.getLayoutParams(); params.width = getContext().getResources().getDimensionPixelSize( R.dimen.notification_panel_width); view.setLayoutParams(params); }
Step3 找源头
偶然发现了这个类
/** * Custom {@link FrameLayout} that re-inflates when changes to {@link Configuration} happen. * Currently supports changes to density and locale. */public class AutoReinflateContainer extends FrameLayout {...... @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); boolean shouldInflateLayout = false; final int density = newConfig.densityDpi; if (density != mDensity) { mDensity = density; shouldInflateLayout = true; } final LocaleList localeList = newConfig.getLocales(); if (localeList != mLocaleList) { mLocaleList = localeList; shouldInflateLayout = true; } if (shouldInflateLayout) { inflateLayout(); } } private void inflateLayout() { removeAllViews(); LayoutInflater.from(getContext()).inflate(mLayout, this); final int N = mInflateListeners.size(); for (int i = 0; i < N; i++) { mInflateListeners.get(i).onInflated(getChildAt(0)); } }......}
当density 和locale变化时会重新加载view,所以我强行的去掉if,只要配置信息变化就加在view,这个是治标不治本的。
// if (shouldInflateLayout) { inflateLayout(); // }
至于为什么横屏切换时导致计算错误还要进一步找原因。
最终的图是这样的
谢谢。
- SystemUI下的快速设置面板显示异常
- Android 4.4 SystemUI 的面板quicksettings删除
- SystemUI下的RecentActivity
- SystemUI快速生效的办法
- 按照控制面板区域设置显示时间的格式函数
- PL/SQL Developer设置要显示的面板布局
- android N systemUI的VOLTE图标显示
- Ubuntu下Java Swing程序显示空的面板
- osg全屏下的输入法面板显示问题
- Android 设置状态栏 显示 或 隐藏 SystemUI flag
- ubuntu16.04下xfce4下快速显示桌面的快捷键设置
- 添加/删除程序空白窗口及控制面板窗口显示异常问题的解决方法
- Android 7.0 SystemUI之快速启动栏的分析
- SystemUi音量显示笔记
- android4.4 systemUI设置
- SystemUI源码分析四(QSPanel显示的流程)
- 关于SystemUI状态栏显示黄色背景的问题
- 控制面板命令,设置控制面板快捷键的方法
- Spark1.6.3 Driver端 task运行完成源码分析
- R语言相关分析
- Java出现No enclosing instance of type E is accessible. Must qualify the allocation with an enclosing
- Android N 来电流程(MT)
- 放苹果
- SystemUI下的快速设置面板显示异常
- 量化分析师的Python日记【Q Quant兵器谱之偏微分方程3的具体金融学运用】
- git
- HTM-16.2代码(1)——编码端一些函数的说明
- 确定主题域
- 汽车权威网站
- Webapp中1px边框在retina屏中变粗的问题
- EXCEL疑难记录
- Java反射机制——学习总结