Google如果发现有些手机厂商有比较好的功能,就会在新版本中添加进来,我觉得 这个QSCustomizer就是属于这类
QSCustomizer就是下拉状态栏中快速设置按钮,支持手机用户自己修改。
这里用了RecyclerView,RecyclerView我没怎么用过,所以很多方法都不知道,碰到了困难还是求助同事才解决
./src/com/android/systemui/qs/customize/QSCustomizer.java
本次的修改都是围绕这个类。
首先找到了布局
./res/layout/qs_customize_panel.xml
<com.android.systemui.qs.customize.QSCustomizer
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:background="@drawable/qs_customizer_background"
android:gravity="center_horizontal">
com.android.systemui.qs.customize.QSCustomizer>
我这里直接修改了background,但是运行后发现,颜色只修改了上面的一半,下面的没变,最后在代码中(adapter)发现了一个Drawable,注释一下,果然生效
./src/com/android/systemui/qs/customize/TileAdapter.java
private final SpanSizeLookup mSizeLookup = new SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
final int type = getItemViewType(position);
return type == TYPE_EDIT || type == TYPE_DIVIDER ? 5 : 1;
}
};
private class TileItemDecoration extends ItemDecoration {
// private final ColorDrawable mDrawable;
private TileItemDecoration(Context context) {
// TypedArray ta =
// context.obtainStyledAttributes(new int[]{android.R.attr.colorSecondary});
// mDrawable = new ColorDrawable(ta.getColor(0, 0));
// ta.recycle();
}
@Override
public void onDraw(Canvas c, RecyclerView parent, State state) {
super.onDraw(c, parent, state);
final int childCount = parent.getChildCount();
final int width = parent.getWidth();
final int bottom = parent.getBottom();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final ViewHolder holder = parent.getChildViewHolder(child);
if (holder.getAdapterPosition() < mEditIndex && !(child instanceof TextView)) {
continue;
}
// final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
// .getLayoutParams();
// final int top = child.getTop() + params.topMargin +
// Math.round(ViewCompat.getTranslationY(child));
// Draw full width, in case there aren't tiles all the way across.
// mDrawable.setBounds(0, top, width, bottom);
// mDrawable.draw(c);
break;
}
}
};
现在的背景色已经统一了
./src/com/android/systemui/qs/customize/QSCustomizer.java -> QSCustomizer():
// GridLayoutManager layout = new GridLayoutManager(getContext(), 3);
GridLayoutManager layout = new GridLayoutManager(getContext(), 5);
我这里是修改为5列,也是国内常见的。但是运行后发现,分割“选中”和“移除”的item,竟然不是占一整行的宽度,导致这个分割item和tileview会挤在一行。最终在同事的帮助下,才知道这这句代码的原因
./src/com/android/systemui/qs/customize/QSCustomizer.java -> QSCustomizer():
layout.setSpanSizeLookup(mTileAdapter.getSizeLookup());
于是到adapter中查看
./src/com/android/systemui/qs/customize/TileAdapter.java -> getSpanSize():
@Override
public int getSpanSize(int position) {
final int type = getItemViewType(position);
//return type == TYPE_EDIT || type == TYPE_DIVIDER ? 3 : 1;
return type == TYPE_EDIT || type == TYPE_DIVIDER ? 5 : 1;
}
这里发现了一个“3:1”,于是果断修改为“5:1”,运行后没问题了,
这里根据个人需要
./res/layout/qs_customize_panel_content.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="match_parent"
android:layout_marginTop="28dp"
android:layout_height="50dp">
<ImageView
android:id="@+id/customize_back"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="@drawable/arrow_left"
android:layout_marginLeft="20dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="50dp"
android:text="@string/qs_edit"
android:textColor="@color/quick_settings_text"/>
<TextView
android:id="@+id/customize_reset"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingRight="20dp"
android:gravity="center_vertical"
android:text="@string/reset"
android:textColor="@color/quick_settings_text"
android:layout_alignParentRight="true"
/>
RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollIndicators="top"
android:scrollbars="vertical"
android:importantForAccessibility="no" />
<View
android:id="@+id/nav_bar_background"
android:layout_width="match_parent"
android:layout_height="@dimen/navigation_bar_size"
android:layout_gravity="bottom"
android:background="#ff000000" />
merge>
./src/com/android/systemui/qs/customize/QSCustomizer.java
//public class QSCustomizer extends LinearLayout implements OnMenuItemClickListener {
public class QSCustomizer extends LinearLayout implements View.OnClickListener {
/* begin */
// mToolbar = findViewById(com.android.internal.R.id.action_bar);
// TypedValue value = new TypedValue();
// mContext.getTheme().resolveAttribute(android.R.attr.homeAsUpIndicator, value, true);
// mToolbar.setNavigationIcon(
// getResources().getDrawable(value.resourceId, mContext.getTheme()));
// mToolbar.setNavigationOnClickListener(new OnClickListener() {
// @Override
// public void onClick(View v) {
// hide((int) v.getX() + v.getWidth() / 2, (int) v.getY() + v.getHeight() / 2);
// }
// });
// mToolbar.setOnMenuItemClickListener(this);
// mToolbar.getMenu().add(Menu.NONE, MENU_RESET, 0,
// mContext.getString(com.android.internal.R.string.reset));
// mToolbar.setTitle(R.string.qs_edit);
mBack = findViewById(R.id.customize_back);
mReset = findViewById(R.id.customize_reset);
mBack.setOnClickListener(this);
mReset.setOnClickListener(this);
/* end */
public void hide(int x, int y) {
if (isShown) {
MetricsLogger.hidden(getContext(), MetricsProto.MetricsEvent.QS_EDIT);
isShown = false;
/* begin */
// mToolbar.dismissPopupMenus();
/* end */
setCustomizing(false);
save();
mClipper.animateCircularClip(mX, mY, false, mCollapseAnimationListener);
mNotifQsContainer.setCustomizerAnimating(true);
mNotifQsContainer.setCustomizerShowing(false);
announceForAccessibility(mContext.getString(
R.string.accessibility_desc_quick_settings));
Dependency.get(KeyguardMonitor.class).removeCallback(mKeyguardCallback);
updateNavColors();
}
}
/* begin */
/*@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case MENU_RESET:
MetricsLogger.action(getContext(), MetricsProto.MetricsEvent.ACTION_QS_EDIT_RESET);
reset();
break;
}
return false;
}*/
/* end */
/* begin */
@Override
public void onClick(View v) {
if (v.getId() == R.id.customize_back) {
hide(0, 0);
} else if (v.getId() == R.id.customize_reset) {
reset();
}
}
/* end */
结束