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

Commit 04882615 authored by Anna Zhuravleva's avatar Anna Zhuravleva Committed by Android (Google) Code Review
Browse files

Merge "Add Bilingual Suggested locale adapter."

parents bc948d84 1b6f052e
Loading
Loading
Loading
Loading
+130 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.android.internal.app;

import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.android.internal.R;

import java.util.Locale;
import java.util.Set;

/**
 * This adapter extends basic SuggestedLocaleAdapter. In addition to the base functionality, it
 * shows language name not only in the native locale, but in secondary locale as well. Secondary
 * locale is passed as a constructor parameter.
 */
public class BilingualSuggestedLocaleAdapter extends SuggestedLocaleAdapter {

    private final Locale mSecondaryLocale;
    private final int mSecondaryLocaleTextDir;

    public BilingualSuggestedLocaleAdapter(
            Set<LocaleStore.LocaleInfo> localeOptions,
            boolean countryMode,
            Locale secondaryLocale) {
        super(localeOptions, countryMode);
        mSecondaryLocale = secondaryLocale;
        if (TextUtils.getLayoutDirectionFromLocale(secondaryLocale) == View.LAYOUT_DIRECTION_RTL) {
            mSecondaryLocaleTextDir = View.TEXT_DIRECTION_RTL;
        } else {
            mSecondaryLocaleTextDir = View.TEXT_DIRECTION_LTR;
        }
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null && super.mInflater == null) {
            mInflater = LayoutInflater.from(parent.getContext());
        }

        int itemType = getItemViewType(position);
        switch (itemType) {
            case TYPE_HEADER_SUGGESTED: // intentional fallthrough
            case TYPE_HEADER_ALL_OTHERS:
                // Covers both null, and "reusing" a wrong kind of view
                if (!(convertView instanceof TextView)) {
                    convertView =
                            mInflater.inflate(
                                    R.layout.language_picker_bilingual_section_header,
                                    parent,
                                    false);
                }
                TextView textView = (TextView) convertView;
                if (itemType == TYPE_HEADER_SUGGESTED) {
                    setHeaderText(
                            textView,
                            R.string.language_picker_section_suggested_bilingual,
                            R.string.region_picker_section_suggested_bilingual);
                } else {
                    setHeaderText(
                            textView,
                            R.string.language_picker_section_all,
                            R.string.region_picker_section_all);
                }
                break;
            default:
                // Covers both null, and "reusing" a wrong kind of view
                if (!(convertView instanceof ViewGroup)) {
                    convertView =
                            mInflater.inflate(
                                    R.layout.language_picker_bilingual_item, parent, false);
                }

                LocaleStore.LocaleInfo item = (LocaleStore.LocaleInfo) getItem(position);
                setLocaleToListItem(convertView, item);
        }
        return convertView;
    }

    private void setHeaderText(
            TextView textView, int languageStringResourceId, int regionStringResourceId) {
        if (mCountryMode) {
            setTextTo(textView, regionStringResourceId);
        } else {
            setTextTo(textView, languageStringResourceId);
        }
    }

    private void setLocaleToListItem(View itemView, LocaleStore.LocaleInfo localeInfo) {
        if (localeInfo == null) {
            throw new NullPointerException("Cannot set locale, locale info is null.");
        }

        TextView textNative = (TextView) itemView.findViewById(R.id.locale_native);
        textNative.setText(localeInfo.getLabel(mCountryMode));
        textNative.setTextLocale(localeInfo.getLocale());
        textNative.setContentDescription(localeInfo.getContentDescription(mCountryMode));

        TextView textSecondary = (TextView) itemView.findViewById(R.id.locale_secondary);
        textSecondary.setText(localeInfo.getLocale().getDisplayLanguage(mSecondaryLocale));
        textSecondary.setTextDirection(mSecondaryLocaleTextDir);
        if (mCountryMode) {
            int layoutDir = TextUtils.getLayoutDirectionFromLocale(localeInfo.getParent());
            //noinspection ResourceType
            itemView.setLayoutDirection(layoutDir);
            textNative.setTextDirection(
                    layoutDir == View.LAYOUT_DIRECTION_RTL
                            ? View.TEXT_DIRECTION_RTL
                            : View.TEXT_DIRECTION_LTR);
        }
    }
}
+7 −4
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
@@ -39,9 +41,9 @@ public class LocaleStore {
    private static boolean sFullyInitialized = false;

    public static class LocaleInfo implements Serializable {
        private static final int SUGGESTION_TYPE_NONE = 0;
        private static final int SUGGESTION_TYPE_SIM = 1 << 0;
        private static final int SUGGESTION_TYPE_CFG = 1 << 1;
        @VisibleForTesting static final int SUGGESTION_TYPE_NONE = 0;
        @VisibleForTesting static final int SUGGESTION_TYPE_SIM = 1 << 0;
        @VisibleForTesting static final int SUGGESTION_TYPE_CFG = 1 << 1;
        // Only for per-app language picker
        private static final int SUGGESTION_TYPE_CURRENT = 1 << 2;
        // Only for per-app language picker
@@ -55,7 +57,8 @@ public class LocaleStore {
        private boolean mIsChecked; // Used by the LocaleListEditor to mark entries for deletion
        // Combination of flags for various reasons to show a locale as a suggestion.
        // Can be SIM, location, etc.
        private int mSuggestionFlags;
        // Set to public to be accessible during runtime from the test app.
        @VisibleForTesting public int mSuggestionFlags;

        private String mFullNameNative;
        private String mFullCountryNameNative;
+36 −22
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ import java.util.Collections;
import java.util.Locale;
import java.util.Set;


/**
 * This adapter wraps around a regular ListAdapter for LocaleInfo, and creates 2 sections.
 *
@@ -51,25 +50,25 @@ import java.util.Set;
 * (Austria, Belgium, Germany, Liechtenstein, Luxembourg)</p>
 */
public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable {
    private static final int TYPE_HEADER_SUGGESTED = 0;
    private static final int TYPE_HEADER_ALL_OTHERS = 1;
    private static final int TYPE_LOCALE = 2;
    private static final int TYPE_SYSTEM_LANGUAGE_FOR_APP_LANGUAGE_PICKER = 3;
    private static final int TYPE_CURRENT_LOCALE = 4;
    private static final int MIN_REGIONS_FOR_SUGGESTIONS = 6;
    private static final int APP_LANGUAGE_PICKER_TYPE_COUNT = 5;
    private static final int SYSTEM_LANGUAGE_TYPE_COUNT = 3;
    private static final int SYSTEM_LANGUAGE_WITHOUT_HEADER_TYPE_COUNT = 1;

    private ArrayList<LocaleStore.LocaleInfo> mLocaleOptions;
    private ArrayList<LocaleStore.LocaleInfo> mOriginalLocaleOptions;
    private int mSuggestionCount;
    private final boolean mCountryMode;
    private LayoutInflater mInflater;

    private Locale mDisplayLocale = null;
    protected static final int TYPE_HEADER_SUGGESTED = 0;
    protected static final int TYPE_HEADER_ALL_OTHERS = 1;
    protected static final int TYPE_LOCALE = 2;
    protected static final int TYPE_SYSTEM_LANGUAGE_FOR_APP_LANGUAGE_PICKER = 3;
    protected static final int TYPE_CURRENT_LOCALE = 4;
    protected static final int MIN_REGIONS_FOR_SUGGESTIONS = 6;
    protected static final int APP_LANGUAGE_PICKER_TYPE_COUNT = 5;
    protected static final int SYSTEM_LANGUAGE_TYPE_COUNT = 3;
    protected static final int SYSTEM_LANGUAGE_WITHOUT_HEADER_TYPE_COUNT = 1;

    protected ArrayList<LocaleStore.LocaleInfo> mLocaleOptions;
    protected ArrayList<LocaleStore.LocaleInfo> mOriginalLocaleOptions;
    protected int mSuggestionCount;
    protected final boolean mCountryMode;
    protected LayoutInflater mInflater;

    protected Locale mDisplayLocale = null;
    // used to potentially cache a modified Context that uses mDisplayLocale
    private Context mContextOverride = null;
    protected Context mContextOverride = null;
    private String mAppPackageName;

    public SuggestedLocaleAdapter(Set<LocaleStore.LocaleInfo> localeOptions, boolean countryMode) {
@@ -122,6 +121,9 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable {
            }

            LocaleStore.LocaleInfo item = (LocaleStore.LocaleInfo) getItem(position);
            if (item == null) {
                throw new NullPointerException("Non header locale cannot be null");
            }
            if (item.isSystemLocale()) {
                return TYPE_SYSTEM_LANGUAGE_FOR_APP_LANGUAGE_PICKER;
            }
@@ -156,6 +158,10 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable {

    @Override
    public Object getItem(int position) {
        if (isHeaderPosition(position)) {
            return null;
        }

        int offset = 0;
        if (showHeaders()) {
            offset = position > mSuggestionCount ? -2 : -1;
@@ -164,6 +170,10 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable {
        return mLocaleOptions.get(position + offset);
    }

    private boolean isHeaderPosition(int position) {
        return showHeaders() && (position == 0 || position == mSuggestionCount + 1);
    }

    @Override
    public long getItemId(int position) {
        return position;
@@ -185,7 +195,7 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable {
        }
    }

    private void setTextTo(@NonNull TextView textView, int resId) {
    protected void setTextTo(@NonNull TextView textView, int resId) {
        if (mContextOverride == null) {
            textView.setText(resId);
        } else {
@@ -220,7 +230,11 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable {
                break;
            case TYPE_SYSTEM_LANGUAGE_FOR_APP_LANGUAGE_PICKER:
                TextView title;
                if (((LocaleStore.LocaleInfo)getItem(position)).isAppCurrentLocale()) {
                LocaleStore.LocaleInfo info = (LocaleStore.LocaleInfo) getItem(position);
                if (info == null) {
                    throw new NullPointerException("Non header locale cannot be null.");
                }
                if (info.isAppCurrentLocale()) {
                    title = itemView.findViewById(R.id.language_picker_item);
                } else {
                    title = itemView.findViewById(R.id.locale);
@@ -292,7 +306,7 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable {
        return updatedView;
    }

    private boolean showHeaders() {
    protected boolean showHeaders() {
        // We don't want to show suggestions for locales with very few regions
        // (e.g. Romanian, with 2 regions)
        // So we put a (somewhat) arbitrary limit.
+31 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/frame"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:paddingTop="8dp"
    android:paddingBottom="8dp"
    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
    android:orientation="vertical">

    <TextView
        android:id="@+id/locale_native"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/language_picker_item_text_color"
        android:textSize="18sp"
        android:textAppearance="?android:attr/textAppearanceListItem"
        />

    <TextView
        android:id="@+id/locale_secondary"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/language_picker_item_text_color_secondary"
        android:textSize="16sp"
        android:textAppearance="?android:attr/textAppearanceListItem"
        />

</LinearLayout>
 No newline at end of file
+27 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2022 Google Inc.

     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.
-->

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          style="?android:attr/preferenceCategoryStyle"
          android:layout_width="match_parent"
          android:layout_height="36dp"
          android:gravity="center_vertical"
          android:paddingStart="?android:attr/listPreferredItemPaddingStart"
          android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
          android:textColor="@color/language_picker_item_text_color"
          android:textAllCaps="true"
          tools:text="@string/language_picker_section_all"/>
Loading