需求描述
默認情況,Android的兩個控件SwitchPreference和CheckBoxPreference的事件處理是和Preference整個區域的事件綁定在一起的,然而,有時需要將其事件分開處理,即點擊Preference整個區域時,不會改變SwitchPreference狀態,僅當點擊SwitchPreference時才去處理SwitchPreference的開關狀態,如點擊Preference整個區域彈出一個對話框或跳轉到某個界面,點擊SwitchPreference時僅是改變開關狀態,不彈出對話框或不跳轉.這樣的需求該如何實現呢?下面將會列舉幾個常用實現方法:
SwitchPreference和CheckBoxPreference都是繼承自TwoStatePreference,下面僅以SwitchPreference介紹,CheckBoxPreference的實現方式是一樣的.
一 繼承SwitchPreference重新復寫一個Preference
import android.content.Context;
import android.preference.SwitchPreference;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Switch;
import com.wtk.gesture.utils.MyLogger;
public class SmartSwitchPreference extends SwitchPreference {
private static final String CLASS_TAG = MyLogger.APP_TAG + / + SmartSwitchPreference.class.getSimpleName();
public SmartSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public SmartSwitchPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SmartSwitchPreference(Context context) {
super(context);
}
@Override
protected void onClick() {
Log.d(CLASS_TAG, onClick());
}
//下面這段代碼,在Android L版本(5.0)之前是不需要的,在Android L版本上必須要有,否則switch獲取不到點擊事件
//此處廢了我不少時間查找原因:從KK移植到L上面就不起作用了.因此L版本上面必須要有下面這段
@Override
protected View onCreateView(ViewGroup parent) {
View view = super.onCreateView(parent);
Switch v = (Switch) view.findViewById(com.android.internal.R.id.switchWidget);
if (v != null) {
v.setClickable(true);
}
return view;
}
}
不足之處:如果在Android L上面運行,僅適用於源碼環境,因為com.android.internal.R.id.switchWidget是私有的
二 通過switch控件實現
調用Preference的setWidgetLayoutResource方法實現控件替換
1. Layout布局文件:smart_gesture_switch.xml
android:id=@+id/prefrence_switch_id
android:layout_width=fill_parent
android:layout_height=fill_parent >
上面布局中的Switch也可以替換成Checkbox or RadioButton
2. 引用smart_gesture_switch布局:GestureSwitchPreference.java
import android.content.Context;
import android.preference.SwitchPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.Switch;
import android.widget.Toast;
import com.wtk.gesture.quick.R;
import com.wtk.gesture.utils.MyLogger;
public class GestureSwitchPreference extends SwitchPreference {
private static final String CLASS_TAG = MyLogger.APP_TAG + / + GestureSwitchPreference.class.getSimpleName();
private Switch mSwitch;
private boolean mChecked = false;
private Context mContext;
// // ///////////////////////////////////////////Custom Listenr Start
// private OnRadioButtonCheckedListener mOnRadioButtonCheckedListener;
//
// public interface OnRadioButtonCheckedListener {
// public void OnRadioButtonChecked(boolean isScreenOffView);
// }
//
// public void setOnRadioButtonCheckedListener(OnRadioButtonCheckedListener
// listener) {
// mOnRadioButtonCheckedListener = listener;
// }
//
// // ///////////////////////////////////////////Custom Listenr End
public GestureSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
}
public GestureSwitchPreference(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
//通過調用setWidgetLayoutResource方法來更新preference的widgetLayout,即更新控件區域
setWidgetLayoutResource(R.layout.smart_gesture_switch);
}
public GestureSwitchPreference(Context context) {
super(context);
mContext = context;
//通過調用setWidgetLayoutResource方法來更新preference的widgetLayout,即更新控件區域
setWidgetLayoutResource(R.layout.smart_gesture_switch);
}
@Override
protected void onBindView(View view) {
mSwitch = (Switch) view.findViewById(R.id.prefrence_switch_id);
//view即是代表的preference整個區域,可以對該view進行事件監聽,也就是實現了preference整個區域的點擊事件
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
showToast(section-all);
//此處調用自定義的監聽器A方法,該監聽器A接口應由使用GestureSwitchPreference的類來實現,從而實現
//preference整個區域的點擊事件.注:監聽器A的定義可以參考OnRadioButtonCheckedListener接口的定義
}
});
//switch開關的點擊事件
if (mSwitch != null) {
mSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton button, boolean checked) {
mChecked = checked;
showToast(only-switch-section);
//此處調用自定義的監聽器B方法,該監聽器B接口應由使用GestureSwitchPreference的類來實現,從而實現
//preference的switch點擊事件.注:監聽器B的定義可以參考OnRadioButtonCheckedListener接口的定義
}
});
}
setChecked(mChecked);
super.onBindView(view);
}
public boolean isChecked() {
return mChecked;
}
public void setChecked(boolean bChecked) {
mChecked = bChecked;
if (mSwitch != null) {
mSwitch.setChecked(bChecked);
}
}
private void showToast(String info) {
Toast mToast = null;
if (mToast == null) {
mToast = Toast.makeText(mContext, info, 5000);
}
mToast.setText(info);
mToast.show();
}
}
3. 引用GestureSwitchPreference:smart_quick_gesture_settings.xml
android:key=GestureSwitchPreference
android:summary=概要
android:title=標題 />
4. 主界面:SmartQuickGestureSettings.java
public class SmartQuickGestureSettings extends PreferenceActivity {
private static final String TAG = MyLogger.APP_TAG + / + SmartQuickGestureSettings.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.smart_quick_gesture_settings);
}
}
5. 效果圖:
點擊preference整個區域
點擊switch:
上述實現方式不足之處是:
A 代碼量比較大
B 需要主動維護switch開關的狀態,否則退出再重新進入時switch開關狀態依舊是原來狀態
三 擴展:完全自定義Preference布局
1 .SmartGesturePrefrence.java
import android.content.Context;
import android.preference.Preference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;
import com.wtk.gesture.quick.R;
import com.wtk.gesture.utils.MyLogger;
public class SmartGesturePrefrence extends Preference {
private static final String CLASS_TAG = MyLogger.APP_TAG + / + SmartGesturePrefrence.class.getSimpleName();
public static boolean isScreenOffBtn = true;// default display gesture view
private Context mContext;
private OnRadioButtonCheckedListener mOnRadioButtonCheckedListener;
public interface OnRadioButtonCheckedListener {
public void OnRadioButtonChecked(boolean isScreenOffView);
}
public void setOnRadioButtonCheckedListener(OnRadioButtonCheckedListener listener) {
mOnRadioButtonCheckedListener = listener;
}
public SmartGesturePrefrence(Context context) {
this(context, null);
}
public SmartGesturePrefrence(Context context, AttributeSet attrs) {
this(context, attrs, 0);
mContext = context;
}
public SmartGesturePrefrence(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
setLayoutResource(R.layout.gesture_preference_layout);
}
@Override
protected void onBindView(final View view) {
super.onBindView(view);
RadioGroup mRadioGroup = (RadioGroup) view.findViewById(R.id.radiogroup_gesture);
RadioButton mScreenOffButton = (RadioButton) view.findViewById(R.id.btn_screen_off);
RadioButton mPhoneCallingButton = (RadioButton) view.findViewById(R.id.btn_phone_calling);
if (isScreenOffBtn) {
mScreenOffButton.setChecked(true);
} else {
mPhoneCallingButton.setChecked(true);
}
mRadioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.btn_screen_off:
isScreenOffBtn = true;
if (mOnRadioButtonCheckedListener != null) {
mOnRadioButtonCheckedListener.OnRadioButtonChecked(true);
}
showToast(screen_off);
break;
case R.id.btn_phone_calling:
isScreenOffBtn = false;
if (mOnRadioButtonCheckedListener != null) {
mOnRadioButtonCheckedListener.OnRadioButtonChecked(false);
}
showToast(phone_calling);
break;
}
}
});
}
private void showToast(String info) {
Toast mToast = null;
if (mToast == null) {
mToast = Toast.makeText(mContext, info, 5000);
}
mToast.setText(info);
mToast.show();
}
}
2. gesture_preference_layout.xml
android:layout_width=match_parent
android:layout_height=wrap_content
android:gravity=center_vertical
android:minHeight=20dp
android:orientation=vertical
android:paddingEnd=?android:attr/scrollbarSize
android:paddingStart=?android:attr/scrollbarSize >
android:id=@+id/radiogroup_gesture
android:layout_width=wrap_content
android:layout_height=52dip
android:layout_marginLeft=0dip
android:layout_marginRight=0dip
android:layout_marginTop=6dip
android:background=@android:color/black
android:gravity=center_vertical
android:orientation=horizontal >
android:id=@+id/btn_screen_off
android:layout_width=wrap_content
android:layout_height=wrap_content
android:background=@drawable/zzz_radio_selector
android:button=@null
android:gravity=center
android:text=@string/title_mode_idle
android:textSize=16sp />
android:layout_width=match_parent
android:layout_height=match_parent
android:contentDescription=@null
android:scaleType=centerCrop
android:src=@drawable/zzz_gesture_tab_space />
android:id=@+id/btn_phone_calling
android:layout_width=wrap_content
android:layout_height=wrap_content
android:background=@drawable/zzz_radio_selector
android:button=@null
android:gravity=center
android:text=@string/title_mode_call
android:textSize=16sp />
android:id=@+id/hint_info
android:layout_width=wrap_content
android:layout_height=wrap_content
android:layout_marginLeft=6dip
android:layout_marginRight=6dip
android:ellipsize=marquee
android:fadingEdge=horizontal
android:singleLine=true
android:text=@string/gesture_operate_description
android:textAppearance=?android:attr/textAppearanceSmall
android:visibility=gone />
3.效果圖: