开发动机
移动端的配置离不开SharePreference,如果我们直接操作SharePreference就需要重复写界面来管理,每次都要做重复的工作,很是麻烦。
想到了谷歌的原生PreferenceActivity,去看了PreferenceScreen相关的源码想把PreferenceScreen抽离出来作为单独的一个组件,可以随意的加入到任何界面中。几经努力后失败了,失败原因如下:
- PreferenceManager 只能被反射调用
- GenericInflater.Parent 包外不能访问
- 不支持网络同步
基于如上原因,所以决定自己写一个Preference的组件来解除重复劳动
开发思路
我们需要的Preference组件需要支持如下功能:
- 保存读取SharePreference
- 可以和服务器进行同步
- 每项Preference支持自定义的view 显示
- 简单易用
- 高度的灵活和定制
根据以上功能,最终决定整个组件是一个ListView,每一个item 包含了SharePreference的key,提供自定义view,点击响应,文字显示,和网络同步接口。给ListView的adapter设置items源,则完成绑定。
代码组成
- SettingItem(item基类)
- SettingItemText(继承自SettingItem,只有文字显示的item,点击跳转)
- SettingItemSwitch(继承自SettingItem,包含switch开关的item,点击switch切换开关)
- SettingItemScreen(绑定listview和items源,便于管理)
- SettingKeyValue(管理所有KEY,可以静态访问Value)
SettingItem
public abstract class SettingItem {
protected String mPrefKey;
protected String mTitle;
protected String mSummary;
public String getKey() {
return mPrefKey;
}
public void setKey(String key) {
mPrefKey = key;
}
public String getTitle() {
return mTitle;
}
public void setTitle(String title) {
mTitle = title;
}
public String getSummary() {
return mSummary;
}
public void setSummary(String text) {
mSummary = text;
}
public abstract View createView();
public boolean getState() {
return getBooleanValue();
}
public void setState(boolean isOn) {
setBooleanValue(isOn);
}
public abstract void bindView(View view);
//将服务器拉下来
public abstract void refreshData();
//将SP上传服务器
public abstract void syncNetwork();
//SP是否有值,如果没有值,需要从服务器拉取
public boolean isSPUnknow() {
return SettingKeyValue.isSPUnknow(mPrefKey);
}
public boolean getBooleanValue() {
return SettingKeyValue.getBooleanValue(mPrefKey);
}
public void setBooleanValue(boolean value) {
SettingKeyValue.setBooleanValue(mPrefKey, value);
}
}
SettingItemText
public class SettingItemText extends SettingItem {
private View.OnClickListener mOnClickListener;
public SettingItemText(String title, String summary, View.OnClickListener onClickListener) {
this.mTitle = title;
this.mSummary = summary;
mOnClickListener = onClickListener;
}
//用于ListView 创建View
@Override
public View createView() {
View view = LayoutInflater.from(HomeApplication.getInstance()).inflate(
R.layout.item_text_setting,
null,
false);
ViewHolder viewHolder = new ViewHolder();
viewHolder.title = (TextView) view.findViewById(R.id.title);
viewHolder.summary = (TextView) view.findViewById(R.id.summary);
view.setTag(viewHolder);
return view;
}
@Override
public boolean getState() {
return false;
}
@Override
public void setState(boolean isOn) {
}
@Override
public void bindView(View view) {
view.setClickable(true);
ViewHolder viewHolder = (ViewHolder) view.getTag();
viewHolder.title.setText(mTitle);
viewHolder.summary.setText(mSummary);
if (mOnClickListener != null) {
view.setOnClickListener(mOnClickListener);
}
}
@Override
public void refreshData() {
}
@Override
public void syncNetwork() {
}
public static class ViewHolder {
TextView title;
TextView summary;
}
}
SettingItemSwitch
这里的SwitchView是一个自定义通用的view,所以需要稍微适配一下
public abstract class SettingItemSwitch extends SettingItem {
private SwitchView.OnSwitchStatusChangeListener mOnSwitchClickListener;
public SettingItemSwitch(String title, String summary, String key) {
mTitle = title;
mSummary = summary;
mPrefKey = key;
mOnSwitchClickListener = new SwitchView.OnSwitchStatusChangeListener() {
@Override
public void onSwitchStatusChange(SwitchView switchView, int switchStatus) {
setState(switchStatus == SwitchView.SWITCH_ON);
}
};
}
@Override
public View createView() {
View view = LayoutInflater.from(HomeApplication.getInstance()).inflate(
R.layout.item_switch_setting,
null,
false);
ViewHolder viewHolder = new ViewHolder();
viewHolder.title = (TextView) view.findViewById(R.id.title);
viewHolder.summary = (TextView) view.findViewById(R.id.summary);
viewHolder.switchView = (SwitchView) view.findViewById(R.id.switch_view);
view.setTag(viewHolder);
return view;
}
@Override
public void bindView(View view) {
ViewHolder viewHolder = (ViewHolder) view.getTag();
viewHolder.title.setText(mTitle);
if (TextUtils.isEmpty(mSummary)) {
viewHolder.summary.setVisibility(View.GONE);
} else {
viewHolder.summary.setText(mSummary);
}
viewHolder.switchView.initSwitchStatus(getState());
viewHolder.switchView.setOnSwitchStatusChangeListener(mOnSwitchClickListener);
}
@Override
public abstract void refreshData();
public abstract void syncNetwork();
public static class ViewHolder {
TextView title;
TextView summary;
SwitchView switchView;
}
}
SettingItemScreen
public class SettingItemScreen{
private ListView mListView;
private List<SettingItem> mItemList;
private BaseAdapter mListAdapter;
private Map<String,Integer> mTypeMap;
public SettingItemScreen(@NotNull ListView listView, @NotNull List<SettingItem> itemList){
mItemList = itemList;
createType(mItemList);
mListView = listView;
mListAdapter = new BaseAdapter() {
@Override
public int getCount() {
return mItemList.size();
}
@Override
public int getItemViewType(int position) {
String type = getItem(position).getClass().toString();
return mTypeMap.get(type);
}
@Override
public int getViewTypeCount() {
return mTypeMap.size();
}
@Override
public Object getItem(int position) {
return mItemList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
SettingItem settingItem = mItemList.get(position);
if(view == null){
view = settingItem.createView();
}
settingItem.bindView(view);
return view;
}
};
mListView.setAdapter(mListAdapter);
}
private void createType(List<SettingItem> mItemList){
int i = 0;
mTypeMap = new HashMap<>();
for(SettingItem settingItem : mItemList){
String type = settingItem.getClass().toString();
if(mTypeMap.get(type) == null){
mTypeMap.put(type,i++);
}
}
}
public void refresh(){
int size = mItemList.size();
for(int i = 0 ; i < size ; i++ ){
SettingItem settingItem = mItemList.get(i);
settingItem.refreshData();
}
}
public void sync(){
int size = mItemList.size();
for(int i = 0 ; i < size ; i++ ){
SettingItem settingItem = mItemList.get(i);
settingItem.syncNetwork();
}
}
public void refreshView(){
mListAdapter.notifyDataSetChanged();
}
}
Demo
代码请移步Demo
效果图
本文介绍了一种自定义偏好设置组件的设计与实现方法,该组件能够简化SharePreference的管理和使用,支持与服务器同步、自定义视图显示等功能。
1166

被折叠的 条评论
为什么被折叠?



