summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Lee <anwlee@google.com>2015-01-13 13:19:50 -0800
committerAndrew Lee <anwlee@google.com>2015-01-13 22:31:42 -0800
commitf06f97fa1c13576ce2b42f8f0e9ad088f2991607 (patch)
treec49c3d0e569da3233a87af29af3a4f9733c363b1
parent8e1c0a9869010dbbfe635cc355e550a38ed1ea64 (diff)
downloadpackages_apps_InCallUI-f06f97fa1c13576ce2b42f8f0e9ad088f2991607.tar.gz
packages_apps_InCallUI-f06f97fa1c13576ce2b42f8f0e9ad088f2991607.tar.bz2
packages_apps_InCallUI-f06f97fa1c13576ce2b42f8f0e9ad088f2991607.zip
Improve call button accessibility.
+ Convert Audio Button into a ToggleButton, and update its content description depending on whether its acting as a toggle for speakerphone, or if it's acting as a menu button to select from more than two audio output modes. + Set custom style on ToggleButtons with null background, to override the default ToggleButton styling which was causing shadows. - Delete CallToggleButton, which did some hacky things with the content description and accessibility. - Delete helper method which abused TYPE_ANNOUNCEMENTS. Rely on default TalkBack behavior for ToggleButtons to read on click. - Delete unused accessibility strings. The states these were formerly read out for will now be handled by a combination of button labels and default TalkBack behavior. The UI (without TalkBack) behaves the same after these changes. The behavior with TalkBack after these changes is that the audio (when toggling for speakerphone), mute, and hold buttons will generally read "speaker/mute/hold button (not) checked" when explored by touch depending on their state. They will read "speaker/mute/hold" when clicked. If more than two audio modes are supported, the audio button will read "<mode> button checked", where <mode> can be speaker, bluetooth, handset, or earpiece. When clicked, it will open the audio pop up menu and read that there are # options displayed on the screen. This is combines the ToggleButton and PopupMenu Talkback behavior, since this is a custom widget. Bug: 18783204 Change-Id: I27363c697bb018b5f87ad2e27678f8db6d93b2e7
-rw-r--r--res/drawable/btn_compound_audio.xml9
-rw-r--r--res/drawable/btn_compound_background.xml2
-rw-r--r--res/layout/call_button_fragment.xml14
-rw-r--r--res/values/strings.xml24
-rw-r--r--res/values/styles.xml9
-rw-r--r--src/com/android/incallui/CallButtonFragment.java92
-rw-r--r--src/com/android/incallui/CallToggleButton.java54
7 files changed, 56 insertions, 148 deletions
diff --git a/res/drawable/btn_compound_audio.xml b/res/drawable/btn_compound_audio.xml
index 222ff1b4..25a64a6a 100644
--- a/res/drawable/btn_compound_audio.xml
+++ b/res/drawable/btn_compound_audio.xml
@@ -90,13 +90,4 @@
android:tint="@color/selectable_icon_tint" />
</item>
- <!-- Generic "audio mode" icon. -->
- <!-- TODO: is this actually needed? -->
- <!--
- <item android:id="@+id/soundItem">
- <bitmap android:src="@drawable/ic_sound_holo_dark"
- android:gravity="center" />
- </item>
- -->
-
</layer-list>
diff --git a/res/drawable/btn_compound_background.xml b/res/drawable/btn_compound_background.xml
index 36aab0df..20e2a305 100644
--- a/res/drawable/btn_compound_background.xml
+++ b/res/drawable/btn_compound_background.xml
@@ -32,4 +32,4 @@
<item android:drawable="@drawable/btn_unselected" />
</selector>
</item>
-</ripple> \ No newline at end of file
+</ripple>
diff --git a/res/layout/call_button_fragment.xml b/res/layout/call_button_fragment.xml
index 2ca64036..24101fea 100644
--- a/res/layout/call_button_fragment.xml
+++ b/res/layout/call_button_fragment.xml
@@ -67,10 +67,10 @@
<!-- "Audio mode". this is a multi-mode button that can behave either like a simple
"compound button" with two states *or* like an action button that brings up a popup
menu; see btn_compound_audio.xml and CallButtonFragment.updateAudioButtons(). -->
- <ImageButton android:id="@+id/audioButton"
+ <ToggleButton android:id="@+id/audioButton"
style="@style/InCallCompoundButton"
android:background="@drawable/btn_compound_audio"
- android:contentDescription="@string/onscreenAudioText" />
+ android:contentDescription="@string/audio_mode_speaker" />
<!-- "Change to audio call" for video calls. -->
<ImageButton android:id="@+id/changeToVoiceButton"
@@ -82,7 +82,7 @@
<!-- MIDDLE LEFT SLOT ================================================================== -->
<!-- "Mute" -->
- <com.android.incallui.CallToggleButton android:id="@+id/muteButton"
+ <ToggleButton android:id="@+id/muteButton"
style="@style/InCallCompoundButton"
android:background="@drawable/btn_compound_mute"
android:contentDescription="@string/onscreenMuteText" />
@@ -90,7 +90,7 @@
<!-- CENTER SLOT ======================================================================= -->
<!-- "Dialpad" -->
- <com.android.incallui.CallToggleButton android:id="@+id/dialpadButton"
+ <ToggleButton android:id="@+id/dialpadButton"
style="@style/InCallCompoundButton"
android:background="@drawable/btn_compound_dialpad"
android:contentDescription="@string/onscreenShowDialpadText" />
@@ -101,7 +101,7 @@
other of these must always be set to GONE. -->
<!-- "Hold" -->
- <com.android.incallui.CallToggleButton android:id="@+id/holdButton"
+ <ToggleButton android:id="@+id/holdButton"
style="@style/InCallCompoundButton"
android:background="@drawable/btn_compound_hold"
android:contentDescription="@string/onscreenHoldText" />
@@ -121,7 +121,7 @@
android:visibility="gone" />
<!-- "Switch camera" for video calls. -->
- <com.android.incallui.CallToggleButton android:id="@+id/switchCameraButton"
+ <ToggleButton android:id="@+id/switchCameraButton"
style="@style/InCallCompoundButton"
android:background="@drawable/btn_compound_video_switch"
android:contentDescription="@string/onscreenSwitchCameraText"
@@ -149,7 +149,7 @@
android:visibility="gone" />
<!-- "Switch camera" for video calls. -->
- <com.android.incallui.CallToggleButton android:id="@+id/pauseVideoButton"
+ <ToggleButton android:id="@+id/pauseVideoButton"
style="@style/InCallCompoundButton"
android:background="@drawable/btn_compound_video_off"
android:contentDescription="@string/onscreenPauseVideoText"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 585030de..e8cc64c1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -336,30 +336,6 @@
<!-- "Custom Message" Send alert dialog button -->
<string name="custom_message_send">Send</string>
- <!-- String used by AccessibilityService to announce that the speakerphone has been selected for audio output [CHAR LIMIT=NONE]-->
- <string name="accessibility_speakerphone_selected">Speakerphone selected</string>
-
- <!-- String used by AccessibilityService to announce that the phone's earpiece has been selected for audio output [CHAR LIMIT=NONE]-->
- <string name="accessibility_earpiece_selected">Earpiece selected</string>
-
- <!-- String used by AccessibilityService to announce that the wired headset has been selected for audio output [CHAR LIMIT=NONE]-->
- <string name="accessibility_wired_headset_selected">Wired headset selected</string>
-
- <!-- String used by AccessibilityService to announce that the bluetooth headset has been selected for audio output [CHAR LIMIT=NONE]-->
- <string name="accessibility_bluetooth_headset_selected">Bluetooth headset selected</string>
-
- <!-- String used by AccessibilityService to announce that the call has been muted [CHAR LIMIT=NONE]-->
- <string name="accessibility_call_muted">Call muted.</string>
-
- <!-- String used by AccessibilityService to announce that the call has been unmuted [CHAR LIMIT=NONE]-->
- <string name="accessibility_call_unmuted">Call unmuted.</string>
-
- <!-- String used by AccessibilityService to announce that the call has been put on hold [CHAR LIMIT=NONE]-->
- <string name="accessibility_call_put_on_hold">Call put on hold.</string>
-
- <!-- String used by AccessibilityService to announce that the call has been removed from hold [CHAR LIMIT=NONE]-->
- <string name="accessibility_call_removed_from_hold">Call no longer on hold.</string>
-
<!-- Description of the answer target in the Slide unlock screen of Phone. [CHAR LIMIT=NONE] -->
<string name="description_target_answer">Answer</string>
<!-- Description of the send_sms target in the Slide unlock screen of Phone. [CHAR LIMIT=NONE] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 9471c183..e16d72cb 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -61,11 +61,11 @@
</style>
<!-- "Compound button" variation of InCallButton.
- These buttons have the concept of two states: checked and unchecked.
- (This style is just like "InCallButton" except that we also
- clear out android:textOn and android:textOff, to avoid the default
- text label behavior of the ToggleButton class.) -->
+ These buttons have the concept of two states: checked and unchecked. This style is just
+ like "InCallButton" except that we also clear out android:background, android:textOn,
+ android:textOff, to avoid the default behavior of the ToggleButton class. -->
<style name="InCallCompoundButton" parent="InCallButton">
+ <item name="android:background">@null</item>
<item name="android:textOn">@null</item>
<item name="android:textOff">@null</item>
</style>
@@ -115,6 +115,7 @@
<item name="android:colorPrimaryDark">@color/dialer_theme_color_dark</item>
<item name="android:popupMenuStyle">@style/InCallPopupMenuStyle</item>
<item name="android:actionBarStyle">@style/InCallActionBarStyle</item>
+ <item name="android:buttonStyleToggle">@style/InCallCompoundButton</item>
</style>
<style name="Theme.CircularRevealAnimation" parent="@android:style/Theme.Material.Light">
diff --git a/src/com/android/incallui/CallButtonFragment.java b/src/com/android/incallui/CallButtonFragment.java
index bb23a881..b2d109a6 100644
--- a/src/com/android/incallui/CallButtonFragment.java
+++ b/src/com/android/incallui/CallButtonFragment.java
@@ -33,8 +33,6 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
import android.widget.CompoundButton;
import android.widget.ImageButton;
import android.widget.PopupMenu;
@@ -51,7 +49,7 @@ public class CallButtonFragment
extends BaseFragment<CallButtonPresenter, CallButtonPresenter.CallButtonUi>
implements CallButtonPresenter.CallButtonUi, OnMenuItemClickListener, OnDismissListener,
View.OnClickListener {
- private ImageButton mAudioButton;
+ private CompoundButton mAudioButton;
private ImageButton mChangeToVoiceButton;
private CompoundButton mMuteButton;
private CompoundButton mShowDialpadButton;
@@ -98,7 +96,7 @@ public class CallButtonFragment
Bundle savedInstanceState) {
final View parent = inflater.inflate(R.layout.call_button_fragment, container, false);
- mAudioButton = (ImageButton) parent.findViewById(R.id.audioButton);
+ mAudioButton = (CompoundButton) parent.findViewById(R.id.audioButton);
mAudioButton.setOnClickListener(this);
mChangeToVoiceButton = (ImageButton) parent.findViewById(R.id.changeToVoiceButton);
mChangeToVoiceButton. setOnClickListener(this);
@@ -337,8 +335,6 @@ public class CallButtonFragment
public void setMute(boolean value) {
if (mMuteButton.isSelected() != value) {
mMuteButton.setSelected(value);
- maybeSendAccessibilityEvent(mMuteButton, value ? R.string.accessibility_call_muted
- : R.string.accessibility_call_unmuted);
}
}
@@ -366,9 +362,6 @@ public class CallButtonFragment
public void setHold(boolean value) {
if (mHoldButton.isSelected() != value) {
mHoldButton.setSelected(value);
- maybeSendAccessibilityEvent(mHoldButton,
- value ? R.string.accessibility_call_put_on_hold :
- R.string.accessibility_call_removed_from_hold);
}
}
@@ -499,26 +492,7 @@ public class CallButtonFragment
refreshAudioModePopup();
if (mPrevAudioMode != mode) {
- if (mPrevAudioMode != 0) {
- int stringId = 0;
- switch (mode) {
- case AudioState.ROUTE_EARPIECE:
- stringId = R.string.accessibility_earpiece_selected;
- break;
- case AudioState.ROUTE_BLUETOOTH:
- stringId = R.string.accessibility_bluetooth_headset_selected;
- break;
- case AudioState.ROUTE_WIRED_HEADSET:
- stringId = R.string.accessibility_wired_headset_selected;
- break;
- case AudioState.ROUTE_SPEAKER:
- stringId = R.string.accessibility_speakerphone_selected;
- break;
- }
- if (stringId != 0) {
- maybeSendAccessibilityEvent(mAudioButton, stringId);
- }
- }
+ updateAudioButtonContentDescription(mode);
mPrevAudioMode = mode;
}
}
@@ -569,6 +543,7 @@ public class CallButtonFragment
public void onDismiss(PopupMenu menu) {
Log.d(this, "- onDismiss: " + menu);
mAudioModePopupVisible = false;
+ updateAudioButtons(getPresenter().getSupportedAudio());
}
/**
@@ -626,10 +601,8 @@ public class CallButtonFragment
Log.d(this, "updateAudioButtons - popup menu mode");
audioButtonEnabled = true;
+ audioButtonChecked = true;
showMoreIndicator = true;
- // The audio button is NOT a toggle in this state. (And its
- // setChecked() state is irrelevant since we completely hide the
- // btn_compound_background layer anyway.)
// Update desired layers:
if (isAudio(AudioState.ROUTE_BLUETOOTH)) {
@@ -643,6 +616,9 @@ public class CallButtonFragment
// sort of "wired headset" icon here instead of the "handset
// earpiece" icon. (Still need an asset for that, though.)
}
+
+ // The audio button is NOT a toggle in this state, so set selected to false.
+ mAudioButton.setSelected(false);
} else if (speakerSupported) {
Log.d(this, "updateAudioButtons - speaker toggle mode");
@@ -651,6 +627,7 @@ public class CallButtonFragment
// The audio button *is* a toggle in this state, and indicated the
// current state of the speakerphone.
audioButtonChecked = isAudio(AudioState.ROUTE_SPEAKER);
+ mAudioButton.setSelected(audioButtonChecked);
// update desired layers:
showToggleIndicator = true;
@@ -662,6 +639,7 @@ public class CallButtonFragment
// irrelevant since it's always disabled and unchecked.
audioButtonEnabled = false;
audioButtonChecked = false;
+ mAudioButton.setSelected(false);
// update desired layers:
showToggleIndicator = true;
@@ -679,7 +657,7 @@ public class CallButtonFragment
// Only enable the audio button if the fragment is enabled.
mAudioButton.setEnabled(audioButtonEnabled && mIsEnabled);
- mAudioButton.setSelected(audioButtonChecked);
+ mAudioButton.setChecked(audioButtonChecked);
final LayerDrawable layers = (LayerDrawable) mAudioButton.getBackground();
Log.d(this, "'layers' drawable: " + layers);
@@ -701,6 +679,38 @@ public class CallButtonFragment
}
+ /**
+ * Update the content description of the audio button.
+ */
+ private void updateAudioButtonContentDescription(int mode) {
+ int stringId = 0;
+
+ // If bluetooth is not supported, the audio buttion will toggle, so use the label "speaker".
+ // Otherwise, use the label of the currently selected audio mode.
+ if (!isSupported(AudioState.ROUTE_BLUETOOTH)) {
+ stringId = R.string.audio_mode_speaker;
+ } else {
+ switch (mode) {
+ case AudioState.ROUTE_EARPIECE:
+ stringId = R.string.audio_mode_earpiece;
+ break;
+ case AudioState.ROUTE_BLUETOOTH:
+ stringId = R.string.audio_mode_bluetooth;
+ break;
+ case AudioState.ROUTE_WIRED_HEADSET:
+ stringId = R.string.audio_mode_wired_headset;
+ break;
+ case AudioState.ROUTE_SPEAKER:
+ stringId = R.string.audio_mode_speaker;
+ break;
+ }
+ }
+
+ if (stringId != 0) {
+ mAudioButton.setContentDescription(getResources().getString(stringId));
+ }
+ }
+
private void showAudioModePopup() {
Log.d(this, "showAudioPopup()...");
@@ -764,7 +774,6 @@ public class CallButtonFragment
mShowDialpadButton.setSelected(value);
if (getActivity() != null && getActivity() instanceof InCallActivity) {
((InCallActivity) getActivity()).displayDialpad(value, animate);
- maybeSendAccessibilityEvent(mShowDialpadButton, R.string.onscreenShowDialpadText);
}
}
@@ -780,19 +789,4 @@ public class CallButtonFragment
public Context getContext() {
return getActivity();
}
-
- private void maybeSendAccessibilityEvent(View view, int stringId) {
- final Context context = getActivity();
- AccessibilityManager manager =
- (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
- if (manager != null && manager.isEnabled()) {
- AccessibilityEvent e = AccessibilityEvent.obtain();
- e.setSource(view);
- e.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
- e.setClassName(getClass().getName());
- e.setPackageName(context.getPackageName());
- e.getText().add(context.getResources().getString(stringId));
- manager.sendAccessibilityEvent(e);
- }
- }
}
diff --git a/src/com/android/incallui/CallToggleButton.java b/src/com/android/incallui/CallToggleButton.java
deleted file mode 100644
index 72c1d593..00000000
--- a/src/com/android/incallui/CallToggleButton.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2015 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.incallui;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.ToggleButton;
-
-public class CallToggleButton extends ToggleButton {
- private static final String EMPTY_STRING = "";
-
- public CallToggleButton(Context context) {
- this(context, null);
- }
-
- public CallToggleButton(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public CallToggleButton(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public CallToggleButton(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- /**
- * Ignore the content description so it is not read by Talkback. When clicked, we expect
- * {@link CallButtonFragment#maybeSendAccessibilityEvent} to dispatch an accessibility event
- * with the text for Talkback to read.
- */
- @Override
- public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
- super.onInitializeAccessibilityEvent(event);
- event.setContentDescription(EMPTY_STRING);
- }
-}