解除SwitchPreference与preference 的绑定事件及单独调用Switch控件
来源:互联网 发布:windows hadoop2.7.3 编辑:程序博客网 时间:2024/05/29 00:33
应用场景:
公司要求在设备上添加一个以太网的视频网卡,我负责在Setting里添加一个UI可以对DHCP服务器进行开或者关的操作。
首先我定义了一个EthernetSettings 继承 SettingsPreferenceFragment,用addPreferencesFromResource(R.xml.ethernet_settings) 加载布局文件。
<?xml version="1.0" encoding="utf-8"?><PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="@string/ethernet_settings" > <Preference android:key="local_connection_key" android:title="@string/local_connection" > </Preference> <PreferenceCategory android:title="@string/lan_configuration" > <com.android.settings.ethernet.views.SmartSwitchPreference android:key="dhcp_setting_key" android:title="@string/dhcp_setting" /> <Preference android:key="port_mapping_key" android:title="@string/port_mapping" > </Preference> </PreferenceCategory></PreferenceScreen>
刚开始dhcp_setting_key我定义的是SwitchPreference 但是问题来了,点击preference跳转到新设置界面的时候,同时也会对Switch进行操作。仔细分析源码后发现在SwitchPreference 父类onClick方法中对switch进行了操作,那么解决这个问题就简单了,重写一个 继承SwitchPreference的类,将onClick方法重写就可以了(因为我不需要操作,直接为空就好)。下面贴上代码!
package com.android.settings.ethernet.views;import android.content.Context;import android.os.SystemProperties;import android.preference.SwitchPreference;import android.text.TextUtils;import android.util.AttributeSet;import com.android.settings.R;import android.view.View.OnClickListener;import android.view.View;import android.view.ViewGroup;import android.widget.Switch;import android.widget.CompoundButton.OnCheckedChangeListener;import android.widget.CompoundButton;public class SmartSwitchPreference extends SwitchPreference { public Switch mDhcpSwitch ; private String mEthernetStatus; private boolean mChecked; public SmartSwitchPreference(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setWidgetLayoutResource(R.layout.ethernet_preference_header_switch_item); } public SmartSwitchPreference(Context context, AttributeSet attrs) { super(context, attrs); setWidgetLayoutResource(R.layout.ethernet_preference_header_switch_item); } public SmartSwitchPreference(Context context) { super(context); setWidgetLayoutResource(R.layout.ethernet_preference_header_switch_item); } @Override public void onBindView(View view) { super.onBindView(view); mDhcpSwitch = (Switch) view.findViewById(R.id.ethernet_switchWidget); initSwitch(); mDhcpSwitch.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mDhcpSwitch.isChecked()) { SystemProperties.set("sys.dnsmasq.status", "on"); } else { SystemProperties.set("sys.dnsmasq.status", "off"); } } }); mDhcpSwitch.setChecked(mChecked); } @Override protected View onCreateView(ViewGroup parent) { // TODO Auto-generated method stub return super.onCreateView(parent); } @Override public void setChecked(boolean checked) { mChecked = checked; notifyChanged(); } @Override public boolean isChecked() { // TODO Auto-generated method stub return super.isChecked(); } public void initSwitch() { mEthernetStatus = SystemProperties.get("sys.dnsmasq.status", null); if (TextUtils.isEmpty(mEthernetStatus) || mEthernetStatus == null) { mDhcpSwitch.setChecked(false); } else if ("on".equals(mEthernetStatus)) { mDhcpSwitch.setChecked(true); } else if ("off".equals(mEthernetStatus)) { mDhcpSwitch.setChecked(false); } else { mDhcpSwitch.setChecked(false); } } @Override protected void onClick() { }}如果不需要对preferce进行点击操作,那么直接在xml文件里添加android:selectable="false"是最方便的操作了。
下面的是ethernet_preference_header_switch_item.xml文件
<?xml version="1.0" encoding="utf-8"?><!-- Layout of a ethernet item in PreferenceActivity. --><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="48dp" android:background="?android:attr/activatedBackgroundIndicator" android:gravity="center_vertical" android:paddingEnd="?android:attr/scrollbarSize"> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="2dip" android:layout_marginEnd="6dip" android:layout_marginTop="6dip" android:layout_marginBottom="6dip" android:layout_weight="1"> <TextView android:id="@+android:id/ethernet_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" android:textAppearance="?android:attr/textAppearanceMedium" android:ellipsize="marquee" android:fadingEdge="horizontal" /> </RelativeLayout> <Switch android:id="@+id/ethernet_switchWidget" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:padding="8dip" android:focusable="false" android:clickable="true" /></LinearLayout>
应用延伸:
我在使用的过程中发现EthernetSettings类中无法对switchPreferce里面的switch控件进行操作,一直报空指针。明明有对switchPreferce进行初始化啊,为什么不能对switch进行操作呢?这个问题困扰了我整整一上午,最后锁定到了onBindView(View view)方法中,通过别人的解释终于明白了。下面贴上别人分析的流程,^_^~
>public class PowerInformationPreference extends Preference { private TextView firstName; public PowerInformationPreference(Context context, AttributeSet attr, int defStyle) { super(context, attr, defStyle); setLayoutResource(R.layout.layout_power_information); } @Override protected void onBindView(View view) {(1) // TODO Auto-generated method stub super.onBindView(view); firstName = (TextView)view.findViewById(R.id.firstname);(2) } }
上面是我们很常见到的自定义preference的基本形式,我们在onBindView()函数中操作自定义视图,比如上面的代码中我们需要动态的改变firstName这一TextView的text值。
如下,我们提供一个setText()接口,通过这个接口我们可以动态改变TextView的text值。
public void setText(String text){(3) firstName.setText(text);//NullPointerException(4) }如果我们真的是这样写这个接口的话,会发现一定会出现NullPointerException,调试发现这里的firstName为空。而回到onBindView()中调试分析又会发现,firstName = (TextView)view.find...实际上是会运行的,也就是有这个firstName对象存在。那么唯一的解释就是setText()的调用在onBindView()运行之前,因此我们的疑惑来了,如何确保onBindView()在setText()调用之前运行呢?
事实上,到这里我们如果继续这样分析的话,就会钻入误区,跳出来,从逻辑层面上想想,我们会发现,(1),(2),(4)是对UI的操作,(3)是对数据的操作。这里,(1)(2)和(4)分开了,也就是说,(1)(2)运行的时候不能保证(4)运行;(4)运行的时候不能保证(1)(2)运行,这对UI操作是非常危险的事,很容易就产生了控制正异常。
不仅仅是这里,我们查看Adapter.java的源码,查看有getView(), onCreateView(), onBindView()等类的相关源码,都会发现,凡是涉及到UI操作的一定是放在一起的。
<pre code_snippet_id="159439" snippet_file_name="blog_20140116_3_2925943" name="code" class="java"><span style="font-size:14px;">public class PowerInformationPreference extends Preference { private TextView firstName; private String text; public PowerInformationPreference(Context context, AttributeSet attr, int defStyle) { super(context, attr, defStyle); setLayoutResource(R.layout.layout_power_information); } @Override protected void onBindView(View view) {(1) // TODO Auto-generated method stub super.onBindView(view); firstName = (TextView)view.findViewById(R.id.firstname);(2) firstName.setText(text); } </span></pre> <br> public void setText(String text){(3) this.text = text;<br> notifyChanged();<br> }<br> }<br> <p></p> <pre></pre> 这里还需要强调的一点是一定不要忘记notifyChanged()这个函数通知UI更新数据,否则我们会发现通过这个接口设置的数据并没有改变原来的值。这个函数如同View中的invalidate(),虽然数据更新了,但是显示在视图中的数字图像依然没变,因此需要通知UI更新显示。<br> <p></p>
总结下吧,switchpreferce 和普通的View 加载layout的方式不同。
switchpreferce :setWidgetLayoutResource(R.layout.ethernet_preference_header_switch_item); 我们无法获取VIew,所以对view的操作,只能通过onBindView(View view)来操作。
View: View view = LayoutInflater.from(context).inflate(R.layout.ipedittext, this); 普通view,我们可以在构造函数中直接得到view,从而在构造函数中直接可以初始化控件。
- 解除SwitchPreference与preference 的绑定事件及单独调用Switch控件
- [Android L or M ]解除SwitchPreference与Preference的绑定事件
- android4.1上去除SwitchPreference中Switch控件与Preference的绑定响应
- jQuery中live绑定的事件与解除绑定
- jQuery中live绑定的事件与解除绑定
- jquery事件绑定与解除
- (107)绑定及解除绑定事件
- 自定义SwitchPreference实现其中Switch控件的enabled属性的解绑
- jquery解除hover事件的绑定方式
- jQuery 如何解除绑定的事件
- javascript绑定、解除事件
- javascript--解除事件绑定
- android Switch控件一直处于聚焦状态,将屏蔽Preference的点击事件(处理方式)_xp
- 绑定服务并调用服务的方法,解除绑定
- SwitchPreference遇到的坑及解决
- delegate绑定与解除绑定
- jQuery解除事件绑定 unbind
- SwitchPreference响应点击事件
- 第四回:产品创新性思维方法论
- ios数据库升级,自动添加字段
- PAT1036跟奥巴马一起编程(15)
- ie下input输入框readonly失效,光标仍可聚焦
- PHPUnit 测试 thinkphp
- 解除SwitchPreference与preference 的绑定事件及单独调用Switch控件
- IOS 接入的应用服务端开发资料搜集
- 关于ExpandableListView用法的一个简单小例子
- Android开发环境配置以及工具
- Java中的包装类
- 安卓入门学习(一)Hello,world!
- Android屏幕适配全攻略(最权威的官方适配指导)
- 《iOS Human Interface Guidelines》——Activity Indicator
- Android 开源项目分类汇总-mark一下,或许会用得着