需求描写叙述

默认情况,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 xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/prefrence_switch_id"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent" >



</Switch>

上面布局中的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"?>

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >



    <com.wtk.gesture.modules.GestureSwitchPreference

        android:key="GestureSwitchPreference"

        android:summary="概要"

        android:title="标题" />



</PreferenceScreen>


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的绑定事件的更多相关文章

  1. ANDROID L——Material Design详解(UI控件)

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! Android L: Google已经确认Android L就是Android Lolli ...

  2. nexus7 二代 升级 android L

    折腾了半天 ,最后发现其实很简单... 1.装好windows下gdb和bootloader的驱动,注意打开usb debug,另外进入bootloader是开机按电源键和音量减小键,至于要解锁这个想 ...

  3. Ubuntu 试用Android L版本

    Android L是最近google一个大更新的版本,目前google开发了android L的开发者预览版本,对于一个android 开发者来说很定是要下载下来体验一把,顺便也要了解一下Androi ...

  4. [Android L]SEAndroid开放设备文件结点权限(读或写)方法(涵盖常用操作:sys/xxx、proc/xxx、SystemProperties)

    温馨提示      建议你先了解一下上一篇博文([Android L]SEAndroid增强Androd安全性背景概要及带来的影响)所讲的内容,先对SEAndroid窥个全貌,然后再继续本节内容.   ...

  5. [Android L]SEAndroid增强Androd安全性背景概要及带来的影响

    1  SEAndroid背景   Android对于操作系统安全性方面的增强一直沿用Linux内核所提供的MAC强制访问控制套件SELinux,对权限进行了更为深度的管理,有效地控制着进程对资源的访问 ...

  6. tcpdump for android L 5.x with pie support

    由于使用了NDK编译的可执行文件在应用中调用,在4.4及之前的版本上一直没出问题. 最近由于要测试在Android L上的运行情况发现,当运行该可执行文件时,报如下错误: error: only po ...

  7. [转]ANDROID L——Material Design详解(动画篇)

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 转自:http://blog.csdn.net/a396901990/article/de ...

  8. Android L Camera2 API 使用实例程序汇总

    在网上发现几个使用Camera API2开发的实例程序,总结一下方便后续参考: 1.Camera2 Basic : https://github.com/googlesamples/android-C ...

  9. Android L 使用ART能提高多少性能?

    点击打开链接 刚刚结束的 Google I/O 大会上,Android 下一代操作系统「L」带来不少惊喜.新系统运行更快.更省电. 然而开发者对这个新系统也有颇多疑问,比如新的运行模式 ART 对开发 ...

随机推荐

  1. BZOJ 4828 DP+BFS

    被一道简单BFS坑了这么长时间我也是hhh了 //By SiriusRen #include <bits/stdc++.h> using namespace std; ,,):d(D),x ...

  2. JS中的面相对象

    1.使用Object或对象字面量创建对象 JS中最基本创建对象的方式: var student = new Object(); student.name = "easy"; stu ...

  3. Android -----listView的重要属性

    android:transcriptMode="alwaysScroll" android:cacheColorHint="#00000000" android ...

  4. js 计算时间差

    function GetDateDiff(startDate,endDate) { var startTime = new (<any>Date)(Date.parse(startDate ...

  5. 程序员的幽默-献给所有Java程序员

    1. 一程序员去面试,面试官问:“你毕业才两年,这三年工作经验是怎么来的?!”程序员答:“加班.” 2. 某程序员对书法十分感兴趣,退休后决定在这方面有所建树.于是花重金购买了上等的文房四宝.一日,饭 ...

  6. 批量注释LOG

    sed -i "s/LOG/\/\/ LOG/g" `grep LOG\(TRACE\) -rl .`

  7. git生成ssh key及本地解决多个ssh key的问题

    git生成ssh key及本地解决多个ssh key的问题 ssh是一种网络协议,用于计算机之间的加密登录.ssh原理及应用可参考: SSH原理与运用(一):远程登录 生成ssh key步骤 这里以配 ...

  8. 关于WEB开发下面DIV层被OCX控件拦住问题

    控件分为有窗口控件与无窗口控件,无窗口控件很好办,如flash控件,可以通过添加wmode属性来解决挡住DIV层这个问题,添加的代码如下: 解决无窗口控件挡住DIV: 1 <param  nam ...

  9. form:input 标签使用

    <form:input path="suplier" htmlEscape="false" maxlength="50" id=&qu ...

  10. Django - 获取表单数据的三种方式

    1.query set 对象 2.字典 3.query set 元组 备注:对象通过 ”对象.列名"方式访问,元组通过“对象.索引”方式访问.