• [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 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.效果图:


  • 相关阅读:
    利用console控制台调试php代码
    数据库比对脚本(PHP版)
    Symfony框架系列----1.入门安装
    Symfony框架系列----常用命令
    Symfony命令行
    Linux SCP指令
    Linux 搭建SVN服务器
    Linux下 保存 git账号密码
    js 视差滚动 记录备份
    移动端 -webkit-user-select:text; ios10 bug 解决方案
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/7115652.html
Copyright © 2020-2023  润新知