diff options
author | sgurun@chromium.org <sgurun@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-27 20:19:27 +0000 |
---|---|---|
committer | sgurun@chromium.org <sgurun@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-27 20:19:27 +0000 |
commit | 32d9fe2ee338a3e9fdec4664b798b1f6248566c4 (patch) | |
tree | 24f932cf7f25714ec74a02194d4d10dc90481237 /ui/android | |
parent | b17e31d3686dee74e421d31183eb2986e87c6ca3 (diff) | |
download | chromium_src-32d9fe2ee338a3e9fdec4664b798b1f6248566c4.zip chromium_src-32d9fe2ee338a3e9fdec4664b798b1f6248566c4.tar.gz chromium_src-32d9fe2ee338a3e9fdec4664b798b1f6248566c4.tar.bz2 |
Implement the autofill UI for chromium powered android webview.
This CL depends on https://codereview.chromium.org/15097004/.
Bug: b/5013406
TBR=battre@chromium.org, palmer@chromium.org
NOTRY=true
contributed by sgurun@chromium.org
Review URL: https://chromiumcodereview.appspot.com/16212007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@208986 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/android')
7 files changed, 356 insertions, 0 deletions
diff --git a/ui/android/java/res/drawable/autofill_popup_background.xml b/ui/android/java/res/drawable/autofill_popup_background.xml new file mode 100644 index 0000000..0f8d38b --- /dev/null +++ b/ui/android/java/res/drawable/autofill_popup_background.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- Copyright 2013 The Chromium Authors. All rights reserved. + + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_above_anchor="true" + android:drawable="@drawable/autofill_popup_background_up" /> + <item android:drawable="@drawable/autofill_popup_background_down" /> +</selector>
\ No newline at end of file diff --git a/ui/android/java/res/layout/autofill_text.xml b/ui/android/java/res/layout/autofill_text.xml new file mode 100644 index 0000000..4a69862 --- /dev/null +++ b/ui/android/java/res/layout/autofill_text.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2013 The Chromium Authors. All rights reserved. + + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/autofill_menu_text" + android:layout_width="fill_parent" + android:layout_height="44dp" + android:minHeight="44dp" + android:orientation="vertical" + android:gravity="center_vertical"> + <TextView android:id="@+id/autofill_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" + android:singleLine="true" + android:textSize="18sp" + android:includeFontPadding="false" + android:layout_marginStart="10dp" + android:layout_marginEnd="10dp"/> + <TextView android:id="@+id/autofill_sublabel" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="14sp" + android:textColor="#8b8b8b" + android:ellipsize="end" + android:singleLine="true" + android:includeFontPadding="false" + android:layout_marginStart="10dp" + android:layout_marginEnd="10dp"/> +</LinearLayout> diff --git a/ui/android/java/res/values-v17/styles.xml b/ui/android/java/res/values-v17/styles.xml new file mode 100644 index 0000000..8295ddf --- /dev/null +++ b/ui/android/java/res/values-v17/styles.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- Copyright 2013 The Chromium Authors. All rights reserved. + + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> + +<resources> + <style name="AutofillPopupWindow" parent="@android:style/Widget.ListPopupWindow"> + <item name="android:popupBackground">@drawable/autofill_popup_background</item> + </style> +</resources>
\ No newline at end of file diff --git a/ui/android/java/resource_map/org/chromium/ui/R.java b/ui/android/java/resource_map/org/chromium/ui/R.java index 0577d39..0c61b4b 100644 --- a/ui/android/java/resource_map/org/chromium/ui/R.java +++ b/ui/android/java/resource_map/org/chromium/ui/R.java @@ -27,6 +27,8 @@ public final class R { public static int color_picker_dialog_title; } public static final class id { + public static int autofill_label; + public static int autofill_sublabel; public static int selected_color_view; public static int title; public static int more_colors_button; @@ -39,6 +41,7 @@ public final class R { public static int seek_bar; } public static final class layout { + public static int autofill_text; public static int color_picker_dialog_title; public static int color_picker_dialog_content; public static int color_picker_advanced_component; @@ -46,4 +49,7 @@ public final class R { public static final class drawable { public static int color_picker_advanced_select_handle; } + public static final class style { + public static int AutofillPopupWindow; + } } diff --git a/ui/android/java/src/org/chromium/ui/autofill/AutofillListAdapter.java b/ui/android/java/src/org/chromium/ui/autofill/AutofillListAdapter.java new file mode 100644 index 0000000..62203dc --- /dev/null +++ b/ui/android/java/src/org/chromium/ui/autofill/AutofillListAdapter.java @@ -0,0 +1,54 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +package org.chromium.ui.autofill; + +import android.content.Context; +import android.text.TextUtils; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import org.chromium.ui.R; + +import java.util.ArrayList; + +/** + * Autofill suggestion adapter for AutofillWindow. + */ +public class AutofillListAdapter extends ArrayAdapter<AutofillSuggestion> { + private Context mContext; + + AutofillListAdapter(Context context, ArrayList<AutofillSuggestion> objects) { + super(context, R.layout.autofill_text, objects); + mContext = context; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View layout = convertView; + if (convertView == null) { + LayoutInflater inflater = + (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + layout = inflater.inflate(R.layout.autofill_text, null); + } + TextView labelView = (TextView) layout.findViewById(R.id.autofill_label); + labelView.setText(getItem(position).mLabel); + + TextView sublabelView = (TextView) layout.findViewById(R.id.autofill_sublabel); + CharSequence sublabel = getItem(position).mSublabel; + if (TextUtils.isEmpty(sublabel)) { + sublabelView.setVisibility(View.GONE); + } else { + sublabelView.setText(sublabel); + sublabelView.setVisibility(View.VISIBLE); + } + + return layout; + } +} diff --git a/ui/android/java/src/org/chromium/ui/autofill/AutofillPopup.java b/ui/android/java/src/org/chromium/ui/autofill/AutofillPopup.java new file mode 100644 index 0000000..7cec3c1 --- /dev/null +++ b/ui/android/java/src/org/chromium/ui/autofill/AutofillPopup.java @@ -0,0 +1,210 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui.autofill; + +import android.content.Context; +import android.graphics.Paint; +import android.graphics.Rect; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnLayoutChangeListener; +import android.widget.AdapterView; +import android.widget.ListPopupWindow; +import android.widget.TextView; + +import java.util.ArrayList; + +import org.chromium.ui.R; +import org.chromium.ui.ViewAndroidDelegate; + +/** + * The Autofill suggestion popup that lists relevant suggestions. + */ +public class AutofillPopup extends ListPopupWindow implements AdapterView.OnItemClickListener { + + /** + * Constants defining types of Autofill suggestion entries. + * Has to be kept in sync with enum in WebAutofillClient.h + * + * Not supported: MenuItemIDWarningMessage, MenuItemIDSeparator, MenuItemIDClearForm, and + * MenuItemIDAutofillOptions. + */ + private static final int ITEM_ID_AUTOCOMPLETE_ENTRY = 0; + private static final int ITEM_ID_PASSWORD_ENTRY = -2; + private static final int ITEM_ID_DATA_LIST_ENTRY = -6; + + private static final int TEXT_PADDING_DP = 30; + + private final AutofillPopupDelegate mAutofillCallback; + private final Context mContext; + private final ViewAndroidDelegate mViewAndroidDelegate; + private View mAnchorView; + private float mAnchorWidth; + private float mAnchorHeight; + private float mAnchorX; + private float mAnchorY; + private Paint mLabelViewPaint; + private Paint mSublabelViewPaint; + private OnLayoutChangeListener mLayoutChangeListener; + + /** + * An interface to handle the touch interaction with an AutofillPopup object. + */ + public interface AutofillPopupDelegate { + /** + * Requests the controller to hide AutofillPopup. + */ + public void requestHide(); + + /** + * Handles the selection of an Autofill suggestion from an AutofillPopup. + * @param listIndex The index of the selected Autofill suggestion. + */ + public void suggestionSelected(int listIndex); + } + + /** + * Creates an AutofillWindow with specified parameters. + * @param context Application context. + * @param viewAndroidDelegate View delegate used to add and remove views. + * @param autofillCallback A object that handles the calls to the native AutofillPopupView. + */ + public AutofillPopup(Context context, ViewAndroidDelegate viewAndroidDelegate, + AutofillPopupDelegate autofillCallback) { + super(context, null, 0, R.style.AutofillPopupWindow); + mContext = context; + mViewAndroidDelegate = viewAndroidDelegate ; + mAutofillCallback = autofillCallback; + + setOnItemClickListener(this); + + mAnchorView = mViewAndroidDelegate.acquireAnchorView(); + mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAnchorY, mAnchorWidth, + mAnchorHeight); + + mLayoutChangeListener = new OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + if (v == mAnchorView) AutofillPopup.this.show(); + } + }; + + mAnchorView.addOnLayoutChangeListener(mLayoutChangeListener); + setAnchorView(mAnchorView); + } + + @Override + public void show() { + // An ugly hack to keep the popup from expanding on top of the keyboard. + setInputMethodMode(INPUT_METHOD_NEEDED); + super.show(); + } + + /** + * Sets the location and the size of the anchor view that the AutofillPopup will use to attach + * itself. + * @param x X coordinate of the top left corner of the anchor view. + * @param y Y coordinate of the top left corner of the anchor view. + * @param width The width of the anchor view. + * @param height The height of the anchor view. + */ + public void setAnchorRect(float x, float y, float width, float height) { + mAnchorWidth = width; + mAnchorHeight = height; + mAnchorX = x; + mAnchorY = y; + if (mAnchorView != null) { + mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAnchorY, + mAnchorWidth, mAnchorHeight); + } + } + + /** + * Sets the Autofill suggestions to display in the popup and shows the popup. + * @param suggestions Autofill suggestion data. + */ + public void show(AutofillSuggestion[] suggestions) { + // Remove the AutofillSuggestions with IDs that are not supported by Android + ArrayList<AutofillSuggestion> cleanedData = new ArrayList<AutofillSuggestion>(); + for (int i = 0; i < suggestions.length; i++) { + int itemId = suggestions[i].mUniqueId; + if (itemId > 0 || itemId == ITEM_ID_AUTOCOMPLETE_ENTRY || + itemId == ITEM_ID_PASSWORD_ENTRY || itemId == ITEM_ID_DATA_LIST_ENTRY) { + cleanedData.add(suggestions[i]); + } + } + setAdapter(new AutofillListAdapter(mContext, cleanedData)); + // Once the mAnchorRect is resized and placed correctly, it will show the Autofill popup. + mAnchorWidth = Math.max(getDesiredWidth(cleanedData), mAnchorWidth); + mViewAndroidDelegate.setAnchorViewPosition(mAnchorView, mAnchorX, mAnchorY, mAnchorWidth, + mAnchorHeight); + } + + /** + * Overrides the default dismiss behavior to request the controller to dismiss the view. + */ + @Override + public void dismiss() { + mAutofillCallback.requestHide(); + } + + /** + * Hides the popup and removes the anchor view from the ContainerView. + */ + public void hide() { + super.dismiss(); + mAnchorView.removeOnLayoutChangeListener(mLayoutChangeListener); + mViewAndroidDelegate.releaseAnchorView(mAnchorView); + } + + /** + * Get desired popup window width by calculating the maximum text length from Autofill data. + * @param data Autofill suggestion data. + * @return The popup window width in DIP. + */ + private float getDesiredWidth(ArrayList<AutofillSuggestion> data) { + if (mLabelViewPaint == null || mSublabelViewPaint == null) { + LayoutInflater inflater = + (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View layout = inflater.inflate(R.layout.autofill_text, null); + TextView labelView = (TextView) layout.findViewById(R.id.autofill_label); + mLabelViewPaint = labelView.getPaint(); + TextView sublabelView = (TextView) layout.findViewById(R.id.autofill_sublabel); + mSublabelViewPaint = sublabelView.getPaint(); + } + + float maxTextWidth = 0; + Rect bounds = new Rect(); + for (int i = 0; i < data.size(); ++i) { + bounds.setEmpty(); + String label = data.get(i).mLabel; + if (!TextUtils.isEmpty(label)) { + mLabelViewPaint.getTextBounds(label, 0, label.length(), bounds); + } + float labelWidth = bounds.width(); + + bounds.setEmpty(); + String sublabel = data.get(i).mSublabel; + if (!TextUtils.isEmpty(sublabel)) { + mSublabelViewPaint.getTextBounds(sublabel, 0, sublabel.length(), bounds); + } + + float localMax = Math.max(labelWidth, bounds.width()); + maxTextWidth = Math.max(maxTextWidth, localMax); + } + // Scale it down to make it unscaled by screen density. + maxTextWidth = maxTextWidth / mContext.getResources().getDisplayMetrics().density; + // Adding padding. + return maxTextWidth + TEXT_PADDING_DP; + } + + @Override + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + mAutofillCallback.suggestionSelected(position); + } + +} diff --git a/ui/android/java/src/org/chromium/ui/autofill/AutofillSuggestion.java b/ui/android/java/src/org/chromium/ui/autofill/AutofillSuggestion.java new file mode 100644 index 0000000..51669ea --- /dev/null +++ b/ui/android/java/src/org/chromium/ui/autofill/AutofillSuggestion.java @@ -0,0 +1,26 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui.autofill; + +/** + * Autofill suggestion container used to store information needed for each Autofill popup entry. + */ +public class AutofillSuggestion { + final String mLabel; + final String mSublabel; + final int mUniqueId; + + /** + * Constructs a Autofill suggestion container. + * @param name The name of the Autofill suggestion. + * @param label The describing label of the Autofill suggestion. + * @param uniqueId The unique id used to identify the Autofill suggestion. + */ + public AutofillSuggestion(String name, String label, int uniqueId) { + mLabel = name; + mSublabel = label; + mUniqueId = uniqueId; + } +}
\ No newline at end of file |