1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.car.settings.common; 18 19 import android.content.Context; 20 import android.util.TypedValue; 21 import android.view.View; 22 23 import androidx.annotation.DrawableRes; 24 import androidx.preference.PreferenceGroup; 25 import androidx.preference.PreferenceGroupAdapter; 26 import androidx.preference.PreferenceViewHolder; 27 import androidx.recyclerview.widget.RecyclerView; 28 29 import com.android.car.settings.R; 30 31 /** RecyclerView adapter that supports single-preference highlighting. */ 32 public class HighlightablePreferenceGroupAdapter extends PreferenceGroupAdapter { 33 34 @DrawableRes 35 private final int mNormalBackgroundRes; 36 @DrawableRes 37 private final int mHighlightBackgroundRes; 38 private int mHighlightPosition = RecyclerView.NO_POSITION; 39 HighlightablePreferenceGroupAdapter(PreferenceGroup preferenceGroup)40 public HighlightablePreferenceGroupAdapter(PreferenceGroup preferenceGroup) { 41 super(preferenceGroup); 42 Context context = preferenceGroup.getContext(); 43 TypedValue outValue = new TypedValue(); 44 context.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, 45 outValue, /* resolveRefs= */ true); 46 mNormalBackgroundRes = outValue.resourceId; 47 mHighlightBackgroundRes = R.drawable.preference_highlight_default; 48 } 49 HighlightablePreferenceGroupAdapter(PreferenceGroup preferenceGroup, @DrawableRes int normalBackgroundRes, @DrawableRes int highlightBackgroundRes)50 public HighlightablePreferenceGroupAdapter(PreferenceGroup preferenceGroup, 51 @DrawableRes int normalBackgroundRes, @DrawableRes int highlightBackgroundRes) { 52 super(preferenceGroup); 53 mNormalBackgroundRes = normalBackgroundRes; 54 mHighlightBackgroundRes = highlightBackgroundRes; 55 } 56 57 @Override onBindViewHolder(PreferenceViewHolder holder, int position)58 public void onBindViewHolder(PreferenceViewHolder holder, int position) { 59 super.onBindViewHolder(holder, position); 60 updateBackground(holder, position); 61 } 62 updateBackground(PreferenceViewHolder holder, int position)63 private void updateBackground(PreferenceViewHolder holder, int position) { 64 View v = holder.itemView; 65 if (position == mHighlightPosition) { 66 addHighlightBackground(v); 67 } else if (hasHighlightBackground(v)) { 68 removeHighlightBackground(v); 69 } 70 } 71 72 /** 73 * Requests that a particular preference be highlighted. This will remove the highlight from 74 * the previously highlighted preference. 75 */ requestHighlight(View root, RecyclerView recyclerView, String key)76 public void requestHighlight(View root, RecyclerView recyclerView, String key) { 77 if (root == null || recyclerView == null) { 78 return; 79 } 80 int position = getPreferenceAdapterPosition(key); 81 if (position < 0) { 82 // Item is not in the list - clearing the previous highlight without setting a new one. 83 clearHighlight(root); 84 return; 85 } 86 root.post(() -> { 87 recyclerView.scrollToPosition(position); 88 int oldPosition = mHighlightPosition; 89 mHighlightPosition = position; 90 notifyItemChanged(oldPosition); 91 notifyItemChanged(position); 92 }); 93 } 94 95 /** 96 * Removes the highlight from the currently highlighted preference. 97 */ clearHighlight(View root)98 public void clearHighlight(View root) { 99 if (root == null) { 100 return; 101 } 102 root.post(() -> { 103 if (mHighlightPosition < 0) { 104 return; 105 } 106 int oldPosition = mHighlightPosition; 107 mHighlightPosition = RecyclerView.NO_POSITION; 108 notifyItemChanged(oldPosition); 109 }); 110 } 111 addHighlightBackground(View v)112 private void addHighlightBackground(View v) { 113 v.setTag(R.id.preference_highlighted, true); 114 v.setBackgroundResource(mHighlightBackgroundRes); 115 } 116 removeHighlightBackground(View v)117 private void removeHighlightBackground(View v) { 118 v.setTag(R.id.preference_highlighted, false); 119 v.setBackgroundResource(mNormalBackgroundRes); 120 } 121 hasHighlightBackground(View v)122 private boolean hasHighlightBackground(View v) { 123 return Boolean.TRUE.equals(v.getTag(R.id.preference_highlighted)); 124 } 125 } 126