1 /* 2 * Copyright (C) 2015 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.permissioncontroller.permission.ui.handheld; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.graphics.drawable.Drawable; 22 import android.os.Bundle; 23 import android.os.UserHandle; 24 import android.view.LayoutInflater; 25 import android.view.View; 26 import android.view.ViewGroup; 27 import android.widget.ImageView; 28 import android.widget.TextView; 29 30 import androidx.annotation.NonNull; 31 import androidx.annotation.Nullable; 32 import androidx.preference.PreferenceScreen; 33 import androidx.preference.PreferenceViewHolder; 34 35 import com.android.permissioncontroller.DeviceUtils; 36 import com.android.permissioncontroller.R; 37 38 /** 39 * A class that contains a header. 40 */ 41 public abstract class SettingsWithLargeHeader extends PermissionsFrameFragment { 42 static final String HEADER_KEY = " HEADER_PREFERENCE"; 43 private static final int HEADER_SORT_FIRST = -2; 44 45 private View mHeader; 46 private LargeHeaderPreference mHeaderPreference; 47 protected Intent mInfoIntent; 48 protected UserHandle mUserHandle; 49 protected Drawable mIcon; 50 protected CharSequence mLabel; 51 protected boolean mSmallIcon; 52 private View.OnClickListener mListener; 53 private CharSequence mSummary; 54 private boolean mShouldShowHeader = true; 55 56 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)57 public View onCreateView(LayoutInflater inflater, ViewGroup container, 58 Bundle savedInstanceState) { 59 ViewGroup root = (ViewGroup) super.onCreateView(inflater, container, savedInstanceState); 60 61 if (!DeviceUtils.isTelevision(getContext())) { 62 if (mHeader != null && mHeader.getVisibility() == View.VISIBLE) { 63 updateHeader(mHeader); 64 mHeader.requireViewById(R.id.header_link).setVisibility(View.VISIBLE); 65 } 66 } 67 68 return root; 69 } 70 71 @Override setPreferenceScreen(PreferenceScreen screen)72 public void setPreferenceScreen(PreferenceScreen screen) { 73 mHeaderPreference = new LargeHeaderPreference(getContext(), this); 74 if (screen.findPreference(HEADER_KEY) == null) { 75 screen.addPreference(mHeaderPreference); 76 } 77 super.setPreferenceScreen(screen); 78 } 79 80 /** 81 * Set the icon and label to use in the header. 82 * 83 * @param icon the icon 84 * @param label the label 85 * @param infoIntent the intent to show on click 86 * @param smallIcon whether the icon should be small 87 */ setHeader(@onNull Drawable icon, @NonNull CharSequence label, Intent infoIntent, @Nullable UserHandle userHandle, boolean smallIcon)88 public void setHeader(@NonNull Drawable icon, @NonNull CharSequence label, 89 Intent infoIntent, @Nullable UserHandle userHandle, boolean smallIcon) { 90 mIcon = icon; 91 mLabel = label; 92 mInfoIntent = infoIntent; 93 mUserHandle = userHandle; 94 mSmallIcon = smallIcon; 95 if (mHeader != null) { 96 updateHeader(mHeader); 97 } 98 } 99 100 /** 101 * Updates the header to use the correct icon and title. 102 * 103 * @param header the View that contains the components. 104 */ updateHeader(@ullable View header)105 protected void updateHeader(@Nullable View header) { 106 if (header != null) { 107 header.setVisibility(View.VISIBLE); 108 109 ImageView appIcon = header.requireViewById( 110 com.android.settingslib.widget.preference.layout.R.id.entity_header_icon); 111 appIcon.setImageDrawable(mIcon); 112 if (mSmallIcon) { 113 int size = getContext().getResources().getDimensionPixelSize( 114 R.dimen.permission_icon_header_size); 115 appIcon.getLayoutParams().width = size; 116 appIcon.getLayoutParams().height = size; 117 } 118 if (mInfoIntent != null) { 119 appIcon.setOnClickListener(v -> getActivity().startActivityAsUser(mInfoIntent, 120 mUserHandle)); 121 appIcon.setContentDescription(mLabel); 122 } 123 124 TextView appName = header.requireViewById( 125 com.android.settingslib.widget.preference.layout.R.id.entity_header_title); 126 appName.setText(mLabel); 127 128 129 header.requireViewById( 130 com.android.settingslib.widget.preference.layout.R.id.entity_header_summary) 131 .setVisibility(View.GONE); 132 133 header.requireViewById( 134 com.android.settingslib.widget.preference.layout.R.id.entity_header_second_summary) 135 .setVisibility(View.GONE); 136 header.requireViewById(R.id.header_link).setVisibility(View.GONE); 137 } 138 } 139 140 /** 141 * Hide the entire header. 142 */ hideHeader()143 public void hideHeader() { 144 if (mHeaderPreference == null) { 145 mShouldShowHeader = false; 146 return; 147 } 148 mHeaderPreference.setVisible(false); 149 mHeader = null; 150 } 151 152 /** 153 * Set the summary text in the header. If the header has not been created yet, then save the 154 * the summary for later. 155 * 156 * @param summary the text to display 157 * @param listener the click listener if the summary should be clickable 158 */ setSummary(@onNull CharSequence summary, @Nullable View.OnClickListener listener)159 public void setSummary(@NonNull CharSequence summary, @Nullable View.OnClickListener listener) { 160 if (mHeader == null) { 161 mSummary = summary; 162 mListener = listener; 163 return; 164 } 165 TextView textView = mHeader.requireViewById(R.id.header_text); 166 TextView linkView = mHeader.requireViewById(R.id.header_link); 167 if (listener != null) { 168 linkView.setOnClickListener(listener); 169 linkView.setVisibility(View.VISIBLE); 170 linkView.setText(summary); 171 textView.setVisibility(View.GONE); 172 } else { 173 textView.setVisibility(View.VISIBLE); 174 textView.setText(summary); 175 linkView.setVisibility(View.GONE); 176 } 177 } 178 179 /** 180 * A Preference that will act as the "Large Header" for "SettingsWithLargeHeader" fragments. 181 */ 182 public static class LargeHeaderPreference extends PermissionPreferenceCategory { 183 private SettingsWithLargeHeader mFragment; 184 LargeHeaderPreference(Context context, SettingsWithLargeHeader fragment)185 private LargeHeaderPreference(Context context, SettingsWithLargeHeader fragment) { 186 super(context); 187 mFragment = fragment; 188 setVisible(mFragment.mShouldShowHeader); 189 setSelectable(false); 190 setLayoutResource(R.layout.header_large); 191 setKey(HEADER_KEY); 192 193 // display the header first (lower numbers are ordered higher) 194 setOrder(HEADER_SORT_FIRST); 195 } 196 197 @Override onBindViewHolder(PreferenceViewHolder holder)198 public void onBindViewHolder(PreferenceViewHolder holder) { 199 if (!isVisible()) { 200 return; 201 } 202 super.onBindViewHolder(holder); 203 204 View view = holder.itemView; 205 if (view == mFragment.mHeader) { 206 return; 207 } 208 mFragment.mHeader = view; 209 if (mFragment.mIcon != null) { 210 mFragment.updateHeader(view); 211 } 212 if (mFragment.mSummary != null) { 213 mFragment.setSummary(mFragment.mSummary, mFragment.mListener); 214 } 215 } 216 } 217 } 218