Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 09da1990 authored by Felipe Leme's avatar Felipe Leme Committed by android-build-merger
Browse files

Merge "Fixed autofill dataset picker so header and footer are sticky." into pi-dev

am: b8c00934

Change-Id: Iea7cded56990ae09d5f60bbbc63978273092db6e
parents 77b5ccb5 b8c00934
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 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.
-->

<view  xmlns:android="http://schemas.android.com/apk/res/android"
    class="com.android.server.autofill.ui.FillUi$AutofillFrameLayout"
    android:id="@+id/autofill_dataset_picker"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    style="@style/AutofillDatasetPicker">

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

      <LinearLayout
          android:id="@+id/autofill_dataset_header"
          android:visibility="gone"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:orientation="vertical"/>

      <ListView
          android:id="@+id/autofill_dataset_list"
          android:layout_weight="1"
          android:layout_width="fill_parent"
          android:layout_height="0dp"
          android:drawSelectorOnTop="true"
          android:clickable="true"
          android:divider="@null"
          android:visibility="gone">
      </ListView>

      <LinearLayout
          android:id="@+id/autofill_dataset_footer"
          android:visibility="gone"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:orientation="vertical"/>

    </LinearLayout>

</view>
+73 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 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.
-->

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/autofill_dataset_picker"
    style="@style/AutofillDatasetPicker"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/autofill_window_title"
        android:layout_above="@+id/autofill_dataset_container"
        android:layout_alignStart="@+id/autofill_dataset_container"
        android:textSize="16sp"/>

    <!-- autofill_container is the common parent for inserting authentication item or
         autofill_dataset_list-->
    <FrameLayout
        android:id="@+id/autofill_dataset_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true">

        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <LinearLayout
                android:id="@+id/autofill_dataset_header"
                android:visibility="gone"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"/>

            <ListView
                android:id="@+id/autofill_dataset_list"
                android:layout_weight="1"
                android:layout_width="fill_parent"
                android:layout_height="0dp"
                android:clickable="true"
                android:divider="@null"
                android:drawSelectorOnTop="true"
                android:visibility="gone"/>

            <LinearLayout
                android:id="@+id/autofill_dataset_footer"
                android:visibility="gone"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"/>

        </LinearLayout>

    </FrameLayout>

</RelativeLayout>
+4 −0
Original line number Diff line number Diff line
@@ -3028,7 +3028,11 @@
  <java-symbol type="layout" name="autofill_save"/>
  <java-symbol type="layout" name="autofill_dataset_picker"/>
  <java-symbol type="layout" name="autofill_dataset_picker_fullscreen"/>
  <java-symbol type="layout" name="autofill_dataset_picker_header_footer"/>
  <java-symbol type="layout" name="autofill_dataset_picker_header_footer_fullscreen"/>
  <java-symbol type="id" name="autofill_dataset_container"/>
  <java-symbol type="id" name="autofill_dataset_footer"/>
  <java-symbol type="id" name="autofill_dataset_header"/>
  <java-symbol type="id" name="autofill_dataset_list"/>
  <java-symbol type="id" name="autofill_dataset_picker"/>
  <java-symbol type="id" name="autofill" />
+95 −55
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RemoteViews;

@@ -119,7 +120,9 @@ final class FillUi {

    private final @NonNull Callback mCallback;

    private final @Nullable View mHeader;
    private final @NonNull ListView mListView;
    private final @Nullable View mFooter;

    private final @Nullable ItemsAdapter mAdapter;

@@ -150,9 +153,18 @@ final class FillUi {

        final LayoutInflater inflater = LayoutInflater.from(context);

        final ViewGroup decor = (ViewGroup) inflater.inflate(
        final RemoteViews headerPresentation = response.getHeader();
        final RemoteViews footerPresentation = response.getFooter();
        final ViewGroup decor;
        if (headerPresentation != null || footerPresentation != null) {
            decor = (ViewGroup) inflater.inflate(
                    mFullScreen ? R.layout.autofill_dataset_picker_header_footer_fullscreen
                            : R.layout.autofill_dataset_picker_header_footer, null);
        } else {
            decor = (ViewGroup) inflater.inflate(
                    mFullScreen ? R.layout.autofill_dataset_picker_fullscreen
                            : R.layout.autofill_dataset_picker, null);
        }

        // if autofill ui is not fullscreen, send unhandled keyevent to app window.
        if (!mFullScreen) {
@@ -191,7 +203,9 @@ final class FillUi {
        };

        if (response.getAuthentication() != null) {
            mHeader = null;
            mListView = null;
            mFooter = null;
            mAdapter = null;

            // insert authentication item under autofill_dataset_container or decor
@@ -212,7 +226,7 @@ final class FillUi {
            decor.setFocusable(true);
            decor.setOnClickListener(v -> mCallback.onResponsePicked(response));

            Point maxSize = mTempPoint;
            final Point maxSize = mTempPoint;
            resolveMaxWindowSize(context, maxSize);
            // fullScreen mode occupy the full width defined by autofill_dataset_picker_max_width
            content.getLayoutParams().width = mFullScreen ? maxSize.x
@@ -231,38 +245,39 @@ final class FillUi {
            requestShowFillUi();
        } else {
            final int datasetCount = response.getDatasets().size();

            // Total items include the (optional) header and footer - we cannot use listview's
            // addHeader() and addFooter() because it would complicate the scrolling logic.
            int totalItems = datasetCount;
            if (sVerbose) {
                Slog.v(TAG, "Number datasets: " + datasetCount + " max visible: "
                        + sVisibleDatasetsMaxCount);
            }

            RemoteViews.OnClickHandler clickBlocker = null;
            final RemoteViews headerPresentation = response.getHeader();
            View header = null;
            if (headerPresentation != null) {
                clickBlocker = newClickBlocker();
                header = headerPresentation.apply(context, null, clickBlocker);
                totalItems++;
                mHeader = headerPresentation.apply(context, null, clickBlocker);
                final LinearLayout headerContainer =
                        decor.findViewById(R.id.autofill_dataset_header);
                if (sVerbose) Slog.v(TAG, "adding header");
                headerContainer.addView(mHeader);
                headerContainer.setVisibility(View.VISIBLE);
            } else {
                mHeader = null;
            }

            final RemoteViews footerPresentation = response.getFooter();
            View footer = null;
            if (footerPresentation != null) {
                if (clickBlocker == null) { // already set for header
                    clickBlocker = newClickBlocker();
                }
                footer = footerPresentation.apply(context, null, clickBlocker);
                totalItems++;
            }
            if (sVerbose) {
                Slog.v(TAG, "Number datasets: " + datasetCount + " Total items: " + totalItems);
                mFooter = footerPresentation.apply(context, null, clickBlocker);
                final LinearLayout footerContainer =
                        decor.findViewById(R.id.autofill_dataset_footer);
                if (sVerbose) Slog.v(TAG, "adding footer");
                footerContainer.addView(mFooter);
                footerContainer.setVisibility(View.VISIBLE);
            } else {
                mFooter = null;
            }

            final ArrayList<ViewItem> items = new ArrayList<>(totalItems);
            if (header != null) {
                if (sVerbose) Slog.v(TAG, "adding header");
                items.add(new ViewItem(null, null, false, null, header));
            }
            final ArrayList<ViewItem> items = new ArrayList<>(datasetCount);
            for (int i = 0; i < datasetCount; i++) {
                final Dataset dataset = response.getDatasets().get(i);
                final int index = dataset.getFieldIds().indexOf(focusedViewId);
@@ -304,10 +319,6 @@ final class FillUi {
                    items.add(new ViewItem(dataset, filterPattern, filterable, valueText, view));
                }
            }
            if (footer != null) {
                if (sVerbose) Slog.v(TAG, "adding footer");
                items.add(new ViewItem(null, null, false, null, footer));
            }

            mAdapter = new ItemsAdapter(items);

@@ -316,11 +327,6 @@ final class FillUi {
            mListView.setVisibility(View.VISIBLE);
            mListView.setOnItemClickListener((adapter, view, position, id) -> {
                final ViewItem vi = mAdapter.getItem(position);
                if (vi.dataset == null) {
                    // Clicked on header or footer; ignore.
                    if (sDebug) Slog.d(TAG, "Ignoring click on item " + position + ": " + view);
                    return;
                }
                mCallback.onDatasetPicked(vi.dataset);
            });

@@ -465,6 +471,13 @@ final class FillUi {
            changed = true;
            mContentWidth = maxSize.x;
        }

        if (mHeader != null) {
            mHeader.measure(widthMeasureSpec, heightMeasureSpec);
            changed |= updateWidth(mHeader, maxSize);
            changed |= updateHeight(mHeader, maxSize);
        }

        for (int i = 0; i < itemCount; i++) {
            final View view = mAdapter.getItem(i).view;
            view.measure(widthMeasureSpec, heightMeasureSpec);
@@ -478,23 +491,40 @@ final class FillUi {
                    break;
                }
            } else {
                changed |= updateWidth(view, maxSize);
                if (i < sVisibleDatasetsMaxCount) {
                    changed |= updateHeight(view, maxSize);
                }
            }
        }

        if (mFooter != null) {
            mFooter.measure(widthMeasureSpec, heightMeasureSpec);
            changed |= updateWidth(mFooter, maxSize);
            changed |= updateHeight(mFooter, maxSize);
        }
        return changed;
    }

    private boolean updateWidth(View view, Point maxSize) {
        boolean changed = false;
        final int clampedMeasuredWidth = Math.min(view.getMeasuredWidth(), maxSize.x);
        final int newContentWidth = Math.max(mContentWidth, clampedMeasuredWidth);
        if (newContentWidth != mContentWidth) {
            mContentWidth = newContentWidth;
            changed = true;
        }
                // Update the width to fit only the first items up to max count
                if (i < sVisibleDatasetsMaxCount) {
        return changed;
    }

    private boolean updateHeight(View view, Point maxSize) {
        boolean changed = false;
        final int clampedMeasuredHeight = Math.min(view.getMeasuredHeight(), maxSize.y);
        final int newContentHeight = mContentHeight + clampedMeasuredHeight;
        if (newContentHeight != mContentHeight) {
            mContentHeight = newContentHeight;
            changed = true;
        }
                }
            }
        }
        return changed;
    }

@@ -506,7 +536,7 @@ final class FillUi {

    private static void resolveMaxWindowSize(Context context, Point outPoint) {
        context.getDisplay().getSize(outPoint);
        TypedValue typedValue = sTempTypedValue;
        final TypedValue typedValue = sTempTypedValue;
        context.getTheme().resolveAttribute(R.attr.autofillDatasetPickerMaxWidth,
                typedValue, true);
        outPoint.x = (int) typedValue.getFraction(outPoint.x, outPoint.x);
@@ -693,17 +723,27 @@ final class FillUi {
    public void dump(PrintWriter pw, String prefix) {
        pw.print(prefix); pw.print("mCallback: "); pw.println(mCallback != null);
        pw.print(prefix); pw.print("mFullScreen: "); pw.println(mFullScreen);
        if (mHeader != null) {
            pw.print(prefix); pw.print("mHeader: "); pw.println(mHeader);
        }
        if (mListView != null) {
            pw.print(prefix); pw.print("mListView: "); pw.println(mListView);
        }
        if (mFooter != null) {
            pw.print(prefix); pw.print("mFooter: "); pw.println(mFooter);
        }
        if (mAdapter != null) {
            pw.print(prefix); pw.print("mAdapter: "); pw.println(mAdapter);
        }
        if (mFilterText != null) {
            pw.print(prefix); pw.print("mFilterText: ");
            Helper.printlnRedactedText(pw, mFilterText);
        }
        pw.print(prefix); pw.print("mContentWidth: "); pw.println(mContentWidth);
        pw.print(prefix); pw.print("mContentHeight: "); pw.println(mContentHeight);
        pw.print(prefix); pw.print("mDestroyed: "); pw.println(mDestroyed);
        if (mWindow != null) {
            pw.print(prefix); pw.print("mWindow: ");
        if (mWindow == null) {
            pw.println("N/A");
        } else {
            final String prefix2 = prefix + "  ";
            pw.println();
            pw.print(prefix2); pw.print("showing: "); pw.println(mWindow.mShowing);