持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情
接下来会对
Preference Library官方库进行一个系列讲解,本篇文章是Preference Library系列的第八篇,主要是介绍Preference Library的触摸事件分发机制。
历史文章
练气篇:设置界面的开发利器Preference Library,了解一下~
筑基篇:设置界面的开发利器Preference Library,了解一下~
金丹篇:设置界面的开发利器Preference Library,了解一下~
元婴篇:设置界面的开发利器Preference Library,了解一下~
化神篇:设置界面的开发利器Preference Library,了解一下~
炼虚篇:设置界面的开发利器Preference Library,了解一下~
合体篇:设置界面的开发利器Preference Library,源码浅析一下
Preference的触摸事件是如何执行的?
上一篇文章合体篇:设置界面的开发利器Preference Library,源码浅析一下 有讲过,Preference Library就是基于RecyclerView实现的多布局列表,所以Preference的点击事件的设置应该就是在PreferenceGroupAdapter中,最终定位到onBindViewHolder()方法:
@Override
public void onBindViewHolder(@NonNull PreferenceViewHolder holder, int position) {
final Preference preference = getItem(position);
holder.resetState();
preference.onBindViewHolder(holder);
}
紧接着分发到了Preference的onBindViewHolder()方法:
public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
View itemView = holder.itemView;
itemView.setOnClickListener(mClickListener);
//...
}
很清晰的看到,Preference设置项的点击事件就在这里设置的,即itemView.setOnClickListener(),我们看下mClickListener这个对象:
private final View.OnClickListener mClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
performClick(v);
}
};
一直往下走,最终调用到了performClick()方法:
public void performClick() {
//1.
if (!isEnabled() || !isSelectable()) {
return;
}
//2.
onClick();
//3.
if (mOnClickListener != null && mOnClickListener.onPreferenceClick(this)) {
return;
}
PreferenceManager preferenceManager = getPreferenceManager();
//4.
if (preferenceManager != null) {
PreferenceManager.OnPreferenceTreeClickListener listener = preferenceManager
.getOnPreferenceTreeClickListener();
if (listener != null && listener.onPreferenceTreeClick(this)) {
return;
}
}
//5.
if (mIntent != null) {
Context context = getContext();
context.startActivity(mIntent);
}
}
上面核心有五点,接下来一步步进行分析:
1. 判断能否触发点击
public boolean isEnabled() {
return mEnabled && mDependencyMet && mParentDependencyMet;
}
public boolean isSelectable() {
return mSelectable;
}
核心的两个属性mEnabled和mSelectable可以在xml中进行配置,是否允许该设置项点击 :
<SwitchPreferenceCompat
app:enabled="false"
app:selectable="false"/>
或者可以通过setEnabled()/setSelectable()在代码中动态设置。
2. onClick()第一个响应点击事件
protected void onClick() {}
Preference的子类可以选择性重写该方法,比如SwitchPreferenceCompat的父类TwoStatePreference就重写了该方法,实现了右边的按钮切换刷新:
protected void onClick() {
super.onClick();
final boolean newValue = !isChecked();
if (callChangeListener(newValue)) {
setChecked(newValue);
}
}
最终调用setChecked()方法通知RecyclerView的适配器调用notifyItemChanged()单刷该设置项,非常的优雅。
3. OnPreferenceClickListener.onPreferenceClick()第二个响应点击事件
这个对象我们可以通过外部调用setOnPreferenceClickListener()进行传入,来响应这个点击事件:
public void setOnPreferenceClickListener(
@Nullable OnPreferenceClickListener onPreferenceClickListener) {
mOnClickListener = onPreferenceClickListener;
}
如果重写的这个对象的onPreferenceClick()方法返回true,就结束点击事件分发了,下面的逻辑都不会走了。
这个监听器是单独为某个Preference设置的,私有的,不被其他的Preference共享。
4. PreferenceManager.OnPreferenceTreeClickListener第三个响应点击事件
这个对象也可以通过外部进行传入,调用PreferenceManager.setOnPreferenceTreeClickListener()就行:
public void setOnPreferenceTreeClickListener(
@Nullable OnPreferenceTreeClickListener listener) {
mOnPreferenceTreeClickListener = listener;
}
和上面一样,如果这个对象的setOnPreferenceTreeClickListener()返回true,就结束点击事件分发了,下面的逻辑都不会走了。
这个监听器是设置项之间共享的,因为它被PreferenceManager持有,而PreferenceManager又是全局的对象。
5. Intent第四个响应点击事件
这个Intent就是之前我们在讲的在xml配置的跳转intent:
<Preference
app:persistent="false"
app:icon="@drawable/ic_launcher_foreground"
app:key="develop"
app:title="开发者选项">
<intent
android:targetClass="com.example.m3demo.DevelopActivity"
android:targetPackage="com.example.m3demo" />
</Preference>
当然了这个intent也支持代码动态设置,不过从上面就可以看出,这个intent响应点击事件的优先级比较低,得前面的两个监听器都不拦截才能得到执行的机会。
总结
本篇文章主要讲解了Preference点击事件是如何分发实现的,以及响应点击事件对象之间的优先级,哪个先响应,哪个优先级最低,希望本篇文章能对你有所帮助。