am eb178890: Merge " Adding a code sample for implementing accessibility in a custom view." into ics-mr1

* commit 'eb1788903298fc12ac800fe8fcfc6b7adec7b258':
  Adding a code sample for implementing accessibility in a custom view.
This commit is contained in:
Svetoslav Ganov
2011-11-30 18:20:12 -08:00
committed by Android Git Automerger
6 changed files with 359 additions and 4 deletions

View File

@@ -542,7 +542,7 @@
</activity>
<!-- ============================ -->
<!-- Accessibility examples strings -->
<!-- Accessibility examples -->
<!-- ============================ -->
<activity android:name=".accessibility.ClockBackActivity"
@@ -580,6 +580,15 @@
android:resource="@xml/taskbackconfig" />
</service>
<activity android:name=".accessibility.CustomViewAccessibilityActivity"
android:label="@string/accessibility_custom_view"
android:enabled="@bool/atLeastIceCreamSandwich">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<!-- Instrumentation Samples -->
<activity android:name=".app.LocalSample" android:label="@string/activity_local_sample">

View File

@@ -39,6 +39,10 @@ support</a></li>
<li><a
href="src/com/example/android/apis/accessibility/TaskBackService.html">Window
Querying Accessibility Service</a></li>
<li><a
href="src/com/example/android/apis/accessibility/CustomViewAccessibilityActivity.html">Custom View
Accessibility</a></li>
</ul>
</div>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="50dip"
android:text="@string/accessibility_custom_view_instructions">
</TextView>
<view
class="com.example.android.apis.accessibility.CustomViewAccessibilityActivity$AccessibleCompoundButtonInheritance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dip"
android:clickable="true" >
</view>
<view
class="com.example.android.apis.accessibility.CustomViewAccessibilityActivity$AccessibleCompoundButtonComposition"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dip"
android:clickable="true" >
</view>
</LinearLayout>

View File

@@ -1296,7 +1296,7 @@
<string name="accessibility_service_label">ClockBack</string>
<string name="accessibility_service_instructions">
1. Enable TalkBack (Settings -> Accessibility -> TalkBack).
\n\n2. Enable Explore-byTouch (Settings -> Accessibility -> Explore by Touch).
\n\n2. Enable Explore-by-Touch (Settings -> Accessibility -> Explore by Touch).
\n\n3. Touch explore the Clock application and the home screen.
\n\n4. Go to the Clock application and change the time of an alarm.
\n\n5. Enable ClockBack (Settings -> Accessibility -> ClockBack).
@@ -1316,10 +1316,19 @@
<string name="accessibility_query_window_description">Task App Accessibility Service</string>
<string name="accessibility_query_window_instructions">
1. Enable QueryBack (Settings -> Accessibility -> QueryBack).
\n\n2. Enable Explore-byTouch (Settings -> Accessibility -> Explore by Touch).
\n\n2. Enable Explore-by-Touch (Settings -> Accessibility -> Explore by Touch).
\n\n3. Touch explore the list.
</string>
<string name="accessibility_custom_view">Accessibility/Custom View</string>
<string name="accessibility_custom_view_instructions">
1. Enable TalkBack (Settings -> Accessibility -> TalkBack).
\n\n2. Enable Explore-by-Touch (Settings -> Accessibility -> Explore by Touch).
\n\n3. Touch explore/poke the buttons.
</string>
<string name="accessibility_custom_on">On</string>
<string name="accessibility_custom_off">Off</string>
<string name="task_name">Task</string>
<string name="task_complete_template">Task %1$s %2$s</string>
<string name="task_complete">is complete</string>

View File

@@ -0,0 +1,280 @@
/*
* Copyright (C) 2011 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.example.android.apis.accessibility;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Build;
import android.os.Bundle;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import com.example.android.apis.R;
/**
* Demonstrates how to implement accessibility support of custom views. Custom view
* is a tailored widget developed by extending the base classes in the android.view
* package. This sample shows how to implement the accessibility behavior via both
* inheritance (non backwards compatible) and composition (backwards compatible).
* <p>
* While the Android framework has a diverse portfolio of views tailored for various
* use cases, sometimes a developer needs a specific functionality not implemented
* by the standard views. A solution is to write a custom view that extends one the
* base view classes. While implementing the desired functionality a developer should
* also implement accessibility support for that new functionality such that
* disabled users can leverage it.
* </p>
*/
public class CustomViewAccessibilityActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_view_accessibility);
}
/**
* Demonstrates how to enhance the accessibility support via inheritance.
* <p>
* <strong>Note:</strong> Using inheritance may break your application's
* backwards compatibility. In particular, overriding a method that takes as
* an argument or returns a class not present on an older platform
* version will prevent your application from running on that platform.
* For example, {@link AccessibilityNodeInfo} was introduced in
* {@link Build.VERSION_CODES#ICE_CREAM_SANDWICH API 14}, thus overriding
* {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
* View.onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}
* will prevent you application from running on a platform older than
* {@link Build.VERSION_CODES#ICE_CREAM_SANDWICH API 14}.
* </p>
*/
public static class AccessibleCompoundButtonInheritance extends BaseToggleButton {
public AccessibleCompoundButtonInheritance(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
// We called the super implementation to let super classes
// set appropriate event properties. Then we add the new property
// (checked) which is not supported by a super class.
event.setChecked(isChecked());
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
// We called the super implementation to let super classes set
// appropriate info properties. Then we add our properties
// (checkable and checked) which are not supported by a super class.
info.setCheckable(true);
info.setChecked(isChecked());
// Very often you will need to add only the text on the custom view.
CharSequence text = getText();
if (!TextUtils.isEmpty(text)) {
info.setText(text);
}
}
@Override
public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
super.onPopulateAccessibilityEvent(event);
// We called the super implementation to populate its text to the
// event. Then we add our text not present in a super class.
// Very often you will need to add only the text on the custom view.
CharSequence text = getText();
if (!TextUtils.isEmpty(text)) {
event.getText().add(text);
}
}
}
/**
* Demonstrates how to enhance the accessibility support via composition.
* <p>
* <strong>Note:</strong> Using composition ensures that your application is
* backwards compatible. The android-support-v4 library has API that allow
* using the accessibility APIs in a backwards compatible manner.
* </p>
*/
public static class AccessibleCompoundButtonComposition extends BaseToggleButton {
public AccessibleCompoundButtonComposition(Context context, AttributeSet attrs) {
super(context, attrs);
tryInstallAccessibilityDelegate();
}
public void tryInstallAccessibilityDelegate() {
// If the API version of the platform we are running is too old
// and does not support the AccessibilityDelegate APIs, do not
// call View.setAccessibilityDelegate(AccessibilityDelegate) or
// refer to AccessibilityDelegate, otherwise an exception will
// be thrown.
// NOTE: The android-support-v4 library contains APIs the enable
// using the accessibility APIs in a backwards compatible fashion.
if (Build.VERSION.SDK_INT < 14) {
return;
}
// AccessibilityDelegate allows clients to override its methods that
// correspond to the accessibility methods in View and register the
// delegate in the View essentially injecting the accessibility support.
setAccessibilityDelegate(new AccessibilityDelegate() {
@Override
public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(host, event);
// We called the super implementation to let super classes
// set appropriate event properties. Then we add the new property
// (checked) which is not supported by a super class.
event.setChecked(isChecked());
}
@Override
public void onInitializeAccessibilityNodeInfo(View host,
AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(host, info);
// We called the super implementation to let super classes set
// appropriate info properties. Then we add our properties
// (checkable and checked) which are not supported by a super class.
info.setCheckable(true);
info.setChecked(isChecked());
// Very often you will need to add only the text on the custom view.
CharSequence text = getText();
if (!TextUtils.isEmpty(text)) {
info.setText(text);
}
}
@Override
public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
super.onPopulateAccessibilityEvent(host, event);
// We called the super implementation to populate its text to the
// event. Then we add our text not present in a super class.
// Very often you will need to add only the text on the custom view.
CharSequence text = getText();
if (!TextUtils.isEmpty(text)) {
event.getText().add(text);
}
}
});
}
}
/**
* This is a base toggle button class whose accessibility is not tailored
* to reflect the new functionality it implements.
* <p>
* <strong>Note:</strong> This is not a sample implementation of a toggle
* button, rather a simple class needed to demonstrate how to refine the
* accessibility support of a custom View.
* </p>
*/
private static class BaseToggleButton extends View {
private boolean mChecked;
private CharSequence mTextOn;
private CharSequence mTextOff;
private Layout mOnLayout;
private Layout mOffLayout;
private TextPaint mTextPaint;
public BaseToggleButton(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.buttonStyle);
}
public BaseToggleButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
TypedValue typedValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.textSize, typedValue, true);
final int textSize = (int) typedValue.getDimension(
context.getResources().getDisplayMetrics());
mTextPaint.setTextSize(textSize);
context.getTheme().resolveAttribute(android.R.attr.textColorPrimary, typedValue, true);
final int textColor = context.getResources().getColor(typedValue.resourceId);
mTextPaint.setColor(textColor);
mTextOn = context.getString(R.string.accessibility_custom_on);
mTextOff = context.getString(R.string.accessibility_custom_off);
}
public boolean isChecked() {
return mChecked;
}
public CharSequence getText() {
return mChecked ? mTextOn : mTextOff;
}
@Override
public boolean performClick() {
final boolean handled = super.performClick();
if (!handled) {
mChecked ^= true;
invalidate();
}
return handled;
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mOnLayout == null) {
mOnLayout = makeLayout(mTextOn);
}
if (mOffLayout == null) {
mOffLayout = makeLayout(mTextOff);
}
final int minWidth = Math.max(mOnLayout.getWidth(), mOffLayout.getWidth())
+ getPaddingLeft() + getPaddingRight();
final int minHeight = Math.max(mOnLayout.getHeight(), mOffLayout.getHeight())
+ getPaddingLeft() + getPaddingRight();
setMeasuredDimension(resolveSizeAndState(minWidth, widthMeasureSpec, 0),
resolveSizeAndState(minHeight, heightMeasureSpec, 0));
}
private Layout makeLayout(CharSequence text) {
return new StaticLayout(text, mTextPaint,
(int) Math.ceil(Layout.getDesiredWidth(text, mTextPaint)),
Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.translate(getPaddingLeft(), getPaddingRight());
Layout switchText = mChecked ? mOnLayout : mOffLayout;
switchText.draw(canvas);
canvas.restore();
}
}
}

View File

@@ -9,7 +9,7 @@
how to provide dynamic, context-dependent feedback &mdash; feedback type changes depending on
the ringer mode.
</dd>
<dt>
</dl>
<dl>
<dt><a href="TaskBackService.html">Window Querying Accessibility Service</a></dt>
@@ -21,3 +21,12 @@
AccessibilityRecords.
</dd>
</dl>
<dl>
<dt><a href="CustomViewAccessibilityActivity.html">Custom View Accessibility</a></dt>
<dd>Demonstrates how to implement accessibility support of custom views. Custom view
is a tailored widget developed by extending the base classes in the android.view
package. This sample shows how to implement the accessibility behavior via both
inheritance (non backwards compatible) and composition (backwards compatible).
</dd>
</dl>