Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 75c2e161 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Animate ranges and toggles" into rvc-dev

parents 28308529 2ee4ec93
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -54,6 +54,11 @@ public class Interpolators {
    public static final Interpolator PANEL_CLOSE_ACCELERATED
            = new PathInterpolator(0.3f, 0, 0.5f, 1);
    public static final Interpolator BOUNCE = new BounceInterpolator();
    /**
     * For state transitions on the control panel that lives in GlobalActions.
     */
    public static final Interpolator CONTROL_STATE = new PathInterpolator(0.4f, 0f, 0.2f,
            1.0f);

    /**
     * Interpolator to be used when animating a move based on a click. Pair with enough duration.
+2 −6
Original line number Diff line number Diff line
@@ -24,12 +24,11 @@ import android.service.controls.actions.BooleanAction
import android.service.controls.actions.CommandAction
import android.util.Log
import android.view.HapticFeedbackConstants

import com.android.systemui.R

object ControlActionCoordinator {
    public const val MIN_LEVEL = 0
    public const val MAX_LEVEL = 10000
    const val MIN_LEVEL = 0
    const val MAX_LEVEL = 10000

    private var dialog: Dialog? = null

@@ -40,9 +39,6 @@ object ControlActionCoordinator {

    fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) {
        cvh.action(BooleanAction(templateId, !isChecked))

        val nextLevel = if (isChecked) MIN_LEVEL else MAX_LEVEL
        cvh.clipLayer.setLevel(nextLevel)
    }

    fun touch(cvh: ControlViewHolder, templateId: String, control: Control) {
+35 −10
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.systemui.controls.ui

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.drawable.ClipDrawable
import android.graphics.drawable.GradientDrawable
@@ -32,11 +35,11 @@ import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView

import com.android.internal.graphics.ColorUtils
import com.android.systemui.Interpolators
import com.android.systemui.R
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.R

import kotlin.reflect.KClass

/**
@@ -53,15 +56,17 @@ class ControlViewHolder(
) {

    companion object {
        const val STATE_ANIMATION_DURATION = 700L
        private const val UPDATE_DELAY_IN_MILLIS = 3000L
        private const val ALPHA_ENABLED = (255.0 * 0.2).toInt()
        private const val ALPHA_DISABLED = 255
        private const val ALPHA_DISABLED = 0
        private val FORCE_PANEL_DEVICES = setOf(
            DeviceTypes.TYPE_THERMOSTAT,
            DeviceTypes.TYPE_CAMERA
        )
    }

    private var stateAnimator: ValueAnimator? = null
    val icon: ImageView = layout.requireViewById(R.id.icon)
    val status: TextView = layout.requireViewById(R.id.status)
    val title: TextView = layout.requireViewById(R.id.title)
@@ -79,6 +84,7 @@ class ControlViewHolder(
        val ld = layout.getBackground() as LayerDrawable
        ld.mutate()
        clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable
        clipLayer.alpha = ALPHA_DISABLED
        // needed for marquee to start
        status.setSelected(true)
    }
@@ -160,30 +166,49 @@ class ControlViewHolder(
        }
    }

    internal fun applyRenderInfo(enabled: Boolean, offset: Int = 0) {
    internal fun applyRenderInfo(enabled: Boolean, offset: Int = 0, animated: Boolean = true) {
        setEnabled(enabled)

        val ri = RenderInfo.lookup(context, cws.componentName, deviceType, enabled, offset)

        val fg = context.getResources().getColorStateList(ri.foreground, context.getTheme())
        val (bg, alpha) = if (enabled) {
        val (bg, newAlpha) = if (enabled) {
            Pair(ri.enabledBackground, ALPHA_ENABLED)
        } else {
            Pair(R.color.control_default_background, ALPHA_DISABLED)
        }

        status.setTextColor(fg)

        icon.setImageDrawable(ri.icon)

        // do not color app icons
        if (deviceType != DeviceTypes.TYPE_ROUTINE) {
            icon.setImageTintList(fg)
            icon.imageTintList = fg
        }

        (clipLayer.getDrawable() as GradientDrawable).apply {
            setColor(context.getResources().getColor(bg, context.getTheme()))
            setAlpha(alpha)
            val newColor = context.resources.getColor(bg, context.theme)
            stateAnimator?.cancel()
            if (animated) {
                val oldColor = color?.defaultColor ?: newColor
                stateAnimator = ValueAnimator.ofInt(clipLayer.alpha, newAlpha).apply {
                    addUpdateListener {
                        alpha = it.animatedValue as Int
                        setColor(ColorUtils.blendARGB(oldColor, newColor, it.animatedFraction))
                    }
                    addListener(object : AnimatorListenerAdapter() {
                        override fun onAnimationEnd(animation: Animator?) {
                            stateAnimator = null
                        }
                    })
                    duration = STATE_ANIMATION_DURATION
                    interpolator = Interpolators.CONTROL_STATE
                    start()
                }
            } else {
                alpha = newAlpha
                setColor(newColor)
            }
        }
    }

+3 −5
Original line number Diff line number Diff line
@@ -18,12 +18,10 @@ package com.android.systemui.controls.ui

import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.view.View
import android.service.controls.Control
import android.service.controls.templates.ToggleTemplate

import android.view.View
import com.android.systemui.R
import com.android.systemui.controls.ui.ControlActionCoordinator.MIN_LEVEL
import com.android.systemui.controls.ui.ControlActionCoordinator.MAX_LEVEL

class ToggleBehavior : Behavior {
@@ -34,7 +32,7 @@ class ToggleBehavior : Behavior {

    override fun initialize(cvh: ControlViewHolder) {
        this.cvh = cvh
        cvh.applyRenderInfo(false)
        cvh.applyRenderInfo(false /* enabled */, 0 /* offset */, false /* animated */)

        cvh.layout.setOnClickListener(View.OnClickListener() {
            ControlActionCoordinator.toggle(cvh, template.getTemplateId(), template.isChecked())
@@ -49,9 +47,9 @@ class ToggleBehavior : Behavior {

        val ld = cvh.layout.getBackground() as LayerDrawable
        clipLayer = ld.findDrawableByLayerId(R.id.clip_layer)
        clipLayer.level = MAX_LEVEL

        val checked = template.isChecked()
        clipLayer.setLevel(if (checked) MAX_LEVEL else MIN_LEVEL)
        cvh.applyRenderInfo(checked)
    }
}
+60 −29
Original line number Diff line number Diff line
@@ -16,11 +16,20 @@

package com.android.systemui.controls.ui

import android.os.Bundle
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.os.Bundle
import android.service.controls.Control
import android.service.controls.actions.FloatAction
import android.service.controls.templates.RangeTemplate
import android.service.controls.templates.ToggleRangeTemplate
import android.util.Log
import android.util.MathUtils
import android.util.TypedValue
import android.view.GestureDetector
import android.view.GestureDetector.SimpleOnGestureListener
import android.view.MotionEvent
@@ -29,19 +38,14 @@ import android.view.ViewGroup
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo
import android.widget.TextView
import android.service.controls.Control
import android.service.controls.actions.FloatAction
import android.service.controls.templates.RangeTemplate
import android.service.controls.templates.ToggleRangeTemplate
import android.util.TypedValue

import com.android.systemui.Interpolators
import com.android.systemui.R
import com.android.systemui.controls.ui.ControlActionCoordinator.MIN_LEVEL
import com.android.systemui.controls.ui.ControlActionCoordinator.MAX_LEVEL

import com.android.systemui.controls.ui.ControlActionCoordinator.MIN_LEVEL
import java.util.IllegalFormatException

class ToggleRangeBehavior : Behavior {
    private var rangeAnimator: ValueAnimator? = null
    lateinit var clipLayer: Drawable
    lateinit var template: ToggleRangeTemplate
    lateinit var control: Control
@@ -61,20 +65,21 @@ class ToggleRangeBehavior : Behavior {
        status = cvh.status
        context = status.getContext()

        cvh.applyRenderInfo(false)
        cvh.applyRenderInfo(false /* enabled */, 0 /* offset */, false /* animated */)

        val gestureListener = ToggleRangeGestureListener(cvh.layout)
        val gestureDetector = GestureDetector(context, gestureListener)
        cvh.layout.setOnTouchListener { v: View, e: MotionEvent ->
            if (gestureDetector.onTouchEvent(e)) {
                return@setOnTouchListener true
                // Don't return true to let the state list change to "pressed"
                return@setOnTouchListener false
            }

            if (e.getAction() == MotionEvent.ACTION_UP && gestureListener.isDragging) {
                v.getParent().requestDisallowInterceptTouchEvent(false)
                gestureListener.isDragging = false
                endUpdateRange()
                return@setOnTouchListener true
                return@setOnTouchListener false
            }

            return@setOnTouchListener false
@@ -87,17 +92,18 @@ class ToggleRangeBehavior : Behavior {
        currentStatusText = control.getStatusText()
        status.setText(currentStatusText)

        // ControlViewHolder sets a long click listener, but we want to handle touch in
        // here instead, otherwise we'll have state conflicts.
        cvh.layout.setOnLongClickListener(null)

        val ld = cvh.layout.getBackground() as LayerDrawable
        clipLayer = ld.findDrawableByLayerId(R.id.clip_layer)
        clipLayer.setLevel(MIN_LEVEL)

        template = control.getControlTemplate() as ToggleRangeTemplate
        rangeTemplate = template.getRange()

        val checked = template.isChecked()
        val currentRatio = rangeTemplate.getCurrentValue() /
                (rangeTemplate.getMaxValue() - rangeTemplate.getMinValue())
        updateRange(currentRatio, checked, /* isDragging */ false)
        updateRange(rangeToLevelValue(rangeTemplate.currentValue), checked, /* isDragging */ false)

        cvh.applyRenderInfo(checked)

@@ -146,9 +152,8 @@ class ToggleRangeBehavior : Behavior {
                        } else {
                            val value = arguments.getFloat(
                                AccessibilityNodeInfo.ACTION_ARGUMENT_PROGRESS_VALUE)
                            val ratioDiff = (value - rangeTemplate.getCurrentValue()) /
                                (rangeTemplate.getMaxValue() - rangeTemplate.getMinValue())
                            updateRange(ratioDiff, template.isChecked(), /* isDragging */ false)
                            val level = rangeToLevelValue(value - rangeTemplate.getCurrentValue())
                            updateRange(level, template.isChecked(), /* isDragging */ false)
                            endUpdateRange()
                            true
                        }
@@ -172,13 +177,30 @@ class ToggleRangeBehavior : Behavior {
                .getDimensionPixelSize(R.dimen.control_status_expanded).toFloat())
    }

    fun updateRange(ratioDiff: Float, checked: Boolean, isDragging: Boolean) {
        val changeAmount = if (checked) (MAX_LEVEL * ratioDiff).toInt() else MIN_LEVEL
        val newLevel = Math.max(MIN_LEVEL, Math.min(MAX_LEVEL, clipLayer.getLevel() + changeAmount))
        clipLayer.setLevel(newLevel)
    fun updateRange(level: Int, checked: Boolean, isDragging: Boolean) {
        val newLevel = if (checked) Math.max(MIN_LEVEL, Math.min(MAX_LEVEL, level)) else MIN_LEVEL

        rangeAnimator?.cancel()
        if (isDragging) {
            clipLayer.level = newLevel
        } else {
            rangeAnimator = ValueAnimator.ofInt(cvh.clipLayer.level, newLevel).apply {
                addUpdateListener {
                    cvh.clipLayer.level = it.animatedValue as Int
                }
                addListener(object : AnimatorListenerAdapter() {
                    override fun onAnimationEnd(animation: Animator?) {
                        rangeAnimator = null
                    }
                })
                duration = ControlViewHolder.STATE_ANIMATION_DURATION
                interpolator = Interpolators.CONTROL_STATE
                start()
            }
        }

        if (checked) {
            val newValue = levelToRangeValue(clipLayer.getLevel())
            val newValue = levelToRangeValue(newLevel)
            currentRangeValue = format(rangeTemplate.getFormatString().toString(),
                    DEFAULT_FORMAT, newValue)
            val text = if (isDragging) {
@@ -206,9 +228,13 @@ class ToggleRangeBehavior : Behavior {
    }

    private fun levelToRangeValue(i: Int): Float {
        val ratio = i.toFloat() / MAX_LEVEL
        return rangeTemplate.getMinValue() +
            (ratio * (rangeTemplate.getMaxValue() - rangeTemplate.getMinValue()))
        return MathUtils.constrainedMap(rangeTemplate.minValue, rangeTemplate.maxValue,
                MIN_LEVEL.toFloat(), MAX_LEVEL.toFloat(), i.toFloat())
    }

    private fun rangeToLevelValue(i: Float): Int {
        return MathUtils.constrainedMap(MIN_LEVEL.toFloat(), MAX_LEVEL.toFloat(),
                rangeTemplate.minValue, rangeTemplate.maxValue, i).toInt()
    }

    fun endUpdateRange() {
@@ -247,6 +273,9 @@ class ToggleRangeBehavior : Behavior {
        }

        override fun onLongPress(e: MotionEvent) {
            if (isDragging) {
                return
            }
            ControlActionCoordinator.longPress(this@ToggleRangeBehavior.cvh)
        }

@@ -265,8 +294,10 @@ class ToggleRangeBehavior : Behavior {
                isDragging = true
            }

            this@ToggleRangeBehavior.updateRange(-xDiff / v.getWidth(),
                /* checked */ true, /* isDragging */ true)
            val ratioDiff = -xDiff / v.width
            val changeAmount = ((MAX_LEVEL - MIN_LEVEL) * ratioDiff).toInt()
            this@ToggleRangeBehavior.updateRange(clipLayer.level + changeAmount,
                    checked = true, isDragging = true)
            return true
        }

Loading