Preference:点击没反应?
最近在某应用中加了一个Preference:
private Preference mSelect;
@Override
public void onResume() {
...
if(mSelect==null) {
mSelect=(Preference)findPreference(KEY_SELECT);
mSelect.setOnPreferenceChangeListener(this);
}
...
}
期望在点击时弹出一个界面,所以在onPreferenceChange 加了如下处理:
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
...
}else if(preference == mSelect){
log("show selet dialog");
this.showDialog(SHOW_SELECT_DIALOG);//显示选择界面
}
return true;
}
但事与愿违,点击后没有任何反应,期望的log"show selet dialog"也没有出现。查了类似的源码,相应的处理是放在onPreferenceTreeClick 中的,于是修改代码如下:
@Override
public boolean onPreferenceTreeClick(Preference preference) {
log("onPreferenceTreeClick preference:"+preference);
if (preference == mSelect) {
log("onPreferenceTreeClick: show selet dialog");
this.showDialog(SHOW_SELECT_DIALOG);
}
return super.onPreferenceTreeClick(preference);
}
...
点击后界面正常弹出,问题解决。为什么会这样呢?
看一下 frameworks\support\v7\preference\src\android\support\v7\preference\Preference.java 中的 performClick:
/**
* Called when a click should be performed.
*
* @hide
*/
@RestrictTo(GROUP_ID)
public void performClick() {
if (!isEnabled()) {
return;
}
onClick();//1
if (mOnClickListener != null && mOnClickListener.onPreferenceClick(this)) {
return;
}
PreferenceManager preferenceManager = getPreferenceManager();
if (preferenceManager != null) {
PreferenceManager.OnPreferenceTreeClickListener listener = preferenceManager
.getOnPreferenceTreeClickListener();
if (listener != null && listener.onPreferenceTreeClick(this)) {//2
return;
}
}
if (mIntent != null) {
Context context = getContext();
context.startActivity(mIntent);
}
}
该方法是在执行点击事件时被调用。对于我们熟悉的SwitchPreference来说,执行点击后运行到 performClick() 方法的标记1处的onClick 时,会执行TwoStatePreference 的 onClick:
@Override
protected void onClick() {
super.onClick();
final boolean newValue = !isChecked();
if (callChangeListener(newValue)) {//1
setChecked(newValue);
}
}
通过标记1处的callChangeListener 调用到 Preference 的 callChangeListener:
public boolean callChangeListener(Object newValue) {
return mOnChangeListener == null || mOnChangeListener.onPreferenceChange(this, newValue);
}
所以对SwitchPreference的点击事件的处理一般都放在onPreferenceChange()方法中。继续看performClick,当执行到标记2处时,会调用onPreferenceTreeClick,所以对SwitchPreference的事件处理也可以放在onPreferenceTreeClick()方法中。
但对Preference来说,当执行到performClick 的标记1处时,它的onClick()方法为空,所以不会调用到onPreferenceChange(),只有执行到标记2处时,调用onPreferenceTreeClick()。所以我把显示界面放在 onPreferenceChange() 无效,而放在onPreferenceTreeClick() 有效。
总结:Preference 的点击事件不会触发onPreferenceChange() ,只会触发onPreferenceTreeClick();而SwitchPreference 的点击事件二者皆会触发。