Prior to this cl, we checked the app bounds for deciding app in two pane or not. However, this might be broken in some certain sceanrios. Currently, api will check the entire task bounds. If the width of task bounds is larger than two pane criteria, then we treat it as in two pane mode. Test: Highlighted behavior works correct. Fix: 203763572 Change-Id: Ib14851b1e3e097328874c7956bb653f50820f877
242 lines
8.5 KiB
Java
242 lines
8.5 KiB
Java
/*
|
|
* Copyright (C) 2021 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.settings.widget;
|
|
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.text.TextUtils;
|
|
import android.util.Log;
|
|
import android.util.TypedValue;
|
|
import android.view.View;
|
|
import android.widget.ImageView;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.annotation.VisibleForTesting;
|
|
import androidx.preference.PreferenceGroup;
|
|
import androidx.preference.PreferenceGroupAdapter;
|
|
import androidx.preference.PreferenceViewHolder;
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
import com.android.settings.Utils;
|
|
import com.android.settings.activityembedding.ActivityEmbeddingUtils;
|
|
|
|
/**
|
|
* Adapter for highlighting top level preferences
|
|
*/
|
|
public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapter {
|
|
|
|
private static final String TAG = "HighlightableTopLevelAdapter";
|
|
|
|
static final long DELAY_HIGHLIGHT_DURATION_MILLIS = 100L;
|
|
|
|
@VisibleForTesting
|
|
final int mHighlightColor;
|
|
final int mTitleColorNormal;
|
|
final int mTitleColorHighlight;
|
|
final int mSummaryColorNormal;
|
|
final int mSummaryColorHighlight;
|
|
final int mIconColorNormal;
|
|
final int mIconColorHighlight;
|
|
|
|
private final Context mContext;
|
|
private final Activity mActivity;
|
|
private final RecyclerView mRecyclerView;
|
|
private final int mNormalBackgroundRes;
|
|
private String mHighlightKey;
|
|
private String mPreviousHighlightKey;
|
|
private int mHighlightPosition = RecyclerView.NO_POSITION;
|
|
private boolean mHighlightNeeded;
|
|
private boolean mScrolled;
|
|
|
|
public HighlightableTopLevelPreferenceAdapter(Activity activity,
|
|
PreferenceGroup preferenceGroup, RecyclerView recyclerView, String key) {
|
|
super(preferenceGroup);
|
|
mRecyclerView = recyclerView;
|
|
mHighlightKey = key;
|
|
mContext = preferenceGroup.getContext();
|
|
mActivity = activity;
|
|
final TypedValue outValue = new TypedValue();
|
|
mContext.getTheme().resolveAttribute(android.R.attr.selectableItemBackground,
|
|
outValue, true /* resolveRefs */);
|
|
mNormalBackgroundRes = outValue.resourceId;
|
|
mHighlightColor = Utils.getColorAttrDefaultColor(mContext,
|
|
com.android.internal.R.attr.colorAccentSecondaryVariant);
|
|
mTitleColorNormal = Utils.getColorAttrDefaultColor(mContext,
|
|
android.R.attr.textColorPrimary);
|
|
mTitleColorHighlight = Utils.getColorAttrDefaultColor(mContext,
|
|
android.R.attr.textColorPrimaryInverse);
|
|
mSummaryColorNormal = Utils.getColorAttrDefaultColor(mContext,
|
|
android.R.attr.textColorSecondary);
|
|
mSummaryColorHighlight = Utils.getColorAttrDefaultColor(mContext,
|
|
android.R.attr.textColorSecondaryInverse);
|
|
mIconColorNormal = Utils.getHomepageIconColor(mContext);
|
|
mIconColorHighlight = Utils.getHomepageIconColorHighlight(mContext);
|
|
}
|
|
|
|
@Override
|
|
public void onBindViewHolder(PreferenceViewHolder holder, int position) {
|
|
super.onBindViewHolder(holder, position);
|
|
updateBackground(holder, position);
|
|
}
|
|
|
|
@VisibleForTesting
|
|
void updateBackground(PreferenceViewHolder holder, int position) {
|
|
if (!isHighlightNeeded()) {
|
|
removeHighlightBackground(holder);
|
|
return;
|
|
}
|
|
|
|
if (position == mHighlightPosition
|
|
&& mHighlightKey != null
|
|
&& TextUtils.equals(mHighlightKey, getItem(position).getKey())) {
|
|
// This position should be highlighted.
|
|
addHighlightBackground(holder);
|
|
} else {
|
|
removeHighlightBackground(holder);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A function can highlight a specific setting in recycler view.
|
|
*/
|
|
public void requestHighlight() {
|
|
if (mRecyclerView == null || TextUtils.isEmpty(mHighlightKey)) {
|
|
return;
|
|
}
|
|
|
|
if (TextUtils.isEmpty(mHighlightKey)) {
|
|
// De-highlight previous preference.
|
|
final int previousPosition = mHighlightPosition;
|
|
mHighlightPosition = RecyclerView.NO_POSITION;
|
|
mScrolled = true;
|
|
if (previousPosition >= 0) {
|
|
notifyItemChanged(previousPosition);
|
|
}
|
|
return;
|
|
}
|
|
|
|
final int position = getPreferenceAdapterPosition(mHighlightKey);
|
|
if (position < 0) {
|
|
return;
|
|
}
|
|
|
|
final boolean highlightNeeded = isHighlightNeeded();
|
|
if (highlightNeeded) {
|
|
scrollToPositionIfNeeded(position);
|
|
}
|
|
|
|
// Turn on/off highlight when screen split mode is changed.
|
|
if (highlightNeeded != mHighlightNeeded) {
|
|
Log.d(TAG, "Highlight change needed: " + highlightNeeded);
|
|
mHighlightNeeded = highlightNeeded;
|
|
mHighlightPosition = position;
|
|
notifyItemChanged(position);
|
|
return;
|
|
}
|
|
|
|
if (position == mHighlightPosition) {
|
|
return;
|
|
}
|
|
|
|
final int previousPosition = mHighlightPosition;
|
|
mHighlightPosition = position;
|
|
Log.d(TAG, "Request highlight position " + position);
|
|
Log.d(TAG, "Is highlight needed: " + highlightNeeded);
|
|
if (!highlightNeeded) {
|
|
return;
|
|
}
|
|
|
|
// Highlight preference.
|
|
notifyItemChanged(position);
|
|
|
|
// De-highlight previous preference.
|
|
if (previousPosition >= 0) {
|
|
notifyItemChanged(previousPosition);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A function that highlights a setting by specifying a preference key. Usually used whenever a
|
|
* preference is clicked.
|
|
*/
|
|
public void highlightPreference(String key, boolean scrollNeeded) {
|
|
mPreviousHighlightKey = mHighlightKey;
|
|
mHighlightKey = key;
|
|
mScrolled = !scrollNeeded;
|
|
requestHighlight();
|
|
}
|
|
|
|
/**
|
|
* A function that restores the previous highlighted setting.
|
|
*/
|
|
public void restorePreviousHighlight() {
|
|
mHighlightKey = mPreviousHighlightKey;
|
|
requestHighlight();
|
|
}
|
|
|
|
private void scrollToPositionIfNeeded(int position) {
|
|
if (mScrolled || position < 0) {
|
|
return;
|
|
}
|
|
|
|
// Only when the recyclerView is loaded, it can be scrolled
|
|
final View view = mRecyclerView.getChildAt(position);
|
|
if (view == null) {
|
|
mRecyclerView.postDelayed(() -> scrollToPositionIfNeeded(position),
|
|
DELAY_HIGHLIGHT_DURATION_MILLIS);
|
|
return;
|
|
}
|
|
|
|
mScrolled = true;
|
|
Log.d(TAG, "Scroll to position " + position);
|
|
// Scroll to the top to reset the position.
|
|
mRecyclerView.nestedScrollBy(0, -mRecyclerView.getHeight());
|
|
|
|
final int scrollY = view.getTop();
|
|
if (scrollY > 0) {
|
|
mRecyclerView.nestedScrollBy(0, scrollY);
|
|
}
|
|
}
|
|
|
|
private void addHighlightBackground(PreferenceViewHolder holder) {
|
|
final View v = holder.itemView;
|
|
v.setBackgroundColor(mHighlightColor);
|
|
((TextView) v.findViewById(android.R.id.title)).setTextColor(mTitleColorHighlight);
|
|
((TextView) v.findViewById(android.R.id.summary)).setTextColor(mSummaryColorHighlight);
|
|
final Drawable drawable = ((ImageView) v.findViewById(android.R.id.icon)).getDrawable();
|
|
if (drawable != null) {
|
|
drawable.setTint(mIconColorHighlight);
|
|
}
|
|
}
|
|
|
|
private void removeHighlightBackground(PreferenceViewHolder holder) {
|
|
final View v = holder.itemView;
|
|
v.setBackgroundResource(mNormalBackgroundRes);
|
|
((TextView) v.findViewById(android.R.id.title)).setTextColor(mTitleColorNormal);
|
|
((TextView) v.findViewById(android.R.id.summary)).setTextColor(mSummaryColorNormal);
|
|
final Drawable drawable = ((ImageView) v.findViewById(android.R.id.icon)).getDrawable();
|
|
if (drawable != null) {
|
|
drawable.setTint(mIconColorNormal);
|
|
}
|
|
}
|
|
|
|
private boolean isHighlightNeeded() {
|
|
return ActivityEmbeddingUtils.isTwoPaneResolution(mActivity);
|
|
}
|
|
}
|