diff options
author | Douglas Sigelbaum <sigelbaum@google.com> | 2017-06-21 18:20:53 -0700 |
---|---|---|
committer | Douglas Sigelbaum <sigelbaum@google.com> | 2017-08-31 21:05:35 +0000 |
commit | 313fb2327ba92aa3771f0d2a807be7149425bb39 (patch) | |
tree | e536f754e32a6035ee828a95def20f1d14f22000 /input | |
parent | 71556a6f6969b258fbcfd5bbc01ac32bb03d9674 (diff) | |
download | android-313fb2327ba92aa3771f0d2a807be7149425bb39.tar.gz |
Autofill sample: add credit card expiration compound view example.
Bug: 38182790
Test: manual
Change-Id: Ib611578b811715103666233f84720ef2bb184c00
Diffstat (limited to 'input')
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> |