公司网站高端,河北邯郸封闭最新消息,可以和WordPress连接的应用,百宝图建设工程电子网站这是我入职的第一个BUG#xff0c;头疼#xff0c;隔壁实习生一周解决了#xff0c;我多花了几天
其中最大的原因就是我思考复杂了#xff0c;在公司系统上#xff0c;此BUG标题为#xff1a;
请确认Wifi优先级#xff0c;状态栏Wifi被忽略
BUG意思就是#xff1a;当…这是我入职的第一个BUG头疼隔壁实习生一周解决了我多花了几天
其中最大的原因就是我思考复杂了在公司系统上此BUG标题为
请确认Wifi优先级状态栏Wifi被忽略
BUG意思就是当前安卓系统状态栏图标有显示尺寸的测量如果比如需要显示8个图标已经在状态栏绘制不下则显示一个点表示省略而不希望wifi被省略
我思考了一下一直以为就是优先级问题是不是Android底层状态栏有各个图标优先级图标过多的时候优先级高的就不会被隐藏而其实最后参考了公司以前相关BUG的修改其实只是状态栏的图标大小修改即可将图标改小状态栏就可以多一个显示图标Wifi就不会被隐藏。点向后一个图标挪了一位
在尺寸文件中进行修改对这两个尺寸进行改小可以调一下刷机看一下 dimen namestatus_bar_icon_size14dip/dimendimen namestatus_bar_system_icon_size11.5dp/dimen
值得一提的是上面的逻辑超出的图标隐藏、绘制、测量相关的Java类是StatusIconContainer.Java虽然和BUG不在这改记录一下
/*** StatusIconContainer 是 StatusBarMobileView 内部的一个自定义视图容器用于管理状态图标的显示。* 它负责在 StatusBarMobileView 中管理状态图标的布局和可见性。*/
public class StatusIconContainer extends AlphaOptimizedLinearLayout {//TAG private static final String TAG StatusIconContainer;//是否打开DEBUG模式会Log相关信息private static final boolean DEBUG false;//是否打开DEBUG_OVERFLOW会在状态栏绘制边框用来显示区域什么的private static final boolean DEBUG_OVERFLOW false;// 最多可以显示 8 个状态图标包括电池图标private static final int MAX_ICONS 7;// private static final int MAX_ICONS 8;//点的个数 private static final int MAX_DOTS 1;//Dot 点 Icon图标 相关属性private int mDotPadding;private int mIconSpacing;private int mStaticDotDiameter;private int mUnderflowWidth;private int mUnderflowStart 0;// 是否可以在溢出空间中绘制private boolean mNeedsUnderflow;// 单个 StatusBarIconView 的点图标在此宽度内居中显示private int mIconDotFrameWidth;private boolean mShouldRestrictIcons true;// 用于计算哪些状态要在布局期间可见private ArrayListStatusIconState mLayoutStates new ArrayList();// 为了正确计数和测量private ArrayListView mMeasureViews new ArrayList();// 任何被忽略的图标将不会被添加为子视图private ArrayListString mIgnoredSlots new ArrayList();/*** 创建 StatusIconContainer 的构造函数。** param context Android 上下文对象*/public StatusIconContainer(Context context) {this(context, null);}/*** 创建 StatusIconContainer 的构造函数。** param context Android 上下文对象* param attrs 属性集*/public StatusIconContainer(Context context, AttributeSet attrs) {super(context, attrs);initDimens();setWillNotDraw(!DEBUG_OVERFLOW);}Overrideprotected void onFinishInflate() {super.onFinishInflate();}/*** 设置是否限制状态图标的显示。** param should 是否应该限制状态图标的显示*/public void setShouldRestrictIcons(boolean should) {mShouldRestrictIcons should;}/*** 检查是否正在限制状态图标的显示。** return 如果正在限制状态图标的显示则返回 true否则返回 false。*/public boolean isRestrictingIcons() {return mShouldRestrictIcons;}/*** 初始化尺寸参数。*/private void initDimens() {// 这是与 StatusBarIconView 使用相同的值mIconDotFrameWidth getResources().getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);mDotPadding getResources().getDimensionPixelSize(R.dimen.overflow_icon_dot_padding);mIconSpacing getResources().getDimensionPixelSize(R.dimen.status_bar_system_icon_spacing);// 点图标int radius getResources().getDimensionPixelSize(R.dimen.overflow_dot_radius);// 计算点的直径 R.dimen.overflow_dot_radius 2dpmStaticDotDiameter 2 * radius;// 不能超过宽度 mIconDotFrameWidth 图标宽度 最大图标个数-1可能还有个点所以-1 每个宽高mUnderflowWidth mIconDotFrameWidth (MAX_DOTS - 1) * (mStaticDotDiameter mDotPadding);android.util.Log.d(TAG, initDimens: mUnderflowStart);}Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {float midY getHeight() / 2.0f;// 首先对所有子视图进行布局以便稍后移动它们for (int i 0; i getChildCount(); i) {View child getChildAt(i);int width child.getMeasuredWidth();int height child.getMeasuredHeight();int top (int) (midY - height / 2.0f);child.layout(0, top, width, top height);}resetViewStates();calculateIconTranslations();applyIconStates();}
//绘制Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (DEBUG_OVERFLOW) {//如果开启了DEBUG_OVERFLOW模式画框框Paint paint new Paint();paint.setStyle(Style.STROKE);paint.setColor(Color.RED);// 显示边界框canvas.drawRect(getPaddingStart(), 0, getWidth() - getPaddingEnd(), getHeight(), paint);// 显示溢出框paint.setColor(Color.GREEN);canvas.drawRect(mUnderflowStart, 0, mUnderflowStart mUnderflowWidth, getHeight(), paint);}}//测量Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {mMeasureViews.clear();int mode MeasureSpec.getMode(widthMeasureSpec);final int width MeasureSpec.getSize(widthMeasureSpec);final int count getChildCount();// 收集所有希望进行布局的视图for (int i 0; i count; i) {// 获取子视图StatusIconDisplayable icon (StatusIconDisplayable) getChildAt(i);// 如果视图可见且没有被阻止则加入可见视图列表if (icon.isIconVisible() !icon.isIconBlocked() !mIgnoredSlots.contains(icon.getSlot())) {mMeasureViews.add((View) icon);}}// 可见视图数量int visibleCount mMeasureViews.size();int maxVisible visibleCount MAX_ICONS ? MAX_ICONS : MAX_ICONS - 1;int totalWidth mPaddingLeft mPaddingRight;boolean trackWidth true;// 测量所有子视图以便它们报告正确的宽度int childWidthSpec MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);mNeedsUnderflow mShouldRestrictIcons visibleCount MAX_ICONS;for (int i 0; i visibleCount; i) {View child mMeasureViews.get(i);measureChild(child, childWidthSpec, heightMeasureSpec);int spacing i visibleCount - 1 ? 0 : mIconSpacing;if (mShouldRestrictIcons) {if (i maxVisible trackWidth) {totalWidth getViewTotalMeasuredWidth(child) spacing;} else if (trackWidth) {// 达到图标限制为点图标添加空间totalWidth mUnderflowWidth;trackWidth false;}} else {totalWidth getViewTotalMeasuredWidth(child) spacing;}}if (mode MeasureSpec.EXACTLY) {if (!mNeedsUnderflow totalWidth width) {mNeedsUnderflow true;}setMeasuredDimension(width, MeasureSpec.getSize(heightMeasureSpec));} else {if (mode MeasureSpec.AT_MOST totalWidth width) {mNeedsUnderflow true;totalWidth width;}setMeasuredDimension(totalWidth, MeasureSpec.getSize(heightMeasureSpec));}}Overridepublic void onViewAdded(View child) {super.onViewAdded(child);StatusIconState vs new StatusIconState();vs.justAdded true;child.setTag(R.id.status_bar_view_state_tag, vs);}Overridepublic void onViewRemoved(View child) {super.onViewRemoved(child);child.setTag(R.id.status_bar_view_state_tag, null);}/*** 添加要忽略的图标槽的名称。它将不会显示在布局中也不会被测量。** param slotName 图标的名称就像在 frameworks/base/core/res/res/values/config.xml 中定义的那样*/public void addIgnoredSlot(String slotName) {android.util.Log.d(TAG, addIgnoredSlot: slotName);boolean added addIgnoredSlotInternal(slotName);if (added) {requestLayout();}}/*** 添加要忽略的图标槽的名称的列表。** param slots 要忽略的图标的名称列表*/public void addIgnoredSlots(ListString slots) {for (String slot : slots) {android.util.Log.d(TAG, addIgnoredSlots: slot);}boolean willAddAny false;for (String slot : slots) {willAddAny | addIgnoredSlotInternal(slot);}if (willAddAny) {requestLayout();}}/*** 内部添加要忽略的图标槽名称。** param slotName 图标的名称就像在 frameworks/base/core/res/res/values/config.xml 中定义的那样* return 如果成功添加则返回 true否则返回 false*/private boolean addIgnoredSlotInternal(String slotName) {android.util.Log.d(TAG, addIgnoredSlotInternal: slotName);if (mIgnoredSlots.contains(slotName)) {return false;}mIgnoredSlots.add(slotName);return true;}/*** 从忽略的图标槽中移除一个名称。** param slotName 要移除的图标槽的名称*/public void removeIgnoredSlot(String slotName) {android.util.Log.d(TAG, removeIgnoredSlot: slotName);boolean removed mIgnoredSlots.remove(slotName);if (removed) {requestLayout();}}/*** 从忽略的图标槽中移除名称的列表。** param slots 要移除的图标槽的名称列表*/public void removeIgnoredSlots(ListString slots) {for (String slot: slots) {android.util.Log.d(TAG, removeIgnoredSlot: slot);}boolean removedAny false;for (String slot : slots) {removedAny | mIgnoredSlots.remove(slot);}if (removedAny) {requestLayout();}}/*** 设置要忽略的图标槽的列表清除当前的列表。** param slots 要忽略的图标槽的名称列表*/public void setIgnoredSlots(ListString slots) {mIgnoredSlots.clear();addIgnoredSlots(slots);}/*** 返回与特定槽名称相对应的视图。* 仅用于操作它如何呈现。** param slot 槽名称与 com.android.internal.R.config_statusBarIcons 中定义的名称相对应* return 如果此容器拥有相应的视图则返回该视图否则返回 null*/public View getViewForSlot(String slot) {for (int i 0; i getChildCount(); i) {View child getChildAt(i);if (child instanceof StatusIconDisplayable ((StatusIconDisplayable) child).getSlot().equals(slot)) {return child;}}return null;}/*** 布局从右到左发生。*/private void calculateIconTranslations() {mLayoutStates.clear();float width getWidth();float translationX width - getPaddingEnd();float contentStart getPaddingStart();int childCount getChildCount();// Underflow 不显示内容直到此索引if (DEBUG) Log.d(TAG, calculateIconTranslations: start translationX width width underflow mNeedsUnderflow);// 收集所有希望可见的状态for (int i childCount - 1; i 0; i--) {View child getChildAt(i);StatusIconDisplayable iconView (StatusIconDisplayable) child;StatusIconState childState getViewStateFromChild(child);if (!iconView.isIconVisible() || iconView.isIconBlocked()|| mIgnoredSlots.contains(iconView.getSlot())) {childState.visibleState STATE_HIDDEN;if (DEBUG) Log.d(TAG, skipping child ( iconView.getSlot() ) not visible);continue;}// 移动 translationX 到布局的位置以添加视图而不截断子视图translationX - getViewTotalWidth(child);childState.visibleState STATE_ICON;childState.xTranslation translationX;mLayoutStates.add(0, childState);// 为下一个视图移动 translationX 以腾出间隔translationX - mIconSpacing;}// 显示 1 至 MAX_ICONS 个图标或 (MAX_ICONS - 1) 个图标 溢出int totalVisible mLayoutStates.size();int maxVisible totalVisible MAX_ICONS ? MAX_ICONS : MAX_ICONS - 1;mUnderflowStart 0;int visible 0;int firstUnderflowIndex -1;for (int i totalVisible - 1; i 0; i--) {StatusIconState state mLayoutStates.get(i);// 如果在测量时发现需要溢出则允许在此之前腾出空间if (mNeedsUnderflow (state.xTranslation (contentStart mUnderflowWidth)) ||(mShouldRestrictIcons visible maxVisible)) {firstUnderflowIndex i;break;}mUnderflowStart (int) Math.max(contentStart, state.xTranslation - mUnderflowWidth - mIconSpacing);visible;}//开始判断是否超出 超出则画点if (firstUnderflowIndex ! -1) {int totalDots 0;int dotWidth mStaticDotDiameter mDotPadding;int dotOffset mUnderflowStart mUnderflowWidth - mIconDotFrameWidth;for (int i firstUnderflowIndex; i 0; i--) {StatusIconState state mLayoutStates.get(i);if (totalDots MAX_DOTS) {state.xTranslation dotOffset;state.visibleState STATE_DOT;dotOffset - dotWidth;totalDots;} else {state.visibleState STATE_HIDDEN;}}}// 从 NotificationIconContainer 中拿来的不是最优解但保持布局逻辑简洁if (isLayoutRtl()) {for (int i 0; i childCount; i) {View child getChildAt(i);StatusIconState state getViewStateFromChild(child);state.xTranslation width - state.xTranslation - child.getWidth();}}}private void applyIconStates() {for (int i 0; i getChildCount(); i) {View child getChildAt(i);StatusIconState vs getViewStateFromChild(child);if (vs ! null) {vs.applyToView(child);}}}private void resetViewStates() {for (int i 0; i getChildCount(); i) {View child getChildAt(i);StatusIconState vs getViewStateFromChild(child);if (vs null) {continue;}vs.initFrom(child);vs.alpha 1.0f;vs.hidden false;}}private static Nullable StatusIconState getViewStateFromChild(View child) {return (StatusIconState) child.getTag(R.id.status_bar_view_state_tag);}private static int getViewTotalMeasuredWidth(View child) {return child.getMeasuredWidth() child.getPaddingStart() child.getPaddingEnd();}private static int getViewTotalWidth(View child) {return child.getWidth() child.getPaddingStart() child.getPaddingEnd();}public static class StatusIconState extends ViewState {/// StatusBarIconView.STATE_*public int visibleState STATE_ICON;public boolean justAdded true;// 从视图末尾的距离是最相关的用于动画float distanceToViewEnd -1;Overridepublic void applyToView(View view) {float parentWidth 0;if (view.getParent() instanceof View) {parentWidth ((View) view.getParent()).getWidth();}float currentDistanceToEnd parentWidth - xTranslation;if (!(view instanceof StatusIconDisplayable)) {return;}StatusIconDisplayable icon (StatusIconDisplayable) view;AnimationProperties animationProperties null;boolean animateVisibility true;// 用于计算哪些状态在布局过程中是可见的找出哪些属性的状态转换(如果有的话)我们需要动画// 确定要动画的状态转换的属性如果有if (justAdded|| icon.getVisibleState() STATE_HIDDEN visibleState STATE_ICON) {// 图标正在出现通过将其放在它将出现的位置并动画 alpha 来淡入它super.applyToView(view);view.setAlpha(0.f);icon.setVisibleState(STATE_HIDDEN);animationProperties ADD_ICON_PROPERTIES;} else if (icon.getVisibleState() ! visibleState) {if (icon.getVisibleState() STATE_ICON visibleState STATE_HIDDEN) {// 消失不要执行任何复杂的操作animateVisibility false;} else {// 所有其他转换到/从点等animationProperties ANIMATE_ALL_PROPERTIES;}} else if (visibleState ! STATE_HIDDEN distanceToViewEnd ! currentDistanceToEnd) {// 可见性不在发生变化只需动画位置animationProperties X_ANIMATION_PROPERTIES;}icon.setVisibleState(visibleState, animateVisibility);if (animationProperties ! null) {view.animate().cancel();icon.addTransformationToViewGroup(view, animationProperties, null);}icon.applyInShelfTransformation(view, this, animationProperties, animationProperties);}}
}