| /* |
| * 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.systemui.qs |
| |
| import android.app.StatusBarManager |
| import android.content.Context |
| import android.content.res.Configuration |
| import android.graphics.PorterDuff |
| import android.graphics.drawable.Drawable |
| import android.graphics.drawable.RippleDrawable |
| import android.os.UserManager |
| import android.util.AttributeSet |
| import android.view.View |
| import android.widget.ImageView |
| import android.widget.LinearLayout |
| import com.android.settingslib.Utils |
| import com.android.settingslib.drawable.UserIconDrawable |
| import com.android.systemui.R |
| import com.android.systemui.statusbar.phone.MultiUserSwitch |
| import com.android.systemui.statusbar.phone.SettingsButton |
| |
| /** |
| * Quick Settings bottom buttons placed in footer (aka utility bar) - always visible in expanded QS, |
| * in split shade mode visible also in collapsed state. May contain up to 5 buttons: settings, |
| * edit tiles, power off and conditionally: user switch and tuner |
| */ |
| class FooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) { |
| private lateinit var settingsContainer: View |
| private lateinit var settingsButton: SettingsButton |
| private lateinit var multiUserSwitch: MultiUserSwitch |
| private lateinit var multiUserAvatar: ImageView |
| private lateinit var tunerIcon: View |
| private lateinit var editTilesButton: View |
| |
| private var settingsCogAnimator: TouchAnimator? = null |
| |
| private var qsDisabled = false |
| private var expansionAmount = 0f |
| |
| override fun onFinishInflate() { |
| super.onFinishInflate() |
| editTilesButton = requireViewById(android.R.id.edit) |
| settingsButton = findViewById(R.id.settings_button) |
| settingsContainer = findViewById(R.id.settings_button_container) |
| multiUserSwitch = findViewById(R.id.multi_user_switch) |
| multiUserAvatar = multiUserSwitch.findViewById(R.id.multi_user_avatar) |
| tunerIcon = requireViewById(R.id.tuner_icon) |
| |
| // RenderThread is doing more harm than good when touching the header (to expand quick |
| // settings), so disable it for this view |
| if (settingsButton.background is RippleDrawable) { |
| (settingsButton.background as RippleDrawable).setForceSoftware(true) |
| } |
| updateResources() |
| importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES |
| } |
| |
| fun updateAnimator(width: Int, numTiles: Int) { |
| val size = (mContext.resources.getDimensionPixelSize(R.dimen.qs_quick_tile_size) - |
| mContext.resources.getDimensionPixelSize(R.dimen.qs_tile_padding)) |
| val remaining = (width - numTiles * size) / (numTiles - 1) |
| val defSpace = mContext.resources.getDimensionPixelOffset(R.dimen.default_gear_space) |
| val translation = if (isLayoutRtl) (remaining - defSpace) else -(remaining - defSpace) |
| settingsCogAnimator = TouchAnimator.Builder() |
| .addFloat(settingsButton, "translationX", translation.toFloat(), 0f) |
| .addFloat(settingsButton, "rotation", -120f, 0f) |
| .build() |
| setExpansion(expansionAmount) |
| } |
| |
| override fun onConfigurationChanged(newConfig: Configuration) { |
| super.onConfigurationChanged(newConfig) |
| updateResources() |
| } |
| |
| override fun onRtlPropertiesChanged(layoutDirection: Int) { |
| super.onRtlPropertiesChanged(layoutDirection) |
| updateResources() |
| } |
| |
| private fun updateResources() { |
| val tunerIconTranslation = mContext.resources |
| .getDimensionPixelOffset(R.dimen.qs_footer_tuner_icon_translation).toFloat() |
| tunerIcon.translationX = if (isLayoutRtl) (-tunerIconTranslation) else tunerIconTranslation |
| } |
| |
| fun setKeyguardShowing() { |
| setExpansion(expansionAmount) |
| } |
| |
| fun setExpansion(headerExpansionFraction: Float) { |
| expansionAmount = headerExpansionFraction |
| if (settingsCogAnimator != null) settingsCogAnimator!!.setPosition(headerExpansionFraction) |
| } |
| |
| fun disable( |
| state2: Int, |
| isTunerEnabled: Boolean, |
| multiUserEnabled: Boolean |
| ) { |
| val disabled = state2 and StatusBarManager.DISABLE2_QUICK_SETTINGS != 0 |
| if (disabled == qsDisabled) return |
| qsDisabled = disabled |
| updateEverything(isTunerEnabled, multiUserEnabled) |
| } |
| |
| fun updateEverything( |
| isTunerEnabled: Boolean, |
| multiUserEnabled: Boolean |
| ) { |
| post { |
| updateVisibilities(isTunerEnabled, multiUserEnabled) |
| updateClickabilities() |
| isClickable = false |
| } |
| } |
| |
| private fun updateClickabilities() { |
| multiUserSwitch.isClickable = multiUserSwitch.visibility == VISIBLE |
| editTilesButton.isClickable = editTilesButton.visibility == VISIBLE |
| settingsButton.isClickable = settingsButton.visibility == VISIBLE |
| } |
| |
| private fun updateVisibilities( |
| isTunerEnabled: Boolean, |
| multiUserEnabled: Boolean |
| ) { |
| settingsContainer.visibility = if (qsDisabled) GONE else VISIBLE |
| tunerIcon.visibility = if (isTunerEnabled) VISIBLE else INVISIBLE |
| multiUserSwitch.visibility = if (multiUserEnabled) VISIBLE else GONE |
| val isDemo = UserManager.isDeviceInDemoMode(context) |
| settingsButton.visibility = if (isDemo) INVISIBLE else VISIBLE |
| } |
| |
| fun onUserInfoChanged(picture: Drawable?, isGuestUser: Boolean) { |
| var pictureToSet = picture |
| if (picture != null && isGuestUser && picture !is UserIconDrawable) { |
| pictureToSet = picture.constantState.newDrawable(resources).mutate() |
| pictureToSet.setColorFilter( |
| Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorForeground), |
| PorterDuff.Mode.SRC_IN) |
| } |
| multiUserAvatar.setImageDrawable(pictureToSet) |
| } |
| } |