[Android L or M ]解除SwitchPreference与Preference的绑定事件
需求描写叙述
默认情况,Android的两个控件SwitchPreference和CheckBoxPreference的事件处理是和Preference整个区域的事件绑定在一起的,然而,有时须要将其事件分开处理,即点击Preference整个区域时,不会改变SwitchPreference状态,仅当点击SwitchPreference时才去处理SwitchPreference的开关状态,如点击Preference整个区域弹出一个对话框或跳转到某个界面,点击SwitchPreference时仅是改变开关状态,不弹出对话框或不跳转.这种需求该怎样实现呢?以下将会列举几个经常使用实现方法:
SwitchPreference和CheckBoxPreference都是继承自TwoStatePreference,以下仅以SwitchPreference介绍,CheckBoxPreference的实现方式是一样的.
【声明】欢迎转载,但请保留文章原始出处:http://blog.csdn.net/yelangjueqi/article/details/46754711
一 继承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 or M上面执行,仅适用于源代码环境,由于com.android.internal.R.id.switchWidget是私有的
再提供一个案例:点击switch或整个开关区域 弹出一个确认框,当用户确认之后再去改变Switch开关的状态
import android.content.Context;
import android.preference.SwitchPreference;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Switch;
import android.util.Log;
import android.util.TypedValue; /**
*
* 点击switch或整个开关区域 弹出一个确认框,当用户确认之后再去改变Switch开关的状态
*
*
*/
public class SwitchPreferenceOnly extends SwitchPreference {
private static final String CLASS_TAG = SwitchPreferenceOnly.class.getSimpleName(); private Switch switchView = null;
private OnSwitchCheckedChangeListener mOnSwitchCheckedListener; public interface OnSwitchCheckedChangeListener {
public boolean OnSwitchCheckedChanged(Switch compoundButton, boolean checked);
} public void setOnSwitchCheckedChangeListener(OnSwitchCheckedChangeListener listener) {
mOnSwitchCheckedListener = listener;
} public SwitchPreferenceOnly(Context paramContext) {
super(paramContext);
} public SwitchPreferenceOnly(Context paramContext, AttributeSet paramAttributeSet) {
this(paramContext, paramAttributeSet, com.android.internal.R.attr.switchPreferenceStyle);
} public SwitchPreferenceOnly(Context paramContext, AttributeSet paramAttributeSet, int paramInt) {
super(paramContext, paramAttributeSet, paramInt);
} @Override
protected View onCreateView(ViewGroup parent) {
View mView = super.onCreateView(parent);
switchView = (Switch) mView.findViewById(com.android.internal.R.id.switchWidget); // false to disable flow,because switch click event can't produce water ripple effect
if (false && switchView != null) {
//Switch和Preference事件切割开了
switchView.setClickable(true);
switchView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP
|| event.getAction() == MotionEvent.ACTION_CANCEL) { switchView.playSoundEffect(SoundEffectConstants.CLICK);// play click sound
handleSwitchChangeState();
}
return true;// return true to ignore click event
}
});
}
return mView;
} public void toggle() {
if (switchView != null) {
handleSwitchChangeState();
}
} private void handleSwitchChangeState() {
if (switchView != null) {
switchView.setChecked(!switchView.isChecked());
if (mOnSwitchCheckedListener != null) {
mOnSwitchCheckedListener.OnSwitchCheckedChanged(switchView,
switchView.isChecked());
}
}
} @Override
public void onClick() {
// not do anything here
}
}
用法:
public class MainActivity extends PreferenceActivity implements
Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { private SwitchPreferenceOnly mFingerprintStatusBar; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.xxx); mFingerprintStatusBar.setOnPreferenceClickListener(this);
mFingerprintStatusBar.setOnSwitchCheckedChangeListener(new SwitchPreferenceOnly.OnSwitchCheckedChangeListener() {
@Override
public boolean OnSwitchCheckedChanged(Switch compoundButton, boolean checked) {
// TODO
return false;
}
});
} @Override
public boolean onPreferenceClick(Preference pref) {
if (pref instanceof Preference && (KEY_FINGERPRINT_STATUS_BAR.equals(pref.getKey()))) {
mFingerprintStatusBar.toggle();
}
return false;
}
......
}
二 通过switch控件实现
调用Preference的setWidgetLayoutResource方法实现控件替换
1. Layout布局文件:smart_gesture_switch.xml
| <?
xml version="1.0" encoding="utf-8"? > |
上面布局中的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
| <?
xml version="1.0" encoding="utf-8"?> |
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
| <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 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" > <RadioGroup 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" > <RadioButton 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" /> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:contentDescription="@null" android:scaleType="centerCrop" android:src="@drawable/zzz_gesture_tab_space" /> <RadioButton 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" /> </RadioGroup> <TextView 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" /> </LinearLayout> |
3.效果图:
[Android L or M ]解除SwitchPreference与Preference的绑定事件的更多相关文章
- ANDROID L——Material Design详解(UI控件)
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! Android L: Google已经确认Android L就是Android Lolli ...
- nexus7 二代 升级 android L
折腾了半天 ,最后发现其实很简单... 1.装好windows下gdb和bootloader的驱动,注意打开usb debug,另外进入bootloader是开机按电源键和音量减小键,至于要解锁这个想 ...
- Ubuntu 试用Android L版本
Android L是最近google一个大更新的版本,目前google开发了android L的开发者预览版本,对于一个android 开发者来说很定是要下载下来体验一把,顺便也要了解一下Androi ...
- [Android L]SEAndroid开放设备文件结点权限(读或写)方法(涵盖常用操作:sys/xxx、proc/xxx、SystemProperties)
温馨提示 建议你先了解一下上一篇博文([Android L]SEAndroid增强Androd安全性背景概要及带来的影响)所讲的内容,先对SEAndroid窥个全貌,然后再继续本节内容. ...
- [Android L]SEAndroid增强Androd安全性背景概要及带来的影响
1 SEAndroid背景 Android对于操作系统安全性方面的增强一直沿用Linux内核所提供的MAC强制访问控制套件SELinux,对权限进行了更为深度的管理,有效地控制着进程对资源的访问 ...
- tcpdump for android L 5.x with pie support
由于使用了NDK编译的可执行文件在应用中调用,在4.4及之前的版本上一直没出问题. 最近由于要测试在Android L上的运行情况发现,当运行该可执行文件时,报如下错误: error: only po ...
- [转]ANDROID L——Material Design详解(动画篇)
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 转自:http://blog.csdn.net/a396901990/article/de ...
- Android L Camera2 API 使用实例程序汇总
在网上发现几个使用Camera API2开发的实例程序,总结一下方便后续参考: 1.Camera2 Basic : https://github.com/googlesamples/android-C ...
- Android L 使用ART能提高多少性能?
点击打开链接 刚刚结束的 Google I/O 大会上,Android 下一代操作系统「L」带来不少惊喜.新系统运行更快.更省电. 然而开发者对这个新系统也有颇多疑问,比如新的运行模式 ART 对开发 ...
随机推荐
- VC窗口类的销毁-是否需要delete
Windows窗口如果使用new的方法添加之后,在父窗口析构的时候,有些需要delete有些却不需要delete.这个的确有点坑,由于c++的实现,对于每个自己new的对象,我都会delete删除它, ...
- gtest ASSERT_TRUE和EXPECT_TRUE
调用ASSERT_TRUE的函数,返回值类型定义必须是void,如果想返回别的类型,就用EXPECT_TRUE: void abc::fun() { ASSERT_TRUE(fun1()); } bo ...
- 白盒-CNN纹理深度可视化: 使用MIT Place 场景预训练模型
MIT发文:深度视觉的量化表示................ Places2 是一个场景图像数据集,包含 1千万张 图片,400多个不同类型的场景环境,可用于以场景和环境为应用内容的视觉认知任务. ...
- 2016.01.07 DOM笔记(二) DOM节点
node节点属性 nodeName属性 oneBox= document.getElementsById('box');var s = oneBox.nodeName; //nodeName与tag ...
- MYSQL数据库迁移到ORACLE数据库
一.环境和需求1.环境 MySQL数据库服务器: OS version:Linux 5.3 for 64 bit mysql Server version: 5.0.45 Oracle数据库服务器: ...
- Windows 8 常见教程
http://www.codeproject.com/Articles/439874/Web-service-on-Windows-Phone http://www.c-sharpcorner.com ...
- .net core 使用 textSharp生成pdf
引入Nuget包 using iTextSharp.text; using iTextSharp.text.pdf; using System; using System.IO; namespace ...
- CAD从二制流数据中加载图形(com接口)
主要用到函数说明: _DMxDrawX::ReadBinStream 从二制流数据中加载图形,详细说明如下: 参数 说明 VARIANT varBinArray 二制流数据,是个byte数组 BSTR ...
- 爬虫文件存储-3:Redis
前提条件: 安装并运行redis服务端程序,安装RedisPy库 说明:Redis 是 StrictRedis 的子类,它的主要功能是用于向后兼容旧版本库里的几个方法,官方推荐使用 StrictRed ...
- Linux下的find命令
Linux下find命令在目录结构中搜索文件,并执行指定的操作.Linux下find命令提供了相当多的查找条件,功能很强大.即使系统中含有网络文件系统,find命令在该文件系统中同样有效.在运行一个非 ...