1 /* 2 * Copyright (C) 2022 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.systemui.media.dialog; 18 19 import android.annotation.Nullable; 20 import android.content.Context; 21 import android.util.AttributeSet; 22 import android.widget.SeekBar; 23 24 import com.android.systemui.res.R; 25 26 /** 27 * Customized SeekBar for MediaOutputDialog, apply scale between device volume and progress, to make 28 * adjustment smoother. 29 */ 30 public class MediaOutputSeekbar extends SeekBar { 31 // The scale is added to make slider value change smooth. 32 private static final int SCALE_SIZE = 1000; 33 34 @Nullable 35 private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener = null; 36 MediaOutputSeekbar(Context context, AttributeSet attrs)37 public MediaOutputSeekbar(Context context, AttributeSet attrs) { 38 super(context, attrs); 39 setMin(0); 40 super.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 41 @Override 42 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 43 final String percentageString = context.getResources().getString( 44 R.string.media_output_dialog_volume_percentage, 45 getPercentage()); 46 // Override the default TTS for the seekbar. The percentage should correspond to 47 // the volume value, not the progress value. I.e. for the volume range 0 - 25, the 48 // percentage should be 0%, 4%, 8%, etc. It should never be 6% since 6% doesn't map 49 // to an integer volume value. 50 setStateDescription(percentageString); 51 if (mOnSeekBarChangeListener != null) { 52 mOnSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser); 53 } 54 } 55 56 @Override 57 public void onStartTrackingTouch(SeekBar seekBar) { 58 if (mOnSeekBarChangeListener != null) { 59 mOnSeekBarChangeListener.onStartTrackingTouch(seekBar); 60 } 61 } 62 63 @Override 64 public void onStopTrackingTouch(SeekBar seekBar) { 65 if (mOnSeekBarChangeListener != null) { 66 mOnSeekBarChangeListener.onStopTrackingTouch(seekBar); 67 } 68 } 69 }); 70 } 71 72 @Override setOnSeekBarChangeListener(@ullable SeekBar.OnSeekBarChangeListener listener)73 public void setOnSeekBarChangeListener(@Nullable SeekBar.OnSeekBarChangeListener listener) { 74 mOnSeekBarChangeListener = listener; 75 } 76 scaleProgressToVolume(int progress)77 static int scaleProgressToVolume(int progress) { 78 return progress / SCALE_SIZE; 79 } 80 scaleVolumeToProgress(int volume)81 static int scaleVolumeToProgress(int volume) { 82 return volume * SCALE_SIZE; 83 } 84 getVolume()85 int getVolume() { 86 return scaleProgressToVolume(getProgress()); 87 } 88 setVolume(int volume)89 void setVolume(int volume) { 90 setProgress(scaleVolumeToProgress(volume), true); 91 } 92 setMaxVolume(int maxVolume)93 void setMaxVolume(int maxVolume) { 94 setMax(scaleVolumeToProgress(maxVolume)); 95 } 96 resetVolume()97 void resetVolume() { 98 setProgress(getMin()); 99 } 100 getPercentage()101 int getPercentage() { 102 // The progress -> volume -> progress conversion is necessary to ensure that progress 103 // strictly corresponds to an integer volume value. 104 // Example: 10424 (progress) -> 10 (volume) -> 10000 (progress). 105 int normalizedProgress = scaleVolumeToProgress(scaleProgressToVolume(getProgress())); 106 return (int) ((double) normalizedProgress * 100 / getMax()); 107 } 108 } 109