需求描写叙述

默认情况,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.效果图:

最新文章

  1. 今天在在linux环境下 管理自己的php项目时 删除一个分类 结果报了一个Table表名 doesn’t exist
  2. JSCH通过密钥文件进行远程访问
  3. java中HashMap详解
  4. 里德九步审讯法 z
  5. MySQL 性能优化
  6. 梦断代码3-message center消息的集中分发
  7. 函数function的方法call()以及apply()
  8. HDU 3966 dfs序+LCA+树状数组
  9. 04737_C++程序设计_第1章_认识C++的对象
  10. 【转】jsp 表单form传值
  11. 关于Update语句的锁
  12. iOS之Xcode修改应用图标
  13. 嵌入式linux——汇编、C语言基础(一)
  14. valgrind 检查内存泄露
  15. 【bzoj 2049】Cave 洞穴勘测
  16. dto vo
  17. angular的组件通信
  18. 12 extremely useful hacks for JavaScript
  19. USB设备驱动_WDS
  20. CSS3完善和模式

热门文章

  1. JavaScript--innerHTML 属性
  2. 一键生成Spring MVC + MyBatis + maven项目
  3. Objective-C——Runtime理解
  4. 【转】Java 集合系列11之 Hashtable详细介绍(源码解析)和使用示例
  5. 4.用Redis Desktop Manager连接Redis(Windows)
  6. Django中图片的上传并显示
  7. PHP 之CURL请求封装GET、POST、PUT、DELETE
  8. java aop面向切面编程
  9. 使用Oracle函数在创建表的时候自动加入生成的流水号 生成格式是:前缀+年月日+00000
  10. The C++ Programming Language - Bjarne Stroustrup