PreferenceFragmentCompat源码分析

preference菜单要在PreferenceFragment中使用,但是这个过期了,最新的建议使用PreferenceFragmentCompat。androidx需要引入的库为

androidx.preference:preference:1.2.0
public abstract class PreferenceFragmentCompat extends Fragment implements...

集成自Fragment,所以我们可以按照Fragment的生命周期来分析。

1、先看onCreate

 @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final TypedValue tv = new TypedValue();
        //设置主题
        requireContext().getTheme().resolveAttribute(R.attr.preferenceTheme, tv, true);
        int theme = tv.resourceId;
        //preferenceTheme为空时使用PreferenceThemeOverlay
        if (theme == 0) {
            // Fallback to default theme.
            theme = R.style.PreferenceThemeOverlay;
        }
        requireContext().getTheme().applyStyle(theme, false);

        //PreferenceManager是一个重要的类,需要使用它来管理Preference组件
        mPreferenceManager = new PreferenceManager(requireContext());
        mPreferenceManager.setOnNavigateToScreenListener(this);
        final Bundle args = getArguments();
        final String rootKey;
        if (args != null) {
            rootKey = getArguments().getString(ARG_PREFERENCE_ROOT);
        } else {
            rootKey = null;
        }
        //子类可以在这里面通过 setPreferenceScreen(PreferenceScreen)或        addPreferencesFromResource(int)将Preference提供给当前Fragment
        onCreatePreferences(savedInstanceState, rootKey);
    }

2、接下来就是onCreateView了

private int mLayoutResId = R.layout.preference_list_fragment;//默认使用布局
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {

/*使用preferenceFragmentCompatStyle主题样式,通过以下方式设置主题
<item name="preferenceFragmentCompatStyle">@style/SettingsPreferenceFragmentStyle</item>
*/

TypedArray a = requireContext().obtainStyledAttributes(null,
                R.styleable.PreferenceFragmentCompat,
                R.attr.preferenceFragmentCompatStyle,
                0);

//确定布局,这里面有一个重要的位置list_container,preference要加在这里
mLayoutResId = a.getResourceId(R.styleable.PreferenceFragmentCompat_android_layout,
                mLayoutResId);
.
.
.
 final View view = themedInflater.inflate(mLayoutResId, container, false);

//获取list_container
        final View rawListContainer = view.findViewById(AndroidResources.ANDROID_R_LIST_CONTAINER);
        if (!(rawListContainer instanceof ViewGroup)) {
            throw new IllegalStateException("Content has view with id attribute "
                    + "'android.R.id.list_container' that is not a ViewGroup class");
        }

        final ViewGroup listContainer = (ViewGroup) rawListContainer;

//创造RecyclerView
        final RecyclerView listView = onCreateRecyclerView(themedInflater, listContainer,
                savedInstanceState);
 if (listView == null) {
            throw new RuntimeException("Could not create RecyclerView");
        }

        mList = listView;

        //设置divider
        listView.addItemDecoration(mDividerDecoration);
        setDivider(divider);
        if (dividerHeight != -1) {
            setDividerHeight(dividerHeight);
        }
        mDividerDecoration.setAllowDividerAfterLastItem(allowDividerAfterLastItem);

        // If mList isn't present in the view hierarchy, add it. mList is automatically inflated
        // on an Auto device so don't need to add it.
        //将RecyclerView加入到list_container
        if (mList.getParent() == null) {
            listContainer.addView(mList);
        }
        mHandler.post(mRequestFocus);

        return view;
    }

3、默认布局preference_list_fragment.xml 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:ignore="NewApi"
    android:orientation="vertical"
    android:layout_height="match_parent"
    android:layout_width="match_parent" >

<!--recyclerview通过addView加入到这里,RecyclerView里面是Preference-->
    <FrameLayout
        android:id="@android:id/list_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <TextView android:id="@android:id/empty"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="8dp"
        android:gravity="center"
        android:visibility="gone" />

</LinearLayout>

4、onCreateRecyclerView

public RecyclerView onCreateRecyclerView(@NonNull LayoutInflater inflater,
            @NonNull ViewGroup parent, @Nullable Bundle savedInstanceState) {
        // If device detected is Auto, use Auto's custom layout that contains a custom ViewGroup
        // wrapping a RecyclerView
        if (requireContext().getPackageManager().hasSystemFeature(PackageManager
                .FEATURE_AUTOMOTIVE)) {
            RecyclerView recyclerView = parent.findViewById(R.id.recycler_view);
            if (recyclerView != null) {
                return recyclerView;
            }
        }
        //默认RecyclerView布局为preference_recyclerview
        RecyclerView recyclerView = (RecyclerView) inflater
                .inflate(R.layout.preference_recyclerview, parent, false);

        //设置排布方式,默认为LinearLayoutManager,子类可以改成Grid或者瀑布流排布
        recyclerView.setLayoutManager(onCreateLayoutManager());
        recyclerView.setAccessibilityDelegateCompat(
                new PreferenceRecyclerViewAccessibilityDelegate(recyclerView));

        return recyclerView;
    }

public RecyclerView.LayoutManager onCreateLayoutManager() {
        return new LinearLayoutManager(requireContext());
    }

5、其他重要的方法:

解析preferce菜单的xml文件,该xml根节点应该为PreferenceScreen
public void addPreferencesFromResource(@XmlRes int preferencesResId) {
        requirePreferenceManager();

        setPreferenceScreen(mPreferenceManager.inflateFromResource(requireContext(),
                preferencesResId, getPreferenceScreen()));
    }

//替换新的PreferenceScreen 
public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
...
}

//处理点击事件
public boolean onPreferenceTreeClick(@NonNull Preference preference) 

//RecyclerView要使用的Adapter
protected RecyclerView.Adapter onCreateAdapter(@NonNull PreferenceScreen preferenceScreen)

 参考文章:PreferenceFragmentCompat - 简书

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值