aboutsummaryrefslogtreecommitdiff
path: root/input/autofill
diff options
context:
space:
mode:
authorDouglas Sigelbaum <sigelbaum@google.com>2017-06-21 18:20:53 -0700
committerDouglas Sigelbaum <sigelbaum@google.com>2017-08-31 21:05:35 +0000
commit313fb2327ba92aa3771f0d2a807be7149425bb39 (patch)
treee536f754e32a6035ee828a95def20f1d14f22000 /input/autofill
parent71556a6f6969b258fbcfd5bbc01ac32bb03d9674 (diff)
downloadandroid-313fb2327ba92aa3771f0d2a807be7149425bb39.tar.gz
Autofill sample: add credit card expiration compound view example.
Bug: 38182790 Test: manual Change-Id: Ib611578b811715103666233f84720ef2bb184c00
Diffstat (limited to 'input/autofill')
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/AndroidManifest.xml3
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CreditCardCompoundViewActivity.java71
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CreditCardExpirationDateView.java126
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.java8
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/res/drawable/ic_view_module_black_24dp.xml9
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/res/layout/activity_main.xml8
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/res/layout/cc_exp_date.xml58
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/res/layout/credit_card_compound_view_activity.xml135
-rw-r--r--input/autofill/AutofillFramework/Application/src/main/res/values/strings.xml10
-rw-r--r--input/autofill/AutofillFramework/kotlinApp/Application/src/main/AndroidManifest.xml7
-rw-r--r--input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CreditCardCompoundViewActivity.kt56
-rw-r--r--input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CreditCardExpirationDateView.kt107
-rw-r--r--input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.kt54
-rw-r--r--input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/drawable/ic_view_module_black_24dp.xml9
-rw-r--r--input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/activity_main.xml8
-rw-r--r--input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/cc_exp_date.xml58
-rw-r--r--input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/credit_card_compound_view_activity.xml135
-rw-r--r--input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/values/strings.xml10
18 files changed, 833 insertions, 39 deletions
diff --git a/input/autofill/AutofillFramework/Application/src/main/AndroidManifest.xml b/input/autofill/AutofillFramework/Application/src/main/AndroidManifest.xml
index f63fb53a..2470645c 100644
--- a/input/autofill/AutofillFramework/Application/src/main/AndroidManifest.xml
+++ b/input/autofill/AutofillFramework/Application/src/main/AndroidManifest.xml
@@ -49,6 +49,9 @@
<activity
android:name=".app.EmailComposeActivity"
android:taskAffinity=".EmailComposeActivity" />
+ <activity
+ android:name=".app.CreditCardCompoundViewActivity"
+ android:taskAffinity=".CreditCardCompoundViewActivity" />
<!--
Including launcher icon for Autofill Settings to convenience.
Not necessary for a real service.
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CreditCardCompoundViewActivity.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CreditCardCompoundViewActivity.java
new file mode 100644
index 00000000..9ff3a74b
--- /dev/null
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CreditCardCompoundViewActivity.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2017 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.autofillframework.app;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+import android.widget.EditText;
+
+import com.example.android.autofillframework.R;
+
+public class CreditCardCompoundViewActivity extends AppCompatActivity {
+
+ private CreditCardExpirationDateView mCcExpDateView;
+ private EditText mCcExpNumber;
+ public static Intent getStartActivityIntent(Context context) {
+ Intent intent = new Intent(context, CreditCardCompoundViewActivity.class);
+ return intent;
+ }
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.credit_card_compound_view_activity);
+ mCcExpDateView = findViewById(R.id.creditCardExpirationView);
+ mCcExpNumber = findViewById(R.id.creditCardNumberField);
+ findViewById(R.id.submitButton).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ submit();
+ }
+ });
+ findViewById(R.id.clearButton).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ resetFields();
+ }
+ });
+ }
+
+ private void resetFields() {
+ mCcExpDateView.reset();
+ mCcExpNumber.setText("");
+ }
+
+ /**
+ * Launches new Activity and finishes, triggering an autofill save request if the user entered
+ * any new data.
+ */
+ private void submit() {
+ Intent intent = WelcomeActivity.getStartActivityIntent(this);
+ startActivity(intent);
+ finish();
+ }
+}
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CreditCardExpirationDateView.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CreditCardExpirationDateView.java
new file mode 100644
index 00000000..22a3777f
--- /dev/null
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/CreditCardExpirationDateView.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2017 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.autofillframework.app;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillValue;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.FrameLayout;
+import android.widget.Spinner;
+
+import com.example.android.autofillframework.R;
+
+import java.util.Calendar;
+
+public class CreditCardExpirationDateView extends FrameLayout {
+
+ private static final int CC_EXP_YEARS_COUNT = 5;
+
+ private final String[] mYears = new String[CC_EXP_YEARS_COUNT];
+
+ private Spinner mCcExpMonthSpinner;
+ private Spinner mCcExpYearSpinner;
+
+ public CreditCardExpirationDateView(@NonNull Context context) {
+ this(context, null);
+ }
+
+ public CreditCardExpirationDateView(@NonNull Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public CreditCardExpirationDateView(@NonNull Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public CreditCardExpirationDateView(@NonNull final Context context,
+ @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ View rootView = LayoutInflater.from(context).inflate(R.layout.cc_exp_date, this);
+ mCcExpMonthSpinner = rootView.findViewById(R.id.ccExpMonth);
+ mCcExpYearSpinner = rootView.findViewById(R.id.ccExpYear);
+ setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS);
+ ArrayAdapter<CharSequence> monthAdapter = ArrayAdapter.createFromResource
+ (context, R.array.month_array, android.R.layout.simple_spinner_item);
+ monthAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ mCcExpMonthSpinner.setAdapter(monthAdapter);
+ int year = Calendar.getInstance().get(Calendar.YEAR);
+ for (int i = 0; i < mYears.length; i++) {
+ mYears[i] = Integer.toString(year + i);
+ }
+ mCcExpYearSpinner.setAdapter(new ArrayAdapter<>(context,
+ android.R.layout.simple_spinner_item, mYears));
+ AdapterView.OnItemSelectedListener onItemSelectedListener =
+ new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ context.getSystemService(AutofillManager.class)
+ .notifyValueChanged(CreditCardExpirationDateView.this);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ };
+ mCcExpMonthSpinner.setOnItemSelectedListener(onItemSelectedListener);
+ mCcExpYearSpinner.setOnItemSelectedListener(onItemSelectedListener);
+ }
+
+ @Override
+ public AutofillValue getAutofillValue() {
+ Calendar calendar = Calendar.getInstance();
+ // Set hours, minutes, seconds, and millis to 0 to ensure getAutofillValue() == the value
+ // set by autofill(). Without this line, the view will not turn yellow when updated.
+ calendar.clear();
+ int year = Integer.parseInt(mCcExpYearSpinner.getSelectedItem().toString());
+ int month = mCcExpMonthSpinner.getSelectedItemPosition();
+ calendar.set(Calendar.YEAR, year);
+ calendar.set(Calendar.MONTH, month);
+ long unixTime = calendar.getTimeInMillis();
+ return AutofillValue.forDate(unixTime);
+ }
+
+ @Override
+ public void autofill(AutofillValue value) {
+ if (!value.isDate()) {
+ return;
+ }
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTimeInMillis(value.getDateValue());
+ int month = calendar.get(Calendar.MONTH);
+ int year = calendar.get(Calendar.YEAR);
+ mCcExpMonthSpinner.setSelection(month);
+ mCcExpYearSpinner.setSelection(year - Integer.parseInt(mYears[0]));
+ }
+
+ @Override
+ public int getAutofillType() {
+ return AUTOFILL_TYPE_DATE;
+ }
+
+ public void reset() {
+ mCcExpMonthSpinner.setSelection(0);
+ mCcExpYearSpinner.setSelection(0);
+ }
+} \ No newline at end of file
diff --git a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.java b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.java
index e8819f14..8aeb85e5 100644
--- a/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.java
+++ b/input/autofill/AutofillFramework/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.java
@@ -36,7 +36,7 @@ public class MainActivity extends AppCompatActivity {
NavigationItem creditCardSpinners = findViewById(R.id.creditCardCheckoutButton);
NavigationItem loginAutoComplete = findViewById(R.id.standardLoginWithAutoCompleteButton);
NavigationItem emailCompose = findViewById(R.id.emailComposeButton);
-
+ NavigationItem creditCardCompoundView = findViewById(R.id.creditCardCompoundViewButton);
loginEditTexts.setNavigationButtonClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
@@ -67,5 +67,11 @@ public class MainActivity extends AppCompatActivity {
startActivity(EmailComposeActivity.getStartActivityIntent(MainActivity.this));
}
});
+ creditCardCompoundView.setNavigationButtonClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(CreditCardCompoundViewActivity.getStartActivityIntent(MainActivity.this));
+ }
+ });
}
} \ No newline at end of file
diff --git a/input/autofill/AutofillFramework/Application/src/main/res/drawable/ic_view_module_black_24dp.xml b/input/autofill/AutofillFramework/Application/src/main/res/drawable/ic_view_module_black_24dp.xml
new file mode 100644
index 00000000..ab36b076
--- /dev/null
+++ b/input/autofill/AutofillFramework/Application/src/main/res/drawable/ic_view_module_black_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M4,11h5L9,5L4,5v6zM4,18h5v-6L4,12v6zM10,18h5v-6h-5v6zM16,18h5v-6h-5v6zM10,11h5L15,5h-5v6zM16,5v6h5L21,5h-5z"/>
+</vector>
diff --git a/input/autofill/AutofillFramework/Application/src/main/res/layout/activity_main.xml b/input/autofill/AutofillFramework/Application/src/main/res/layout/activity_main.xml
index b85f6c58..f441a2ce 100644
--- a/input/autofill/AutofillFramework/Application/src/main/res/layout/activity_main.xml
+++ b/input/autofill/AutofillFramework/Application/src/main/res/layout/activity_main.xml
@@ -71,6 +71,14 @@
app:labelText="@string/navigation_button_email_compose_label"
app:itemLogo="@drawable/ic_email_black_24dp"
app:imageColor="@android:color/holo_purple"/>
+ <com.example.android.autofillframework.app.NavigationItem
+ android:id="@+id/creditCardCompoundViewButton"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:infoText="@string/compound_view_credit_card_info"
+ app:labelText="@string/navigation_button_compound_view_credit_card_label"
+ app:imageColor="@android:color/holo_blue_light"
+ app:itemLogo="@drawable/ic_view_module_black_24dp" />
</LinearLayout>
</ScrollView> \ No newline at end of file
diff --git a/input/autofill/AutofillFramework/Application/src/main/res/layout/cc_exp_date.xml b/input/autofill/AutofillFramework/Application/src/main/res/layout/cc_exp_date.xml
new file mode 100644
index 00000000..aebe9f83
--- /dev/null
+++ b/input/autofill/AutofillFramework/Application/src/main/res/layout/cc_exp_date.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ * Copyright (C) 2017 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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <android.support.constraint.ConstraintLayout
+ android:id="@+id/navigation_item_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <Spinner
+ android:id="@+id/ccExpMonth"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"
+ android:contentDescription="@string/cc_exp_month_description"
+ app:layout_constraintBottom_toBottomOf="@+id/monthYearDelimiter"
+ app:layout_constraintEnd_toStartOf="@+id/monthYearDelimiter"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="@+id/monthYearDelimiter" />
+
+ <TextView
+ android:id="@+id/monthYearDelimiter"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/slash"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/ccExpYear"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintStart_toEndOf="@+id/ccExpMonth"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <Spinner
+ android:id="@+id/ccExpYear"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@string/cc_exp_year_description"
+ app:layout_constraintBottom_toBottomOf="@+id/monthYearDelimiter"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintStart_toEndOf="@+id/monthYearDelimiter"
+ app:layout_constraintTop_toTopOf="@+id/monthYearDelimiter" />
+ </android.support.constraint.ConstraintLayout>
+</merge> \ No newline at end of file
diff --git a/input/autofill/AutofillFramework/Application/src/main/res/layout/credit_card_compound_view_activity.xml b/input/autofill/AutofillFramework/Application/src/main/res/layout/credit_card_compound_view_activity.xml
new file mode 100644
index 00000000..e95d0527
--- /dev/null
+++ b/input/autofill/AutofillFramework/Application/src/main/res/layout/credit_card_compound_view_activity.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ * Copyright (C) 2017 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.
+-->
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/authLayout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin">
+
+ <TextView
+ android:id="@+id/standard_login_header"
+ style="@style/TextAppearance.AppCompat.Large"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:gravity="center"
+ android:text="@string/navigation_button_compound_view_credit_card_label"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/imageButton"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintHorizontal_chainStyle="spread"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <com.example.android.autofillframework.app.InfoButton
+ android:id="@+id/imageButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/spacing_normal"
+ android:background="@drawable/ic_info_black_24dp"
+ app:dialogText="@string/compound_view_credit_card_info"
+ app:layout_constraintBottom_toBottomOf="@+id/standard_login_header"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintStart_toEndOf="@+id/standard_login_header"
+ app:layout_constraintTop_toTopOf="@+id/standard_login_header" />
+
+ <TextView
+ android:id="@+id/creditCardNumberLabel"
+ style="@style/TextAppearance.AppCompat.Body1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/spacing_normal"
+ android:layout_marginStart="@dimen/spacing_normal"
+ android:layout_marginTop="@dimen/spacing_large"
+ android:labelFor="@+id/creditCardNumberField"
+ android:text="@string/credit_card_number_label"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/standard_login_header" />
+
+ <EditText
+ android:id="@+id/creditCardNumberField"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/spacing_normal"
+ android:layout_marginTop="@dimen/spacing_normal"
+ android:autofillHints="creditCardNumber"
+ android:ems="12"
+ android:inputType="number"
+ android:paddingHorizontal="@dimen/spacing_micro"
+ app:layout_constraintBottom_toBottomOf="@+id/creditCardNumberLabel"
+ app:layout_constraintStart_toEndOf="@+id/creditCardNumberLabel"
+ app:layout_constraintTop_toTopOf="@+id/creditCardNumberLabel" />
+
+ <TextView
+ android:id="@+id/creditCardExpirationLabel"
+ style="@style/TextAppearance.AppCompat.Body1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/spacing_large"
+ android:labelFor="@+id/creditCardExpirationView"
+ android:text="@string/credit_card_expiration_label"
+ app:layout_constraintStart_toStartOf="@id/creditCardNumberLabel"
+ app:layout_constraintTop_toBottomOf="@+id/creditCardNumberLabel" />
+
+ <com.example.android.autofillframework.app.CreditCardExpirationDateView
+ android:id="@+id/creditCardExpirationView"
+ android:layout_width="250dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:layout_marginStart="@dimen/spacing_normal"
+ android:layout_marginTop="@dimen/spacing_normal"
+ android:autofillHints="creditCardExpirationDate"
+ app:layout_constraintBottom_toBottomOf="@+id/creditCardExpirationLabel"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toEndOf="@+id/creditCardExpirationLabel"
+ app:layout_constraintTop_toTopOf="@+id/creditCardExpirationLabel" />
+
+ <TextView
+ android:id="@+id/clearButton"
+ style="@style/Widget.AppCompat.Button.Borderless"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/spacing_normal"
+ android:layout_marginTop="@dimen/spacing_normal"
+ android:text="@string/clear_label"
+ android:textColor="@android:color/holo_blue_dark"
+ app:layout_constraintEnd_toStartOf="@+id/submitButton"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintHorizontal_chainStyle="packed"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/creditCardExpirationView" />
+
+ <TextView
+ android:id="@+id/submitButton"
+ style="@style/Widget.AppCompat.Button.Borderless"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/spacing_normal"
+ android:layout_marginStart="@dimen/spacing_normal"
+ android:text="@string/submit_label"
+ android:textColor="@android:color/holo_blue_dark"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintStart_toEndOf="@+id/clearButton"
+ app:layout_constraintTop_toTopOf="@+id/clearButton" />
+
+</android.support.constraint.ConstraintLayout> \ No newline at end of file
diff --git a/input/autofill/AutofillFramework/Application/src/main/res/values/strings.xml b/input/autofill/AutofillFramework/Application/src/main/res/values/strings.xml
index 86ecdb05..1eca8c1e 100644
--- a/input/autofill/AutofillFramework/Application/src/main/res/values/strings.xml
+++ b/input/autofill/AutofillFramework/Application/src/main/res/values/strings.xml
@@ -23,6 +23,7 @@
<string name="navigation_button_edittext_login_label">Sample Login Using EditTexts</string>
<string name="navigation_button_autocomplete_login_label">Sample Login Using AutoCompleteTextViews</string>
<string name="navigation_button_email_compose_label">Sample Email Compose Using EditTexts</string>
+ <string name="navigation_button_compound_view_credit_card_label">Sample Credit Card Check Out Using Compound Views</string>
<string name="username_label">Username</string>
<string name="password_label">Password</string>
<string name="welcome_text">Success!</string>
@@ -43,6 +44,7 @@
</string>
<string name="settings_clear_data_confirmation_title">Confirmation</string>
<string name="ok">OK</string>
+ <string name="slash">/</string>
<string name="cancel">Cancel</string>
<string name="settings_authentication_header">Authentication</string>
<string name="settings_data_header">Data</string>
@@ -56,6 +58,8 @@
<string name="body_label">Body</string>
<string name="autofill_master_login_label">Autofill Master Login</string>
<string name="submit_label">Submit</string>
+ <string name="cc_exp_month_description">Credit Card Expiration Month</string>
+ <string name="cc_exp_year_description">Credit Card Expiration Year</string>
<string name="edittext_login_info">This is a sample login page that uses standard EditTexts
from the UI toolkit. EditTexts are already optimized for autofill so extra autofill-specific
code is almost never needed.
@@ -84,6 +88,12 @@
on the root View if all Views in the hierarchy should not be autofilled. In this case, we
did the latter.
</string>
+ <string name="compound_view_credit_card_info">
+ This is a sample credit card checkout page that uses a custom compound View to input the credit
+ card\'s expiration date and an EditText to input the credit card number. While the EditText is
+ optimized out of the box for autofill, this example shows how to implement certain Autofill-
+ specific methods and XML properties for the custom compound view.
+ </string>
<plurals name="welcome_page_countdown">
<item quantity="one">Automatically return to main page in %d second.</item>
<item quantity="other">Automatically return to main page in %d seconds.</item>
diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/AndroidManifest.xml b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/AndroidManifest.xml
index 4d796e4f..2470645c 100644
--- a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/AndroidManifest.xml
+++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/AndroidManifest.xml
@@ -41,9 +41,7 @@
android:taskAffinity=".StandardAutoCompleteSignInActivity" />
<activity
android:name=".app.VirtualSignInActivity"
- android:taskAffinity=".VirtualSignInActivity">
-
- </activity>
+ android:taskAffinity=".VirtualSignInActivity" />
<activity android:name=".app.WelcomeActivity" />
<activity
android:name=".app.CreditCardActivity"
@@ -51,6 +49,9 @@
<activity
android:name=".app.EmailComposeActivity"
android:taskAffinity=".EmailComposeActivity" />
+ <activity
+ android:name=".app.CreditCardCompoundViewActivity"
+ android:taskAffinity=".CreditCardCompoundViewActivity" />
<!--
Including launcher icon for Autofill Settings to convenience.
Not necessary for a real service.
diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CreditCardCompoundViewActivity.kt b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CreditCardCompoundViewActivity.kt
new file mode 100644
index 00000000..09f83ac4
--- /dev/null
+++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CreditCardCompoundViewActivity.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 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.autofillframework.app
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.support.v7.app.AppCompatActivity
+
+import com.example.android.autofillframework.R
+import kotlinx.android.synthetic.main.credit_card_compound_view_activity.*
+
+class CreditCardCompoundViewActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.credit_card_compound_view_activity)
+ submitButton.setOnClickListener { submit() }
+ clearButton.setOnClickListener { resetFields() }
+ }
+
+ private fun resetFields() {
+ creditCardExpirationView.reset()
+ creditCardNumberField.setText("")
+ }
+
+ /**
+ * Launches new Activity and finishes, triggering an autofill save request if the user entered
+ * any new data.
+ */
+ private fun submit() {
+ val intent = WelcomeActivity.getStartActivityIntent(this)
+ startActivity(intent)
+ finish()
+ }
+
+ companion object {
+ fun getStartActivityIntent(context: Context): Intent {
+ val intent = Intent(context, CreditCardCompoundViewActivity::class.java)
+ return intent
+ }
+ }
+}
diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CreditCardExpirationDateView.kt b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CreditCardExpirationDateView.kt
new file mode 100644
index 00000000..609522b3
--- /dev/null
+++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/CreditCardExpirationDateView.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2017 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.autofillframework.app
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.view.autofill.AutofillManager
+import android.view.autofill.AutofillValue
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import android.widget.FrameLayout
+import com.example.android.autofillframework.R
+import kotlinx.android.synthetic.main.cc_exp_date.view.*
+import java.util.Calendar
+
+class CreditCardExpirationDateView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0,
+ defStyleRes: Int = 0
+) : FrameLayout(context, attrs, defStyleAttr, defStyleRes) {
+
+ private val startYear = Calendar.getInstance().get(Calendar.YEAR)
+
+ init {
+ LayoutInflater.from(context).inflate(R.layout.cc_exp_date, this)
+ importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
+ val spinnerOnItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int,
+ id: Long) {
+ context.getSystemService(AutofillManager::class.java)
+ .notifyValueChanged(this@CreditCardExpirationDateView)
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>) = Unit
+ }
+ val years = arrayOfNulls<String>(CC_EXP_YEARS_COUNT)
+ for (i in 0 until years.size) {
+ years[i] = Integer.toString(startYear + i)
+ }
+
+ with(ccExpMonth) {
+ adapter = ArrayAdapter.createFromResource(context, R.array.month_array,
+ android.R.layout.simple_spinner_item).apply {
+ setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
+ }
+ onItemSelectedListener = spinnerOnItemSelectedListener
+ }
+
+ with(ccExpYear) {
+ adapter = ArrayAdapter<String>(context,
+ android.R.layout.simple_spinner_item, years)
+ onItemSelectedListener = spinnerOnItemSelectedListener
+ }
+ }
+
+ override fun getAutofillValue() =
+ AutofillValue.forDate(Calendar.getInstance().apply {
+ // clear() sets hours, minutes, seconds, and millis to 0 to ensure that after
+ // autofill() is called, getAutofillValue() == the value that was originally passed
+ // into autofill(). Without clear(), the view will not turn yellow when updated.
+ clear()
+ val year = Integer.parseInt(ccExpYear.selectedItem.toString())
+ val month = ccExpMonth.selectedItemPosition
+ set(Calendar.YEAR, year)
+ set(Calendar.MONTH, month)
+ }.timeInMillis)
+
+ override fun autofill(value: AutofillValue) {
+ if (!value.isDate) {
+ return
+ }
+ val calendar = Calendar.getInstance().apply {
+ timeInMillis = value.dateValue
+ }
+ val month = calendar.get(Calendar.MONTH)
+ val year = calendar.get(Calendar.YEAR)
+ ccExpMonth.setSelection(month)
+ ccExpYear.setSelection(year - startYear)
+ }
+
+ override fun getAutofillType() = View.AUTOFILL_TYPE_DATE
+
+ fun reset() {
+ ccExpMonth.setSelection(0)
+ ccExpYear.setSelection(0)
+ }
+
+ companion object {
+ private const val CC_EXP_YEARS_COUNT = 5
+ }
+} \ No newline at end of file
diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.kt b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.kt
index d251369d..43a25220 100644
--- a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.kt
+++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/java/com/example/android/autofillframework/app/MainActivity.kt
@@ -19,11 +19,7 @@ import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.View
import com.example.android.autofillframework.R
-import kotlinx.android.synthetic.main.activity_main.creditCardCheckoutButton
-import kotlinx.android.synthetic.main.activity_main.emailComposeButton
-import kotlinx.android.synthetic.main.activity_main.standardLoginWithAutoCompleteButton
-import kotlinx.android.synthetic.main.activity_main.standardViewSignInButton
-import kotlinx.android.synthetic.main.activity_main.virtualViewSignInButton
+import kotlinx.android.synthetic.main.activity_main.*
/**
* This is used to launch sample activities that showcase autofill.
@@ -33,35 +29,23 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
- standardViewSignInButton.setNavigationButtonClickListener(View.OnClickListener { standardViewSignIn() })
- virtualViewSignInButton.setNavigationButtonClickListener(View.OnClickListener { virtualViewSignIn() })
- creditCardCheckoutButton.setNavigationButtonClickListener(View.OnClickListener { creditCardCheckout() })
- standardLoginWithAutoCompleteButton.setNavigationButtonClickListener(View.OnClickListener { standardAutoCompleteSignIn() })
- emailComposeButton.setNavigationButtonClickListener(View.OnClickListener { emailCompose() })
- }
-
- private fun creditCardCheckout() {
- val intent = CreditCardActivity.getStartActivityIntent(this)
- startActivity(intent)
- }
-
- private fun standardViewSignIn() {
- val intent = StandardSignInActivity.getStartActivityIntent(this)
- startActivity(intent)
- }
-
- private fun standardAutoCompleteSignIn() {
- val intent = StandardAutoCompleteSignInActivity.getStartActivityIntent(this)
- startActivity(intent)
- }
-
- private fun virtualViewSignIn() {
- val intent = VirtualSignInActivity.getStartActivityIntent(this)
- startActivity(intent)
- }
-
- private fun emailCompose() {
- val intent = EmailComposeActivity.getStartActivityIntent(this)
- startActivity(intent)
+ standardViewSignInButton.setNavigationButtonClickListener(View.OnClickListener {
+ startActivity(StandardSignInActivity.getStartActivityIntent(this@MainActivity))
+ })
+ virtualViewSignInButton.setNavigationButtonClickListener(View.OnClickListener {
+ startActivity(VirtualSignInActivity.getStartActivityIntent(this@MainActivity))
+ })
+ creditCardCheckoutButton.setNavigationButtonClickListener(View.OnClickListener {
+ startActivity(CreditCardActivity.getStartActivityIntent(this@MainActivity))
+ })
+ standardLoginWithAutoCompleteButton.setNavigationButtonClickListener(View.OnClickListener {
+ startActivity(StandardAutoCompleteSignInActivity.getStartActivityIntent(this@MainActivity))
+ })
+ emailComposeButton.setNavigationButtonClickListener(View.OnClickListener {
+ startActivity(EmailComposeActivity.getStartActivityIntent(this@MainActivity))
+ })
+ creditCardCompoundViewButton.setNavigationButtonClickListener(View.OnClickListener {
+ startActivity(CreditCardCompoundViewActivity.getStartActivityIntent(this@MainActivity))
+ })
}
} \ No newline at end of file
diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/drawable/ic_view_module_black_24dp.xml b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/drawable/ic_view_module_black_24dp.xml
new file mode 100644
index 00000000..ab36b076
--- /dev/null
+++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/drawable/ic_view_module_black_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M4,11h5L9,5L4,5v6zM4,18h5v-6L4,12v6zM10,18h5v-6h-5v6zM16,18h5v-6h-5v6zM10,11h5L15,5h-5v6zM16,5v6h5L21,5h-5z"/>
+</vector>
diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/activity_main.xml b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/activity_main.xml
index b85f6c58..f441a2ce 100644
--- a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/activity_main.xml
+++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/activity_main.xml
@@ -71,6 +71,14 @@
app:labelText="@string/navigation_button_email_compose_label"
app:itemLogo="@drawable/ic_email_black_24dp"
app:imageColor="@android:color/holo_purple"/>
+ <com.example.android.autofillframework.app.NavigationItem
+ android:id="@+id/creditCardCompoundViewButton"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:infoText="@string/compound_view_credit_card_info"
+ app:labelText="@string/navigation_button_compound_view_credit_card_label"
+ app:imageColor="@android:color/holo_blue_light"
+ app:itemLogo="@drawable/ic_view_module_black_24dp" />
</LinearLayout>
</ScrollView> \ No newline at end of file
diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/cc_exp_date.xml b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/cc_exp_date.xml
new file mode 100644
index 00000000..aebe9f83
--- /dev/null
+++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/cc_exp_date.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ * Copyright (C) 2017 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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <android.support.constraint.ConstraintLayout
+ android:id="@+id/navigation_item_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <Spinner
+ android:id="@+id/ccExpMonth"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"
+ android:contentDescription="@string/cc_exp_month_description"
+ app:layout_constraintBottom_toBottomOf="@+id/monthYearDelimiter"
+ app:layout_constraintEnd_toStartOf="@+id/monthYearDelimiter"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="@+id/monthYearDelimiter" />
+
+ <TextView
+ android:id="@+id/monthYearDelimiter"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/slash"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/ccExpYear"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintStart_toEndOf="@+id/ccExpMonth"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <Spinner
+ android:id="@+id/ccExpYear"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@string/cc_exp_year_description"
+ app:layout_constraintBottom_toBottomOf="@+id/monthYearDelimiter"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintStart_toEndOf="@+id/monthYearDelimiter"
+ app:layout_constraintTop_toTopOf="@+id/monthYearDelimiter" />
+ </android.support.constraint.ConstraintLayout>
+</merge> \ No newline at end of file
diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/credit_card_compound_view_activity.xml b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/credit_card_compound_view_activity.xml
new file mode 100644
index 00000000..e95d0527
--- /dev/null
+++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/layout/credit_card_compound_view_activity.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ * Copyright (C) 2017 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.
+-->
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/authLayout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin">
+
+ <TextView
+ android:id="@+id/standard_login_header"
+ style="@style/TextAppearance.AppCompat.Large"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:gravity="center"
+ android:text="@string/navigation_button_compound_view_credit_card_label"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintEnd_toStartOf="@+id/imageButton"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintHorizontal_chainStyle="spread"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <com.example.android.autofillframework.app.InfoButton
+ android:id="@+id/imageButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/spacing_normal"
+ android:background="@drawable/ic_info_black_24dp"
+ app:dialogText="@string/compound_view_credit_card_info"
+ app:layout_constraintBottom_toBottomOf="@+id/standard_login_header"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintStart_toEndOf="@+id/standard_login_header"
+ app:layout_constraintTop_toTopOf="@+id/standard_login_header" />
+
+ <TextView
+ android:id="@+id/creditCardNumberLabel"
+ style="@style/TextAppearance.AppCompat.Body1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/spacing_normal"
+ android:layout_marginStart="@dimen/spacing_normal"
+ android:layout_marginTop="@dimen/spacing_large"
+ android:labelFor="@+id/creditCardNumberField"
+ android:text="@string/credit_card_number_label"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/standard_login_header" />
+
+ <EditText
+ android:id="@+id/creditCardNumberField"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/spacing_normal"
+ android:layout_marginTop="@dimen/spacing_normal"
+ android:autofillHints="creditCardNumber"
+ android:ems="12"
+ android:inputType="number"
+ android:paddingHorizontal="@dimen/spacing_micro"
+ app:layout_constraintBottom_toBottomOf="@+id/creditCardNumberLabel"
+ app:layout_constraintStart_toEndOf="@+id/creditCardNumberLabel"
+ app:layout_constraintTop_toTopOf="@+id/creditCardNumberLabel" />
+
+ <TextView
+ android:id="@+id/creditCardExpirationLabel"
+ style="@style/TextAppearance.AppCompat.Body1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/spacing_large"
+ android:labelFor="@+id/creditCardExpirationView"
+ android:text="@string/credit_card_expiration_label"
+ app:layout_constraintStart_toStartOf="@id/creditCardNumberLabel"
+ app:layout_constraintTop_toBottomOf="@+id/creditCardNumberLabel" />
+
+ <com.example.android.autofillframework.app.CreditCardExpirationDateView
+ android:id="@+id/creditCardExpirationView"
+ android:layout_width="250dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:layout_marginStart="@dimen/spacing_normal"
+ android:layout_marginTop="@dimen/spacing_normal"
+ android:autofillHints="creditCardExpirationDate"
+ app:layout_constraintBottom_toBottomOf="@+id/creditCardExpirationLabel"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toEndOf="@+id/creditCardExpirationLabel"
+ app:layout_constraintTop_toTopOf="@+id/creditCardExpirationLabel" />
+
+ <TextView
+ android:id="@+id/clearButton"
+ style="@style/Widget.AppCompat.Button.Borderless"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/spacing_normal"
+ android:layout_marginTop="@dimen/spacing_normal"
+ android:text="@string/clear_label"
+ android:textColor="@android:color/holo_blue_dark"
+ app:layout_constraintEnd_toStartOf="@+id/submitButton"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintHorizontal_chainStyle="packed"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/creditCardExpirationView" />
+
+ <TextView
+ android:id="@+id/submitButton"
+ style="@style/Widget.AppCompat.Button.Borderless"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/spacing_normal"
+ android:layout_marginStart="@dimen/spacing_normal"
+ android:text="@string/submit_label"
+ android:textColor="@android:color/holo_blue_dark"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.5"
+ app:layout_constraintStart_toEndOf="@+id/clearButton"
+ app:layout_constraintTop_toTopOf="@+id/clearButton" />
+
+</android.support.constraint.ConstraintLayout> \ No newline at end of file
diff --git a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/values/strings.xml b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/values/strings.xml
index 86ecdb05..1eca8c1e 100644
--- a/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/values/strings.xml
+++ b/input/autofill/AutofillFramework/kotlinApp/Application/src/main/res/values/strings.xml
@@ -23,6 +23,7 @@
<string name="navigation_button_edittext_login_label">Sample Login Using EditTexts</string>
<string name="navigation_button_autocomplete_login_label">Sample Login Using AutoCompleteTextViews</string>
<string name="navigation_button_email_compose_label">Sample Email Compose Using EditTexts</string>
+ <string name="navigation_button_compound_view_credit_card_label">Sample Credit Card Check Out Using Compound Views</string>
<string name="username_label">Username</string>
<string name="password_label">Password</string>
<string name="welcome_text">Success!</string>
@@ -43,6 +44,7 @@
</string>
<string name="settings_clear_data_confirmation_title">Confirmation</string>
<string name="ok">OK</string>
+ <string name="slash">/</string>
<string name="cancel">Cancel</string>
<string name="settings_authentication_header">Authentication</string>
<string name="settings_data_header">Data</string>
@@ -56,6 +58,8 @@
<string name="body_label">Body</string>
<string name="autofill_master_login_label">Autofill Master Login</string>
<string name="submit_label">Submit</string>
+ <string name="cc_exp_month_description">Credit Card Expiration Month</string>
+ <string name="cc_exp_year_description">Credit Card Expiration Year</string>
<string name="edittext_login_info">This is a sample login page that uses standard EditTexts
from the UI toolkit. EditTexts are already optimized for autofill so extra autofill-specific
code is almost never needed.
@@ -84,6 +88,12 @@
on the root View if all Views in the hierarchy should not be autofilled. In this case, we
did the latter.
</string>
+ <string name="compound_view_credit_card_info">
+ This is a sample credit card checkout page that uses a custom compound View to input the credit
+ card\'s expiration date and an EditText to input the credit card number. While the EditText is
+ optimized out of the box for autofill, this example shows how to implement certain Autofill-
+ specific methods and XML properties for the custom compound view.
+ </string>
<plurals name="welcome_page_countdown">
<item quantity="one">Automatically return to main page in %d second.</item>
<item quantity="other">Automatically return to main page in %d seconds.</item>