Android P Language设置

在AndroidManifest文件中定位:

        <activity
            android:name=".Settings$LanguageAndInputSettingsActivity"
            android:label="@string/language_settings"
            android:icon="@drawable/ic_settings_language"
            android:taskAffinity="com.android.settings"
            android:parentActivityName="Settings">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.VOICE_LAUNCH" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <intent-filter android:priority="260">
                <action android:name="com.android.settings.action.SETTINGS"/>
            </intent-filter>
            <meta-data android:name="com.android.settings.category"
                //分类,表示属于系统分类下 android:value="com.android.settings.category.ia.system"/> <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                //对应的路径 android:value="com.android.settings.language.LanguageAndInputSettings"/> <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED" android:value="true"/> </activity>
  @Override
    protected int getPreferenceScreenResId() {
        //要加载的布局
        return R.xml.language_and_input;
    }        
    //初始化controllers
 @Override
    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
        return buildPreferenceControllers(context, getLifecycle());
    }
    private static List<AbstractPreferenceController> buildPreferenceControllers(
            @NonNull Context context, @Nullable Lifecycle lifecycle) {
        final List<AbstractPreferenceController> controllers = new ArrayList<>();
        // Language
        controllers.add(new PhoneLanguagePreferenceController(context));
        // Input
        final VirtualKeyboardPreferenceController virtualKeyboardPreferenceController =
                new VirtualKeyboardPreferenceController(context);
        final PhysicalKeyboardPreferenceController physicalKeyboardPreferenceController =
                new PhysicalKeyboardPreferenceController(context, lifecycle);
        controllers.add(virtualKeyboardPreferenceController);
        controllers.add(physicalKeyboardPreferenceController);
        controllers.add(new PreferenceCategoryController(context,
                KEY_KEYBOARDS_CATEGORY).setChildren(
                Arrays.asList(virtualKeyboardPreferenceController,
                        physicalKeyboardPreferenceController)));
        // Pointer and Tts
        final TtsPreferenceController ttsPreferenceController =
                new TtsPreferenceController(context, new TtsEngines(context));
        controllers.add(ttsPreferenceController);
        final PointerSpeedController pointerController = new PointerSpeedController(context);
        controllers.add(pointerController);
        controllers.add(new PreferenceCategoryController(context,
                KEY_POINTER_AND_TTS_CATEGORY).setChildren(
                Arrays.asList(pointerController, ttsPreferenceController)));
        // Input Assistance
        controllers.add(new SpellCheckerPreferenceController(context));
        controllers.add(new DefaultAutofillPreferenceController(context));
        controllers.add(new UserDictionaryPreferenceController(context));
        return controllers;
    }    

  先看到language的controller->PhoneLanguagePreferenceController

   @Override
    public boolean isAvailable() { //判断是否可用
        return mContext.getResources().getBoolean(R.bool.config_show_phone_language)
                && mContext.getAssets().getLocales().length > 1;
    }
    @Override
    public void updateState(Preference preference) {
        if (preference == null) {
            return;
        }
//更新Summary
        final String localeNames = FeatureFactory.getFactory(mContext)
                .getLocaleFeatureProvider().getLocaleNames();
        preference.setSummary(localeNames);
    }
//添加进不需要索引的list(即移除索引,因为该preference与其父界面名称一致)
    @Override
    public void updateNonIndexableKeys(List<String> keys) {
        // No index needed, because this pref has the same name as the parent page. Indexing it will
        // make search page look like there are duplicate result, creating confusion.
        keys.add(getPreferenceKey());
    }
//获得preference的key
    @Override
    public String getPreferenceKey() {
        return KEY_PHONE_LANGUAGE;
    }
    @Override
    public boolean handlePreferenceTreeClick(Preference preference) {
        if (!KEY_PHONE_LANGUAGE.equals(preference.getKey())) {
            return false;
        }
//新建SubSettingLauncher加载新的界面
        new SubSettingLauncher(mContext)
                .setDestination(LocaleListEditor.class.getName())
                .setSourceMetricsCategory(MetricsProto.MetricsEvent.SETTINGS_LANGUAGE_CATEGORY)
                .setTitle(R.string.pref_title_lang_selection)
                .launch();
        return true;
    }

PhoneLanguagePreferenceController继承于RestrictedSettingsFragment并实现了LocalePickerWithRegion.LocaleSelectedListener接口

RestrictedSettingsFragment是所有需要pin码保护的Settings子页面的基类,主要控制进入该设置项前的验证等。打开java文件

/**
 * A two-step locale picker. It shows a language, then a country.
 *
 * <p>It shows suggestions at the top, then the rest of the locales.
 * Allows the user to search for locales using both their native name and their name in the
 * default locale.</p>
 */
public class LocalePickerWithRegion extends ListFragment implements SearchView.OnQueryTextListener {

看到注释部分,这里告诉我们该类是一个选择器,用于显示语言以及所属国家,会在顶部显示建议语言,然后再显示所有可用的语言供选择,并且允许用户使用名称进行搜索。

    public interface LocaleSelectedListener {
        /**
         * The classes that want to retrieve the locale picked should implement this method.
         * @param locale    the locale picked.
         */
//方法在子类被重写
        void onLocaleSelected(LocaleStore.LocaleInfo locale);
    }
   @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        final LocaleStore.LocaleInfo locale =
                (LocaleStore.LocaleInfo) getListAdapter().getItem(position);
    //设置listener选中
        if (locale.getParent() != null) {
            if (mListener != null) {
                mListener.onLocaleSelected(locale);
            }
//设置后返回到父界面
            returnToParentFrame();
        }    

  重新回到LocaleListEditor,看到被重写的onLocaleSelected方法

  @Override
    public void onLocaleSelected(LocaleStore.LocaleInfo locale) {
        mAdapter.addLocale(locale);
        updateVisibilityOfRemoveMenu();
    }

  在调用Adapter的addLocale方法后更新了界面。

    void addLocale(LocaleStore.LocaleInfo li) {
        /*UNISOC for bug 945144 repetition localeInfo not add into list @{ */
        if (mFeedItemList.contains(li)) {
            Log.d(TAG," mFeedItemList  = " + mFeedItemList);
            return;
        }
        /* @} */
//添加后刷新界面,做更新处理
        mFeedItemList.add(li);
        notifyItemInserted(mFeedItemList.size() - 1);
        doTheUpdate();
    }
 public void doTheUpdate() {
      .....
        updateLocalesWhenAnimationStops(ll);
    }
 public void updateLocalesWhenAnimationStops(final LocaleList localeList) {
    ....
//调用LocalePicker的更新方法
                LocalePicker.updateLocales(mLocalesToSetNext);
    .....
    }

  最后更新到用户的系统配置中

    public static void updateLocales(LocaleList locales) {
        try {
            final IActivityManager am = ActivityManager.getService();
            final Configuration config = am.getConfiguration();
            config.setLocales(locales);
            config.userSetLocale = true;
            am.updatePersistentConfiguration(config);
            // Trigger the dirty bit for the Settings Provider.
            BackupManager.dataChanged("com.android.providers.settings");
        } catch (RemoteException e) {
            // Intentionally left blank
        }
    }

  在LocaleListEditor的onCreate方法中对Adapter和feedsList进行了初始化

    final List<LocaleStore.LocaleInfo> feedsList = getUserLocaleList();
        mAdapter = new LocaleDragAndDropAdapter(this.getContext(), feedsList);
    private List<LocaleStore.LocaleInfo> getUserLocaleList() {
        final List<LocaleStore.LocaleInfo> result = new ArrayList<>();
//调用Picker的getLocales方法后取出info赋值给result集合
        final LocaleList localeList = LocalePicker.getLocales();
        for (int i = 0; i < localeList.size(); i++) {
            Locale locale = localeList.get(i);
            result.add(LocaleStore.getLocaleInfo(locale));
        }
//分那会result集合
        return result;
    }

   说完初始化和添加,下面分析删除,看到覆写的onOptionsItemSelected方法,当点击右上角菜单选择删除后会判断是否处于删除模式,如果是则显示删除警告提醒,如果不是则设置为删除模式。

  

    private void setRemoveMode(boolean mRemoveMode) {
        this.mRemoveMode = mRemoveMode;
//调用Adapter的设置移除模式方法去更新界面
        mAdapter.setRemoveMode(mRemoveMode);
        mAddLanguage.setVisibility(mRemoveMode ? View.INVISIBLE : View.VISIBLE);
        updateVisibilityOfRemoveMenu();
    }
//Adapter设置自身为移除模式并且更新UI,将所有的item设置为未选中状态
   void setRemoveMode(boolean removeMode) {
        mRemoveMode = removeMode;
        int itemCount = mFeedItemList.size();
        for (int i = 0; i < itemCount; i++) {
            mFeedItemList.get(i).setChecked(false);
            notifyItemChanged(i);
        }
    }

  然后在onBindViewHolder中给每个checkbox设置监听,更改选中状态,此时用户选择点击删除按钮,就回到点击事件判断中的弹出删除警告方法,用户确认之后,关闭移除模式,并且调用Adapter的removeChecked方法移除所选中的item

 private void showRemoveLocaleWarningDialog() {
....
     .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        mRemoveMode = false;
                        mShowingRemoveDialog = false;
                        mAdapter.removeChecked();
                        setRemoveMode(false);
                    }
                })


//Adapter移除方法
  void removeChecked() {
        int itemCount = mFeedItemList.size();
        for (int i = itemCount - 1; i >= 0; i--) {
            if (mFeedItemList.get(i).getChecked()) {
                mFeedItemList.remove(i);
            }
        }
        notifyDataSetChanged();
        doTheUpdate();
    }
posted @ 2020-01-14 11:11  等下一个Bug  阅读(962)  评论(0)    收藏  举报