哼着小曲 听着田馥甄的《小幸运》。--遇见你是注定,也许当时忙着微笑和哭泣,离别之后只会流泪和哭泣。当我没听见你声音,我又重新做回我自己,她会有多幸运。哎....抒发下半年以来的压抑和哭泣。让我看着你们手中的亮光好吧!---在Android原生系统中所看到的设置界面,使用的是与Preference相关的视图完成的。使用Preference相关的视图能较好地进行了文字的分类和排版。而原生的preference基本很难满足我们的需求开发,所以自定义preference必不可缺。而为了使应用更轻量更碎片化,preferencefragment也是需要的。
本篇文章防谷歌样式的自定义preference结合preferencefragment的体现来讲解:主要通过key_values健值对ListViw里面自动添加和移除。
class Settings extends PreferenceFragment
private SwitchPreference mApSwitch;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
mContext = getActivity().getBaseContext();
mApSwitch = (SwitchPreference) buildPreference(R.string.title_network_hot_post, 0, true, isWifiApEnable());
buildPreference(R.string.input_ap_password, mWifiAP.getPreSharedKey(), false, false); //自动添加
}
//ListViw里面移除
List<Preference> list =getPrefeerences();
Iterator<Preference> iterator = list.iterator();
while(iterator.hashNext()){
Preference preference =iterator.next();
if(preference.getId() == R.string.input_ap_password){
iterator.remove();
}
}
2.第二部就是自定义Preference的文件啦!
、、、
public abstract class Preference {
private View rootView;
protected int id;
protected int iconId = 0;
private PreferenceFragment fragment;
protected String title;
private String key;
protected String summary;
protected TextView titleView, summaryView;
protected OnPreferenceClickListener mOnClickListener;
protected OnPreferenceChangeListener mOnChangeListener;
protected boolean isShowIcon = true;
protected boolean isEnable = true;
protected Context mContext;
public abstract View buildView(Context context, View view);
public Preference(Context context, String title) {
this(context, title, null);
}
public Preference(Context context, String title, String summary) {
this.title = title;
this.summary = summary;
mContext = context;
}
public int getId() {
return id;
}
public void setKey(String key) {
this.key = key;
}
public String getKey(){
return key;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
if (titleView != null) {
titleView.setText(title);
}
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
if (rootView != null){
summaryView = (TextView) rootView.findViewById(R.id.summary);
if (summaryView != null) {
summaryView.setText(summary);
summaryView.setVisibility(TextUtils.isEmpty(summary) ? View.GONE
: View.VISIBLE);
}
}
}
public PreferenceFragment getFragment() {
return fragment;
}
public void setFragment(PreferenceFragment fragment) {
this.fragment = fragment;
}
public void initView(View view) {
Log.i(TAG , "preference init View title = " + title + " summary = " + summary);
rootView = view;
titleView = (TextView) view.findViewById(R.id.title);
summaryView = (TextView) view.findViewById(R.id.summary);
if (!TextUtils.isEmpty(title)) {
titleView.setText(title);
titleView.setVisibility(View.VISIBLE);
} else {
titleView.setVisibility(View.GONE);
}
Log.i(TAG , "preference init summaryView = " + summaryView + " summary = " + summary);
if (!TextUtils.isEmpty(summary)) {
summaryView.setText(summary);
summaryView.setVisibility(View.VISIBLE);
} else {
summaryView.setVisibility(View.GONE);
}
titleView.setTextColor(isEnable ? mContext.getResources().getColor(android.R.color.white)
: mContext.getResources().getColor(R.color.setting_line_color));
}
public void setEnabled(boolean enabled) {
isEnable = enabled;
if (titleView != null) {
titleView.setTextColor(enabled ? mContext.getResources().getColor(
android.R.color.white) : mContext.getResources().getColor(
R.color.setting_line_color));
}
}
public boolean getEnable() {
return isEnable;
}
/**
* Interface definition for a callback to be invoked when the value of this
* {@link Preference} has been changed by the user and is about to be set
* and/or persisted. This gives the client a chance to prevent setting
* and/or persisting the value.
*/
public interface OnPreferenceChangeListener {
/**
* Called when a Preference has been changed by the user. This is called
* before the state of the Preference is about to be updated and before
* the state is persisted.
*
* @param preference
* The changed Preference.
* @param newValue
* The new value of the Preference.
* @return True to update the state of the Preference with the new
* value.
*/
boolean onPreferenceChange(Preference preference, Object newValue);
}
/**
* Interface definition for a callback to be invoked when a
* {@link Preference} is clicked.
*/
public interface OnPreferenceClickListener {
/**
* Called when a Preference has been clicked.
*
* @param preference
* The Preference that was clicked.
* @return True if the click was handled.
*/
void onPreferenceClick(Preference preference);
}
/**
* Sets the callback to be invoked when this Preference is clicked.
*
* @param onPreferenceClickListener
* The callback to be invoked.
*/
public void setOnPreferenceClickListener(
OnPreferenceClickListener onPreferenceClickListener) {
mOnClickListener = onPreferenceClickListener;
}
/**
* Sets the callback to be invoked when this Preference is changed by the
* user (but before the internal state has been updated).
*
* @param onPreferenceChangeListener
* The callback to be invoked.
*/
public void setOnPreferenceChangeListener(
OnPreferenceChangeListener onPreferenceChangeListener) {
mOnChangeListener = onPreferenceChangeListener;
}
public void performClick() {
if (isEnable){
if (mOnClickListener != null) {
mOnClickListener.onPreferenceClick(this);
}
}
}
/**
* Call this method after the user changes the preference, but before the
* internal state is set. This allows the client to ignore the user value.
*
* @param newValue
* The new value of this Preference.
* @return True if the user value should be set as the preference value (and
* persisted).
*/
protected void callChangeListener(Object newValue) {
if (mOnChangeListener != null) {
mOnChangeListener.onPreferenceChange(this, newValue);
}
}
}
、、、
该类主要介绍 titleView, summaryView两个TextView的添加、以及设置 OnPreferenceClickListener,setOnPreferenceChangeListener两个点击事件接口回调,内容比较简单就
不过多的介绍了。
3.第三部让我们来看看PreferenceFragment的精妙的写法吧!该类继承了Preference类里面的两个监听回调的接口OnPreferenceClickListener, OnPreferenceChangeListener
、、、
public abstract class PreferenceFragment extends SubFragment implements OnPreferenceClickListener,
OnPreferenceChangeListener{
private static final String TAG = PreferenceFragment.class.getSimpleName();
private ListView mListView;
private List<Preference> mList = new ArrayList<Preference>();
private PreferenceAdapter adapter;
/** 默认选中项 */
private int mCurSelected = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mList.clear();
}
public void setSelect(int select){
if (select >= 0 && select < mList.size() && mCurSelected != select) {
mCurSelected = select;
if (adapter != null) {
adapter.setSelect(mCurSelected);
}
Log.i(TAG, "setSelect mCurSelected = " + mCurSelected);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = getCustomView();
if (view == null) {
view = inflater.inflate(R.layout.fragment_preference, null);
}
initView(view);
return view;
}
/**
* 如果子类想重写此fragment的布局 请重写此方法
* @return 自定的PreferenceView 此View 必须包含一个ListView 并且ID为 item_list
* 如果为null 将使用默认的Fragment
*/
protected View getCustomView() {
return null;
}
private void initView(View view) {
adapter = new PreferenceAdapter(mList, getActivity());
adapter.setSelect(mCurSelected);
mListView = (ListView) view.findViewById(R.id.item_list);
if (mListView == null) {
throw new IllegalArgumentException("自定义的PreferenceFragment 必须包含一个ListView 并且id为 item_list");
}
mListView.setAdapter(adapter);
mListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> viewGroup, View view, int position,
long id) {
adapter.getItem(position).performClick();
}
});
}
public void setVerticalScrollBarEnabled(boolean show){
mListView.setVerticalScrollBarEnabled(show);
}
public void addPreference(Preference preference){ //在ListView里面添加Preference对象
if (!mList.contains(preference)){
mList.add(preference);
preference.setFragment(this);
if (mListView != null){
adapter.notifyDataSetChanged();
}
}
}
public void removePreference(Preference preference){
if (mList.contains(preference)){
mList.remove(preference);
if (mListView != null){
adapter.notifyDataSetChanged();
}
}
}
public Preference findPrederenceById(int id){
for (Preference preference : mList){
if (preference.getId() == id){
return preference;
}
}
return null;
}
public void refresh(){
if (mListView != null){
adapter.notifyDataSetChanged();
}
}
public void removeAllPreference(){
mList.clear();
if (mListView != null){
adapter.notifyDataSetChanged();
}
}
public int getPreferenceCount(){
return mList.size();
}
public List<Preference> getPreferences(){
return mList;
}
/**
* 向上移动一项
*/
public void onMoveToUp() {
Log.i(TAG, "onMoveToUp ");
setSelect(mCurSelected - 1);
}
/**
* 向下移动一项
*/
public void onMoveToDown() {
Log.i(TAG, "onMoveToDown ");
setSelect(mCurSelected + 1);
}
/**
* ok键被按下
*/
public void onCenterSure() {
Log.i(TAG, "onCenterSure mCurSelected = " + mCurSelected);
adapter.getItem(mCurSelected).performClick();
}
/**
*
* @param titleId 标题
* @param summayId 简要信息
* @param isCheckPreference 是否是带check功能的Preference
* @param isChecked 初始值
* @return
*/
protected Preference buildPreference(int titleId, int summayId, boolean isSwitchPreference, boolean isChecked) {
return buildPreference(titleId, summayId != 0 ? getString(summayId) : null, isSwitchPreference, isChecked);
}
/**
*
* @param titleId 标题
* @param summay 简要信息
* @param isCheckPreference 是否是带check功能的Preference
* @param isChecked 初始值
* @return
*/
protected Preference buildPreference(int titleId, String summay, boolean isSwitchPreference, boolean isChecked) {
Preference preference = null;
if (isSwitchPreference){
preference = new SwitchPreference(getActivity(), getString(titleId));
((SwitchPreference)preference).setChecked(isChecked, false);
preference.setOnPreferenceChangeListener(this);
}else{
preference = new BasePreference(getActivity(), getString(titleId));
}
if (summay != null){
preference.setSummary(summay);
}
preference.setOnPreferenceClickListener(this);
preference.setId(titleId);
addPreference(preference);
return preference;
}
}
、、、
在该类中我们终于看见我们所关注的 buildPreference方法啦!是不是有点小激动。方法里面我们会看见addPreference(preference)的添加Preference对象的方法。再仔细
观察下你会发现该类已经写好Preference对象的添加、移除、刷新、全部移除等方法。同时Preference对象我们存储到 List<Preference> 集合中。
4.其中fragment_preference布局如下就是一个ListView 哈哈:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ListView
android:id="@+id/item_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@drawable/menu_drivder"
android:dividerHeight="3dp"
android:listSelector="@android:color/transparent"
>
</ListView>
</RelativeLayout>
5.那我们Preference对象里面的数据布局怎么布局呢?俗话说“家有小妙招”请接下看小编的详解:自定义一个SwitchPreference类继承Preference类 代码如下:
、
public class SwitchPreference extends Preference{
protected static final String TAG = "Settings.SwitchPreference";
private CheckSwitchButton switchButton;
private boolean isChecked;
public SwitchPreference(Context context, String title) {
this(context, title, null);
}
public SwitchPreference(Context context, String title, String summary) {
super(context, title, summary);
}
public View buildView(Context context, View view) {
if (view == null){
view = View.inflate(context, R.layout.preference_switch_view, null);
view.setTag(this);
}else{
Object tag = view.getTag();
if (tag == null || !(tag instanceof SwitchPreference)){
view = View.inflate(context, R.layout.preference_switch_view, null);
view.setTag(this);
}
}
initView(view, context);
return view;
}
public void initView(View view, Context context) {
super.initView(view);
Log.i(TAG , " initView isChecked = " + isChecked + " title = " + title);
switchButton = (CheckSwitchButton) view.findViewById(R.id.switch_button);
switchButton.setOnSwitchChangeListener(new OnSwitchChangeListener() {
@Override
public void onCheckedChanged(CheckSwitchButton switchButton,
boolean isChecked, boolean isTracking) {
SwitchPreference.this.isChecked = isChecked;
if (isTracking){
callChangeListener(isChecked);
}
}
});
switchButton.setChecked(isChecked);
}
/**
*
* @param isChecked
* @param isByUser ?????????????
*/
public void setChecked(boolean isChecked, boolean isByUser){
if (switchButton != null){
if (isByUser){
switchButton.setCheckedByUser(isChecked);
}else{
switchButton.setChecked(isChecked);
}
}
this.isChecked = isChecked;
}
public boolean isChecked(){
if (switchButton != null){
return switchButton.isChecked();
}
return isChecked;
}
@Override
public void performClick() {
super.performClick();
}
}
、
在该子类 SwitchPreference中 加载布局layout.preference_switch_view就是Preference对象数据传递UI显示。用户可以根据自身需求改变布局,继承Preference类即可完成所需的功能,简单方便吧!
6.展示下layout.preference_switch_view 的布局:
、
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:paddingRight="15dp"
>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textColor="@android:color/white"
android:textSize="@dimen/title_text_size" />
<TextView
android:id="@+id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/title"
android:gravity="center_vertical"
android:textColor="@color/setting_line_color"
android:textSize="16sp"
android:visibility="gone" />
</RelativeLayout>
<com.ssdf.sdk.widgets.CheckSwitchButton
android:id="@+id/switch_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_alignParentRight="true"
/>
、
OK ,《小幸运》单曲循环十几遍了 我也改收尾了!--本文终于写完了,翻看源码,查阅资料,画图花了两天时间,最后回顾一下,我们是如何通过key_values健值对ListViw里面自动添加和移除自定义Preference对象数据呢?下篇也是伴着小曲写着文章,忙着追逐天空中的流星吧!
网友评论