Create BasicAccessibility sample
Sample to demonstrate basic changes to an application to support
accessibility. Covers contentDescription, nextFocusUp/Down,
and adding AccessibilityEvent support to a custom view.
Change-Id: I99b7d9b469a352d7c73e1aa95de16b4cd4799ac0
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/build.gradle b/ui/accessibility/BasicAccessibility/BasicAccessibility/build.gradle
new file mode 100644
index 0000000..f8f1c8a
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/build.gradle
@@ -0,0 +1,23 @@
+buildscript {
+ repositories {
+ maven { url 'http://repo1.maven.org/maven2' }
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:0.4'
+ }
+}
+apply plugin: 'android'
+
+dependencies {
+ compile files('libs/android-support-v4.jar')
+}
+
+android {
+ compileSdkVersion 17
+ buildToolsVersion "17.0.0"
+
+ defaultConfig {
+ minSdkVersion 7
+ targetSdkVersion 16
+ }
+}
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/libs/android-support-v4.jar b/ui/accessibility/BasicAccessibility/BasicAccessibility/libs/android-support-v4.jar
new file mode 100644
index 0000000..428bdbc
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/libs/android-support-v4.jar
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/AndroidManifest.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..3c0e66a
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.ui.accessibility.BasicAccessibility"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="11"
+ android:targetSdkVersion="16" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name="com.example.android.ui.accessibility.BasicAccessibility.MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/ic_launcher-web.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/ic_launcher-web.png
new file mode 100644
index 0000000..6967d3e
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/ic_launcher-web.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/java/com/example/android/ui/accessibility/BasicAccessibility/DialView.java b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/java/com/example/android/ui/accessibility/BasicAccessibility/DialView.java
new file mode 100644
index 0000000..1fc5e0c
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/java/com/example/android/ui/accessibility/BasicAccessibility/DialView.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2013 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.ui.accessibility.BasicAccessibility;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+
+/**
+ * Custom view to demonstrate accessibility.
+ *
+ * <p>This view does not use any framework widgets, so does not get any accessibility features
+ * automatically. Instead, we use {@link AccessibilityEvent} to provide accessibility hints to
+ * the OS.
+ *
+ * <p>For example, if TalkBack is enabled, users will be able to receive spoken feedback as they
+ * interact with this view.
+ *
+ * <p>More generally, this view renders a multi-position "dial" that can be used to select a value
+ * between 1 and 4. Each time the dial is clicked, the next position will be selected (modulo
+ * the maximum number of positions).
+ */
+public class DialView extends View {
+ private static int SELECTION_COUNT = 4;
+
+ private static float FONT_SIZE = 40f;
+ private float mWidth;
+ private float mHeight;
+ private float mWidthPadded;
+ private float mHeightPadded;
+ private Paint mTextPaint;
+ private Paint mDialPaint;
+ private float mRadius;
+ private int mActiveSelection;
+
+ /**
+ * Constructor that is called when inflating a view from XML. This is called
+ * when a view is being constructed from an XML file, supplying attributes
+ * that were specified in the XML file.
+ *
+ * <p>In our case, this constructor just calls init().
+ *
+ * @param context The Context the view is running in, through which it can
+ * access the current theme, resources, etc.
+ * @param attrs The attributes of the XML tag that is inflating the view.
+ * @see #View(android.content.Context, android.util.AttributeSet, int)
+ */
+ public DialView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ /**
+ * Helper method to initialize instance variables. Called by constructor.
+ */
+ private void init() {
+ // Paint styles used for rendering are created here, rather than at render-time. This
+ // is a performance optimization, since onDraw() will get called frequently.
+ mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mTextPaint.setColor(Color.BLACK);
+ mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+ mTextPaint.setTextSize(FONT_SIZE);
+
+ mDialPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mDialPaint.setColor(Color.GRAY);
+
+ // Initialize current selection. This will store where the dial's "indicator" is pointing.
+ mActiveSelection = 0;
+
+ // Setup onClick listener for this view. Rotates between each of the different selection
+ // states on each click.
+ //
+ // Notice that we call sendAccessibilityEvent here. Some AccessibilityEvents are generated
+ // by the system. However, custom views will typically need to send events manually as the
+ // user interacts with the view. The type of event sent will vary, depending on the nature
+ // of the view and how the user interacts with it.
+ //
+ // In this case, we are sending TYPE_VIEW_SELECTED rather than TYPE_VIEW_CLICKED, because
+ // clicking on this view selects a new value.
+ //
+ // We will give our AccessibilityEvent further information about the state of the view in
+ // onPopulateAccessibilityEvent(), which will be called automatically by the system
+ // for each AccessibilityEvent.
+ setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Rotate selection to the next valid choice.
+ mActiveSelection = (mActiveSelection + 1) % SELECTION_COUNT;
+ // Send an AccessibilityEvent, since the user has interacted with the view.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+ // Redraw the entire view. (Inefficient, but this is sufficient for demonstration
+ // purposes.)
+ invalidate();
+ }
+ });
+ }
+
+ /**
+ * This is where a View should populate outgoing accessibility events with its text content.
+ * While this method is free to modify event attributes other than text content, doing so
+ * should normally be performed in
+ * {@link #onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent)}.
+ * <p/>
+ * <p>Note that the behavior of this method will typically vary, depending on the type of
+ * accessibility event is passed into it. The allowed values also very, and are documented
+ * in {@link android.view.accessibility.AccessibilityEvent}.
+ * <p/>
+ * <p>Typically, this is where you'll describe the state of your custom view. You may also
+ * want to provide custom directions when the user has focused your view.
+ *
+ * @param event The accessibility event which to populate.
+ */
+ // BEGIN_INCLUDE (on_populate_accessibility_event)
+ @Override
+ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event);
+
+ // Detect what type of accessibility event is being passed in.
+ int eventType = event.getEventType();
+
+ // Common case: The user has interacted with our view in some way. State may or may not
+ // have been changed. Read out the current status of the view.
+ //
+ // We also set some other metadata which is not used by TalkBack, but could be used by
+ // other TTS engines.
+ if (eventType == AccessibilityEvent.TYPE_VIEW_SELECTED ||
+ eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
+ event.getText().add("Mode selected: " + Integer.toString(mActiveSelection + 1) + ".");
+ event.setItemCount(SELECTION_COUNT);
+ event.setCurrentItemIndex(mActiveSelection);
+ }
+
+ // When a user first focuses on our view, we'll also read out some simple instructions to
+ // make it clear that this is an interactive element.
+ if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
+ event.getText().add("Tap to change.");
+ }
+ }
+ // END_INCLUDE (on_populate_accessibility_event)
+
+ /**
+ * This is called during layout when the size of this view has changed. If
+ * you were just added to the view hierarchy, you're called with the old
+ * values of 0.
+ *
+ * <p>This is where we determine the drawing bounds for our custom view.
+ *
+ * @param w Current width of this view.
+ * @param h Current height of this view.
+ * @param oldw Old width of this view.
+ * @param oldh Old height of this view.
+ */
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ // Account for padding
+ float xPadding = (float) (getPaddingLeft() + getPaddingRight());
+ float yPadding = (float) (getPaddingTop() + getPaddingBottom());
+
+ // Compute available width/height
+ mWidth = w;
+ mHeight = h;
+ mWidthPadded = w - xPadding;
+ mHeightPadded = h - yPadding;
+ mRadius = (float) (Math.min(mWidth, mHeight) / 2 * 0.8);
+ }
+
+ /**
+ * Render view content.
+ *
+ * <p>We render an outer grey circle to serve as our "dial", and then render a smaller black
+ * circle to server as our indicator. The position for the indicator is determined based
+ * on mActiveSelection.
+ *
+ * @param canvas the canvas on which the background will be drawn
+ */
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ // Draw dial
+ canvas.drawCircle(mWidth / 2, mHeight / 2, (float) mRadius, mDialPaint);
+
+ // Draw text labels
+ final float labelRadius = mRadius + 10;
+ for (int i = 0; i < SELECTION_COUNT; i++) {
+ float[] xyData = computeXYForPosition(i, labelRadius);
+ float x = xyData[0];
+ float y = xyData[1];
+ canvas.drawText(Integer.toString(i + 1), x, y, mTextPaint);
+ }
+
+ // Draw indicator mark
+ final float markerRadius = mRadius - 35;
+ float[] xyData = computeXYForPosition(mActiveSelection, markerRadius);
+ float x = xyData[0];
+ float y = xyData[1];
+ canvas.drawCircle(x, y, 20, mTextPaint);
+ }
+
+ /**
+ * Compute the X/Y-coordinates for a label or indicator, given the position number and radius
+ * where the label should be drawn.
+ *
+ * @param pos Zero based position index
+ * @param radius Radius where label/indicator is to be drawn.
+ * @return 2-element array. Element 0 is X-coordinate, element 1 is Y-coordinate.
+ */
+ private float[] computeXYForPosition(final int pos, final float radius) {
+ float[] result = new float[2];
+ Double startAngle = Math.PI * (9 / 8d); // Angles are in radiansq
+ Double angle = startAngle + (pos * (Math.PI / 4));
+ result[0] = (float) (radius * Math.cos(angle)) + (mWidth / 2);
+ result[1] = (float) (radius * Math.sin(angle)) + (mHeight / 2);
+ return result;
+ }
+}
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/java/com/example/android/ui/accessibility/BasicAccessibility/MainActivity.java b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/java/com/example/android/ui/accessibility/BasicAccessibility/MainActivity.java
new file mode 100644
index 0000000..869301d
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/java/com/example/android/ui/accessibility/BasicAccessibility/MainActivity.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2013 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.ui.accessibility.BasicAccessibility;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Basic activity class.
+ *
+ * <p>Responsible for rendering layout, and displaying some toasts to give buttons feedback.
+ * There's nothing terribly interesting in this class. All the interesting stuff is in
+ * res/layout/activity_main.xml and {@link DialView}.
+ */
+public class MainActivity extends Activity {
+
+ /**
+ * Standard onCreate() implementation. Sets R.layout.activity_main as the layout.
+ */
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
+}
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_action_discard.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_action_discard.png
new file mode 100644
index 0000000..ece5ad8
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_action_discard.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_action_info.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_action_info.png
new file mode 100644
index 0000000..da65dea
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_action_info.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_launcher.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..6c0b5ee
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/partly_cloudy.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/partly_cloudy.png
new file mode 100644
index 0000000..b1b380c
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-hdpi/partly_cloudy.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_action_discard.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_action_discard.png
new file mode 100644
index 0000000..93483b6
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_action_discard.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_action_info.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_action_info.png
new file mode 100644
index 0000000..7f7e0a3
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_action_info.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_launcher.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..4ce0b82
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_action_discard.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_action_discard.png
new file mode 100644
index 0000000..94f7c8c
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_action_discard.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_action_info.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_action_info.png
new file mode 100644
index 0000000..4ede9ce
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_action_info.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..6ded707
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..74ae891
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/layout/activity_main.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..394c72f
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/layout/activity_main.xml
@@ -0,0 +1,206 @@
+<!--
+Copyright (C) 2013 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"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_horizontal">
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="false">
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ tools:context=".MainActivity"
+ >
+
+ <!-- Notice the presence of nextFocusDown/nextFocusUp on the elements below. You can
+ also use nextFocusLeft/nextFocusRight. This tells the system in what order elements
+ should be navigated through. If not present, the system will make a guess based on
+ element location in the layout. -->
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Buttons"
+ android:id="@+id/buttonsLabel"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:nextFocusDown="@+id/composeButton"/>
+
+ <!-- This is a regular, text-based button. No contentDescription is needed, since the
+ text field sufficiently describes the action performed. -->
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/composeButtonLabel"
+ android:id="@+id/composeButton"
+ android:layout_below="@+id/buttonsLabel"
+ android:layout_alignLeft="@+id/buttonsLabel"
+ android:nextFocusUp="@+id/buttonsLabel"
+ android:nextFocusDown="@+id/checkboxesLabel"
+ />
+
+ <!-- The next two buttons are different types of image-based buttons. -->
+
+ <!-- BEGIN_INCLUDE (image_content_description) -->
+ <!-- Adding a contentDescription is needed for accessibility, since no text is present.
+ Since the contentDescription is read verbatim, you may want to be a bit more
+ descriptive than usual, such as adding "button" to the end of your description, if
+ appropriate. -->
+ <ImageButton
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/discardButton"
+ android:layout_alignTop="@+id/composeButton"
+ android:layout_toRightOf="@+id/composeButton"
+ android:src="@drawable/ic_action_discard"
+ android:layout_alignBottom="@+id/composeButton"
+ android:contentDescription="@string/discardButtonDescription"
+ android:scaleType="fitCenter"
+ android:nextFocusUp="@+id/buttonsLabel"
+ android:nextFocusDown="@+id/checkboxesLabel"
+ />
+ <!-- END_INCLUDE (image_content_description) -->
+
+ <ImageButton
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/infoButton"
+ android:layout_alignTop="@+id/discardButton"
+ android:layout_toRightOf="@+id/discardButton"
+ android:src="@drawable/ic_action_info"
+ android:layout_alignBottom="@+id/discardButton"
+ android:layout_alignRight="@+id/hyperspaceCheckbox"
+ android:scaleType="fitCenter"
+ android:background="?android:selectableItemBackground"
+ android:padding="5dp"
+ android:contentDescription="@string/infoButtonDescription"
+ android:nextFocusUp="@+id/buttonsLabel"
+ android:nextFocusDown="@+id/checkboxesLabel"
+ />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/checkboxesLabel"
+ android:id="@+id/checkboxesLabel"
+ android:layout_below="@+id/composeButton"
+ android:layout_alignLeft="@+id/composeButton"
+ android:nextFocusUp="@+id/composeButton"
+ android:nextFocusDown="@+id/jetpackCheckbox"
+ />
+
+ <!-- Like a text-based button, checkboxes with text will often work correctly as-is.
+ If your checkboxes do not have a text attribute, you will need to add a
+ contentDescriptoin. -->
+ <CheckBox
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/jetpackCheckboxLabel"
+ android:id="@+id/jetpackCheckbox"
+ android:layout_below="@+id/checkboxesLabel"
+ android:layout_alignLeft="@+id/checkboxesLabel"
+ android:checked="false"
+ android:nextFocusUp="@+id/checkboxesLabel"
+ android:nextFocusDown="@+id/hyperspaceCheckbox"
+ />
+
+ <CheckBox
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/hyperspaceCheckboxLabel"
+ android:id="@+id/hyperspaceCheckbox"
+ android:layout_below="@+id/jetpackCheckbox"
+ android:layout_alignLeft="@+id/jetpackCheckbox"
+ android:checked="false"
+ android:nextFocusUp="@+id/jetpackCheckbox"
+ android:nextFocusDown="@+id/imagesAndTextLabel"
+ />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/imagesAndTextLabel"
+ android:id="@+id/imagesAndTextLabel"
+ android:layout_below="@+id/hyperspaceCheckbox"
+ android:layout_alignLeft="@+id/hyperspaceCheckbox"
+ android:nextFocusUp="@+id/hyperspaceCheckbox"
+ android:nextFocusDown="@+id/partlyCloudImage"
+ />
+
+ <!-- Images should have a contentDescription if they convey any meaningful
+ information. Images that are purely decorative may not need a contentDescription,
+ however. -->
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/partlyCloudyImage"
+ android:layout_below="@+id/imagesAndTextLabel"
+ android:layout_alignLeft="@+id/imagesAndTextLabel"
+ android:src="@drawable/partly_cloudy"
+ android:contentDescription="@string/partlyCloudyDescription"
+ android:layout_alignRight="@+id/discardButton"
+ android:nextFocusUp="@+id/imagesAndTextLabel"
+ android:nextFocusDown="@+id/customViewLabel"
+ />
+
+ <!-- TextViews are typically self describing, so do not need extra modifications. -->
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:text="@string/temperature"
+ android:textSize="60sp"
+ android:id="@+id/temperatureText"
+ android:layout_alignTop="@+id/partlyCloudyImage"
+ android:layout_toRightOf="@+id/partlyCloudyImage"
+ android:layout_alignBottom="@+id/partlyCloudyImage"
+ android:gravity="center_vertical"
+ android:nextFocusUp="@+id/imagesAndTextLabel"
+ android:nextFocusDown="@+id/customViewLabel"
+ />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/customViewLabel"
+ android:id="@+id/customViewLabel"
+ android:layout_below="@+id/partlyCloudyImage"
+ android:layout_alignLeft="@+id/partlyCloudyImage"
+ android:nextFocusUp="@+id/partlyCloudImage"
+ android:nextFocusDown="@+id/dialView"
+ />
+
+ <!-- Custom views require additonal code changes. See DialView.java for more
+ details. -->
+ <com.example.android.ui.accessibility.BasicAccessibility.DialView
+ android:layout_width="200dp"
+ android:layout_height="200dp"
+ android:id="@+id/dialView"
+ android:layout_below="@+id/customViewLabel"
+ android:layout_alignLeft="@+id/partlyCloudyImage"
+ android:nextFocusUp="@+id/customViewLabel"
+ />
+
+ </RelativeLayout>
+ </ScrollView>
+</LinearLayout>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-sw600dp/dimens.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-sw600dp/dimens.xml
new file mode 100644
index 0000000..d0946b3
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-sw600dp/dimens.xml
@@ -0,0 +1,20 @@
+<!--
+Copyright (C) 2013 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.
+-->
+
+<resources>
+ <!-- Customize dimensions originally defined in res/values/dimens.xml (such as
+ screen margins) for sw600dp devices (e.g. 7" tablets) here. -->
+</resources>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-sw720dp-land/dimens.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-sw720dp-land/dimens.xml
new file mode 100644
index 0000000..2c2d431
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-sw720dp-land/dimens.xml
@@ -0,0 +1,21 @@
+<!--
+Copyright (C) 2013 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.
+-->
+
+<resources>
+ <!-- Customize dimensions originally defined in res/values/dimens.xml (such as
+ screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here. -->
+ <dimen name="activity_horizontal_margin">128dp</dimen>
+</resources>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-v11/styles.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-v11/styles.xml
new file mode 100644
index 0000000..5b1a3f2
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-v11/styles.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2013 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.
+-->
+
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-v14/styles.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-v14/styles.xml
new file mode 100644
index 0000000..b16c97b
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values-v14/styles.xml
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2013 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.
+-->
+
+<resources>
+
+ <!--
+ Base application theme for API 14+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/dimens.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..a5e4ebe
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/dimens.xml
@@ -0,0 +1,20 @@
+<!--
+Copyright (C) 2013 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.
+-->
+<resources>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/strings.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/strings.xml
new file mode 100644
index 0000000..57b8e49
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2013 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.
+-->
+
+<resources>
+
+ <string name="app_name" >Accessibility Sample</string>
+ <string name="composeButtonPressed">(Compose button pressed.)</string>
+ <string name="discardButtonPressed">(Discard button pressed.)</string>
+ <string name="infoButtonPressed">(Info button pressed.)</string>
+ <string name="composeButtonLabel">Compose</string>
+ <string name="discardButtonDescription">Discard Button</string>
+ <string name="infoButtonDescription">Info Button</string>
+ <string name="partlyCloudyDescription">Partly Cloudy</string>
+ <string name="checkboxesLabel">Checkboxes</string>
+ <string name="jetpackCheckboxLabel">Enable Jetpack</string>
+ <string name="hyperspaceCheckboxLabel">Enable Hyperspace Engines</string>
+ <string name="imagesAndTextLabel">Images & Text</string>
+ <string name="temperature">53 °F</string>
+ <string name="customViewLabel">Custom View</string>
+</resources>
diff --git a/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/styles.xml b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/styles.xml
new file mode 100644
index 0000000..b0e6075
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/BasicAccessibility/src/main/res/values/styles.xml
@@ -0,0 +1,36 @@
+<!--
+Copyright (C) 2013 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.
+-->
+
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
diff --git a/ui/accessibility/BasicAccessibility/build.gradle b/ui/accessibility/BasicAccessibility/build.gradle
new file mode 100644
index 0000000..495c503
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/build.gradle
@@ -0,0 +1 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
diff --git a/ui/accessibility/BasicAccessibility/settings.gradle b/ui/accessibility/BasicAccessibility/settings.gradle
new file mode 100644
index 0000000..1c4fa86
--- /dev/null
+++ b/ui/accessibility/BasicAccessibility/settings.gradle
@@ -0,0 +1 @@
+include ':BasicAccessibility'