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