`
quanminchaoren
  • 浏览: 926828 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Android preference与ActivityGroup UI更新

阅读更多

之前发过一篇有关于自定义preference 在ActivityGroup 的包容下出现UI不能更新的问题,当时还以为是Android 的一个BUG 现在想想真可笑 。其实是自己对机制的理解不够深刻,看来以后要多看看源码才行。

本篇讲述内容大致为如何自定义preference 开始到与ActivityGroup 互用下UI更新的解决方法。

首先从扩展preference开始:

类文件必须继承自Preference并实现构造函数,这里我一般实现两个构造函数分别如下(类名为:test):

 

     public  test(Context context) {
        
this (context,  null );
        
//  TODO Auto-generated constructor stub
    }

    
public  test(Context context, AttributeSet attrs) {
        super(context, attrs);
        
//  TODO Auto-generated constructor stub
    }

 

这里第二个构造函数第二个参数为可以使用attrs 为我们自定义的preference 添加扩展的注册属性,比如我们如果希望为扩展的preference 添加一个数组引用,就可使用如下代码:

 

int  resouceId  =  attrs.getAttributeResourceValue( null " Entries " 0 );
        
if  (resouceId  >   0 ) {
            mEntries 
=  getContext().getResources().getTextArray(resouceId);
        }

 

 

这里的mEntries 是头部声明的一个数组,我们可以在xml文件通过 Entries=数组索引得到一个数组。在这里不深入为大家示范了。

我们扩展preference 有时想让其UI更丰富更好看,这里我们可以通过引用一个layout 文件为其指定UI,可以通过实现如下两个回调函数:

 

@Override
    
protected  View onCreateView(ViewGroup parent) {
        
//  TODO Auto-generated method stub
         return  LayoutInflater.from(getContext()).inflate(
                R.layout.preference_screen, parent, 
false );
    }

 

此回调函数与onBindView 一一对应,并优先执行于onBindView ,当创建完后将得到的VIEW返回出去给onBindView处理,如下代码:

 

@Override
    
protected   void  onBindView(View view) {
        
//  TODO Auto-generated method stub
        super.onBindView(view);
        canlendar 
=  Calendar.getInstance();
        layout 
=  (RelativeLayout) view.findViewById(R.id.area);
        title 
=  (TextView) view.findViewById(R.id.title);
        summary 
=  (TextView) view.findViewById(R.id.summary);
        layout.setOnClickListener(
this );
        title.setText(getTitle());
        summary.setText(getPersistedString(canlendar.
get (Calendar.YEAR)  +   " / "
                
+  (canlendar. get (Calendar.MONTH)  +   1 +   " / "
                
+  canlendar. get (Calendar.DAY_OF_MONTH)));

    }

 

 

Tip:onBindView 不是必须的,可以将onBindView 里的处理代码在onCreateView 回调函数一并完成然后返回给onBindView ,具体怎么写看自己的代码风格吧。我个人比较喜欢这种写法,比较明了。

下面我们来了解一下我扩展preference 比较常用到的几个方法:

  • compareTo (Preference another)
    与另外一个preference比较,如果相等则返回0,不相等则返回小于0的数字。
  • getContext ()
    获取上下文
  • getEditor ()
    得到一个SharePrefence 的Editor 对象
  • getIntent ()
    获取Intetn
  • getKey ()
    获取当前我们在XML为其注册的KEY
  • getLayoutResource ()
    得到当前layout 的来源
  • getOnPreferenceChangeListener ()
    值改变的监听事件
  • getPreferenceManager ()
    获得一个preference管理
  • getSharedPreferences ()
    通过获得管理获取当前的sharePreferences
  • getSummary ()
    获得当前我们在XML为其注册的备注为summary 的值。Tip:在OnBindView 或者onCreateView 找到VIEW的时候如果存在summary 的View 对象必须为其设置summary
  • getTitle ()
    如上,不过这里是获取标题
  • callChangeListener (Object newValue)
    如果你希望你扩展的Preference 可以支持当数值改变时候可以调用OnPreferenceChangeListener此监听方法,则必须调用此方法,查看该方法源码为:
      protected  boolean callChangeListener(Object newValue) {
            
    return  mOnChangeListener  ==   null   ?   true  : mOnChangeListener.onPreferenceChange( this , newValue);
        }
        

     

    源码简单不做过多介绍,只是实现一个接口。
  • getPersistedBoolean (boolean defaultReturnValue)
    获得一个保存后的布尔值,查看一下源码:
      protected  boolean getPersistedBoolean(boolean defaultReturnValue) {
            
    if  ( ! shouldPersist()) {
                
    return  defaultReturnValue;
            }
            
            
    return  mPreferenceManager.getSharedPreferences().getBoolean(mKey, defaultReturnValue);
        }

     

    如果你有接触过sharePreference 相信一眼就能看出这里它为我们做了什么。
  • getPersistedFloat (float defaultReturnValue)
    如上,这里获取一个Float 的值
  • getPersistedInt (int defaultReturnValue)
    如上,获取一个int 的值
  • getPersistedLong (long defaultReturnValue)
    如上,获取一个Long 型数值
  • getPersistedString (String defaultReturnValue)
    如上,获取一个String 数值
  • persistBoolean (boolean value)
    将一个布尔值保存在sharepreference中,查看一下源码:
      protected  boolean persistBoolean(boolean value) {
            
    if  (shouldPersist()) {
                
    if  (value  ==  getPersistedBoolean( ! value)) {
                    
    //  It's already there, so the same as persisting
                     return   true ;
                }
                
                SharedPreferences.Editor editor 
    =  mPreferenceManager.getEditor();
                editor.putBoolean(mKey, value);
                tryCommit(editor);
                
    return   true ;
            }
            
    return   false ;
        }

     

    都是sharePreference 的知识,这里不做过多介绍。其他的跟上面的都 一样,略过。

通过如上的一些设置,一个基本的扩展preference 就己经完成,下面来讲讲如果在ActivityGroup 里面让扩展的preference可以更新UI。之前 农民伯伯 探讨过,他建议我使用onContentChanged()方法,可以使UI更新 ,试了一下发现有些许问题,不过非常感谢农民伯伯。这个方法是全局刷新,则全部UI都刷新一次,但是这样不是很合理,我想了一下,那既然此方法可以更新 UI那么一定可以行得通,我查看一下源码,下面把源码贴出来:

 

 @Override
    
public   void  onContentChanged() {
        super.onContentChanged();
        postBindPreferences();
    }

    
/* *
     * Posts a message to bind the preferences to the list view.
     * <p>
     * Binding late is preferred as any custom preference types created in
     * {@link #onCreate(Bundle)} are able to have their views recycled.
     
*/
    
private   void  postBindPreferences() {
        
if  (mHandler.hasMessages(MSG_BIND_PREFERENCES))  return ;
        mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
    }
    
    
private   void  bindPreferences() {
        final PreferenceScreen preferenceScreen 
=  getPreferenceScreen();
        
if  (preferenceScreen  !=   null ) {
            preferenceScreen.bind(getListView());
        }
    }

 

 

 

   
    
private   static  final  int  MSG_BIND_PREFERENCES  =   0 ;
    
private  Handler mHandler  =   new  Handler() {
        @Override
        
public   void  handleMessage(Message msg) {
            
switch  (msg.what) {
                
                
case  MSG_BIND_PREFERENCES:
                    bindPreferences();
                    
break ;
            }
        }
    };

 


原来,这里它是另开一条线程来更新UI,然后当值发生变化时为其发送消息,在消息队列里面处理UI,只不过它这里继承了 listActivity 更新了一整个listView ,那么我们就将它提取出来,只更新我们想要的UI则可。OK,思路出来了,下面将我扩展的一个preference 的源码提供出来:

 

package com.yaomei.preference;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Message;
import android.preference.Preference;
import android.preference.PreferenceGroup;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

import com.yaomei.
set .R;

public   class  PreferenceScreenExt extends PreferenceGroup implements
        OnItemClickListener, DialogInterface.OnDismissListener {

    
private  Dialog dialog;
    
private  TextView title, summary;
    
private  RelativeLayout area;
    
private  ListView listView;
    List
< Preference >  list;

    
private  List < HashMap < String, String >>  listStr;
    
private  CharSequence[] mEntries;
    
private  String mValue;

    
private  SimpleAdapter simple;
    
private   static  final  int  MSG_BIND_PREFERENCES  =   0 ;
    
private  Handler mHandler  =   new  Handler() {
        @Override
        
public   void  handleMessage(Message msg) {
            
switch  (msg.what) {

            
case  MSG_BIND_PREFERENCES:
                setValue(mValue);
                
break ;
            }
        }
    };

    
public  PreferenceScreenExt(Context context, AttributeSet attrs) {
        
this (context, attrs, android.R.attr.preferenceScreenStyle);
        
//  TODO Auto-generated constructor stub
    }

    
public  PreferenceScreenExt(Context context, AttributeSet attrs,  int  defStyle) {
        super(context, attrs, android.R.attr.preferenceScreenStyle);
        
//  TODO Auto-generated constructor stub
         int  resouceId  =  attrs.getAttributeResourceValue( null " Entries " 0 );
        
if  (resouceId  >   0 ) {
            mEntries 
=  getContext().getResources().getTextArray(resouceId);
        }
    }

    @Override
    
protected   void  onBindView(View view) {
        
//  TODO Auto-generated method stub
        area  =  (RelativeLayout) view.findViewById(R.id.area);
        title 
=  (TextView) view.findViewById(R.id.title);
        summary 
=  (TextView) view.findViewById(R.id.summary);
        title.setText(getTitle());
        summary.setText(getPersistedString(getSummary().toString()));
        area.setOnClickListener(
new  OnClickListener() {
            @Override
            
public   void  onClick(View v) {
                
//  TODO Auto-generated method stub
                showDialog();
            }
        });

    }

    @Override
    
protected  View onCreateView(ViewGroup parent) {
        
//  TODO Auto-generated method stu
        View view  =  LayoutInflater.from(getContext()).inflate(
                R.layout.preference_screen, parent, 
false );
        
return  view;
    }

    
public   void  bindView(ListView listview) {
        
int  length  =  mEntries.length;
        
int  i  =   0 ;
        listStr 
=   new  ArrayList < HashMap < String, String >> ();
        
for  (i  =   0 ; i  <  length; i ++ ) {
            HashMap
< String, String >  map  =   new  HashMap < String, String > ();
            map.put(
" keyname " , mEntries[i].toString());
            listStr.add(map);
        }
        simple 
=   new  SimpleAdapter(getContext(), listStr, R.layout.dialog_view,
                
new  String[] {  " keyname "  },  new   int [] { R.id.text });
        listview.setAdapter(simple);
        listview.setOnItemClickListener(
this );
    }

    
public   void  showDialog() {
        listView 
=   new  ListView(getContext());
        bindView(listView);
        dialog 
=   new  Dialog(getContext(), android.R.style.Theme_NoTitleBar);
        dialog.setContentView(listView);
        dialog.setOnDismissListener(
this );
        dialog.show();
    }

    @Override
    
public   void  onItemClick(AdapterView <?>  parent, View view,  int  position,
            
long  id) {
        
//  TODO Auto-generated method stub
        mValue  =  listStr. get (position). get ( " keyname " ).toString();
        persistString(mValue);
        callChangeListener(mValue);
        dialog.dismiss();
    }

    @Override
    
public   void  onDismiss(DialogInterface dialog) {
        
//  TODO Auto-generated method stub
    }

    
private  OnPreferenceChangeListener temp;

    
public   interface  OnPreferenceChangeListener {
        
public  boolean onPreferenceChange(Preference preference, Object newValue);
    }

    
public   void  setOnPreferenceChangeListener(
            OnPreferenceChangeListener preference) {
        
this .temp  =  preference;
    }

    
public   void  setValue(String value) {
        summary.setText(value);
    }

    
public  boolean callChangeListener(Object newValue) {
        
return  temp  ==   null   ?   true  : temp.onPreferenceChange( this , newValue);
    }

    
public   void  postBindPreferences() {
        
if  (mHandler.hasMessages(MSG_BIND_PREFERENCES))
            
return ;
        mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
    }

}

 

 

然后在preferenceActivity 界面在回调函数:onPreferenceChange调用postBindPreferences即可更新。

Tip:这里的onPreferenceChange  调用postBindPreferences 不是必须的,你同样可以在内部里面实现,通过执行某一操作发送消息也可。

分享到:
评论
1 楼 George_ghc 2012-01-04  
不错,可以学习一下!

相关推荐

    android Preference自定义样式

    在Android开发中,Preference是用来构建设置界面的一种组件,它提供了用户可以交互的选项,如开关、选择列表等。为了提供个性化的用户体验,开发者有时需要对Preference进行自定义样式。本篇将深入探讨如何在Android...

    Android中Preference的使用以及监听事件分析

    Preference类是Android框架的一部分,它简化了UI元素的创建和管理,使得开发者可以方便地实现设置界面。本文将深入探讨Preference的使用方法及其事件监听机制。 一、Preference的种类 Preference家族包括多种类型...

    Android应用Preference

    Preference组件是android的SharePreferences的衍生品,Preference组件的状态值是默认永久的保存在/data/data/包名/shared_prefs ...Preference组件其实就是Android常见UI组件与SharePreferences的组合封装实现。

    Android Preference解读

    在与Preference相关的应用中,我们需要在这里声明PreferenceActivity或PreferenceFragment。例如,我们可以声明一个继承自`PreferenceActivity`的类,这样我们就可以在该类中添加和管理Preferences: ```xml ...

    Android中preference的使用实例代码

    在Android开发中,Preference是用来构建用户设置界面的关键组件。它允许开发者轻松地创建具有开关、选择器、输入框等交互元素的配置界面。本篇文章将深入探讨如何在Android项目中使用Preference,通过实例代码来展示...

    Android 自定义preference组件

    上篇博文代码实现了Android自带的preference组件,本文将通过实例讲解自定义preference组件。 主要通过以下几步来实现: 1.定义需要的layout布局res-&gt;layout-&gt;xml文件; 2.通过继承Preference类,来实现自定义...

    Android Preference Framework源码

    Android的Preference Framework是Android系统中用于构建设置界面的一个强大工具,它允许开发者通过XML定义各种偏好设置元素,如开关按钮、选择列表等,然后在应用中轻松地将这些设置集成到用户界面。这个框架大大...

    android Preference的Demo

    本Demo旨在展示如何在Android应用中使用Preference来实现用户设置的保存与读取。 首先,我们需要在布局文件(通常是res/xml/preference.xml)中定义Preference视图。这个XML文件包含了各种Preference类型的节点,如...

    Android Preference组件使用

    Android提供preference这个键值对的方式来处理这种情况,自动保存这些数据,并立时生效,同时Android提供一种类似的layout的方式来进行Preference的布局。 Preference组件有ListPreference,EditTextPreference,...

    android preference framework demo

    此DEMO内含基本的android preference framework的简单介绍,包括CheckboxPreference, RingtonePreference, EditTextPreference以及ListPreference。主要探究了一下android 怎么通过使用preference从而达到对用户定制...

    Android代码-Material Design风格Preference UI

    Based on support-preference from Android Support Library, adding a lot of exciting features. Sample How to use add dependencies // replace with version above implementation 'moe.shizuku.preference...

    安卓Android源码——Preference_Demo.rar

    - 在XML布局文件中,使用自定义的类名替换`&lt;Preference&gt;`标签,确保类名与`android:name`属性匹配。 4. **联动效果**:在设置界面中,某些Preference的可见性或可编辑性可能依赖于其他Preference的状态。可以使用`...

    android Preference Demo

    Preference是Android SDK提供的一种轻量级UI组件,主要用于实现应用的设置界面。它允许开发者创建具有交互性的设置项,比如开关按钮、单选框、复选框、文本输入等。通过继承Preference类并自定义布局,开发者可以...

    Android应用源码之Preference_Demo-IT计算机-毕业设计.zip

    在Android应用开发中,Preference是实现用户界面(UI)中设置和首选项管理的重要组件。本项目"Android应用源码之Preference_Demo"是一个毕业设计示例,它深入展示了如何在Android应用程序中创建和管理用户偏好设置。...

    Android Preference

    在Android开发中,Preference是用户界面(UI)的一个重要组件,用于创建设置界面或选项菜单。Preference Activity是Android系统提供的一种特殊类型的Activity,专门用来显示和处理用户偏好设置。在这个"Android_...

    Android程序 preference应用

    在Android开发中,Preference是系统提供的一种用户界面组件,用于创建设置界面,让用户可以方便地进行各种偏好设置。本篇文章将深入探讨`Android程序 preference应用`,并结合一个注册案例来详细阐述如何在应用程序...

    Android学习笔记 Preference的使用

    - 标签提到“源码”,可能文章会深入分析`Preference`类的内部工作原理,包括如何读写SharedPreferences,以及UI更新的机制等。 8. **工具使用**: - 可能会介绍一些辅助工具,如Android Studio的预览功能,帮助...

    android-support-v7-preference.jar

    android-support-v7-preference.jar

    AndroidPreferenceDemo

    2. **PreferenceActivity的实现**:在Java源代码中,可能会有一个类继承自`PreferenceActivity`,在这个类中,开发者会通过`addPreferencesFromResource()`方法加载上面提到的XML布局文件,将UI与设置项关联起来。...

    Android PreferenceActivity 使用练习

    它允许开发者通过XML定义UI元素,如开关、单选按钮、复选框等,并在活动中动态加载这些元素,简化了构建用户设置界面的过程。本篇文章将深入探讨PreferenceActivity的使用方法以及相关知识点。 首先,我们了解`...

Global site tag (gtag.js) - Google Analytics