Setting模块简介
一、Settings涉及的模块
4.0设置的layout有很大的改变。将设置分为四个部分:
WIRELESS & NETWORKS:SIM卡管理,流量使用情况,飞行模式,VPN,网络共享等
DEVICE :情景模式,显示,存储,电池,应用程序
PERSONAL: 账户与同步,位置服务,安全,语言和输入法,备份和重置
SYSTEM: 日期和时间,定时开关及,辅助功能,开发人员选项,关于手机
二、Settings部分的Fragment
public class Settings extends PreferenceActivity{}。因为从3.0中就引入了Fragment机制,所以在Settings里面就只有这一个Acitivity类,而进入里表中的某项设置后,不是进入到新的Activity,而是在原来的Activity上切换了一个UI界面而已。Fragment是我们在单个Activity上要切换多个UI界面,显示不同内容,对不同的界面不再使用不同的Activity。将这些UI面板模块化以便提供给其它Acitivity使用。当然显示的Fragment也会受到当前 Acitivity生命周期影响,而平常的Fragment页有其自己的生命周期。Setting模块典型的使用这个方法,它定义很多独立的fragment然后将这些fragment纳入到SubSettings.java activity中,这样可将要展示的fragment像调用Activity那样般调用。
三、Setting界面的加载
1.继承关系
Settings.java 是继承PreferenceActivity.java,而referenceActivity.java是继承ListActivity-->Activity
2. 界面加载
1)加载界面对应的Fragment
a. 实现onBuildHeaders()回调用来指定头文件
调用loadHeadersFromResource()方法对界面进行加载
方法实现:
@Override
public void onBuildHeaders(List<Header> headers) {//fengyaing 11
loadHeadersFromResource(R.xml.settings_headers, headers); //加载header文件
updateHeaderList(headers);//显示列表项删选
}
b. header放入listview
@Override
public void setListAdapter(ListAdapter adapter) {
if (adapter == null) {
super.setListAdapter(null);
} else {
super.setListAdapter(new HeaderAdapter(this, getHeaders(), mAuthenticatorHelper));//
}
}
c. Settings.java的内部类HeaderAdapter 类介绍
private static class HeaderAdapter extends ArrayAdapter<Header> {
static final int HEADER_TYPE_CATEGORY = 0;
static final int HEADER_TYPE_NORMAL = 1;
static final int HEADER_TYPE_SWITCH = 2;
@Override
public View getView(int position, View convertView, ViewGroup parent) {//加载header列表
HeaderViewHolder holder;
Header header = getItem(position);
int headerType = getHeaderType(header);
View view = null;
if (convertView == null) {
holder = new HeaderViewHolder();
switch (headerType) {
case HEADER_TYPE_CATEGORY:
view = new TextView(getContext(), null,
android.R.attr.listSeparatorTextViewStyle);
holder.title = (TextView) view;
break;
case HEADER_TYPE_SWITCH:
view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
false);
holder.icon = (ImageView) view.findViewById(R.id.icon);
holder.title = (TextView)
view.findViewById(com.android.internal.R.id.title);
holder.summary = (TextView)
view.findViewById(com.android.internal.R.id.summary);
holder.switch_ = (Switch) view.findViewById(R.id.switchWidget);
break;
case HEADER_TYPE_NORMAL:
view = mInflater.inflate(
R.layout.preference_header_item, parent,
false);
holder.icon = (ImageView) view.findViewById(R.id.icon);
holder.title = (TextView)
view.findViewById(com.android.internal.R.id.title);
holder.summary = (TextView)
view.findViewById(com.android.internal.R.id.summary);
break;
}
view.setTag(holder);
} else {
view = convertView;
holder = (HeaderViewHolder) view.getTag();
}
// All view fields must be updated every time, because the view may be recycled
switch (headerType) {
case HEADER_TYPE_CATEGORY:
holder.title.setText(header.getTitle(getContext().getResources()));
break;
case HEADER_TYPE_SWITCH:
// Would need a different treatment if the main menu had more switches
if (header.id == R.id.wifi_settings) {
mWifiEnabler.setSwitch(holder.switch_);
} else {
mBluetoothEnabler.setSwitch(holder.switch_);
}
// No break, fall through on purpose to update common fields
//$FALL-THROUGH$
case HEADER_TYPE_NORMAL:
if (header.extras != null
&& header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
String accType = header.extras.getString(
ManageAccountsSettings.KEY_ACCOUNT_TYPE);
ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
lp.width = getContext().getResources().getDimensionPixelSize(
R.dimen.header_icon_width);
lp.height = lp.width;
holder.icon.setLayoutParams(lp);
Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
holder.icon.setImageDrawable(icon);
} else {
holder.icon.setImageResource(header.iconRes);
}
holder.title.setText(header.getTitle(getContext().getResources()));
CharSequence summary = header.getSummary(getContext().getResources());
if (!TextUtils.isEmpty(summary)) {
holder.summary.setVisibility(View.VISIBLE);
holder.summary.setText(summary);
} else {
holder.summary.setVisibility(View.GONE);
}
break;
}
// /M: add for sim management feature
if (header.id == R.id.sim_settings) {
handleDisableHolder(holder, view);
} else {
handleEnableHolder(holder, view);
}
return view;
}}
类的开头就定义了三个常量:这个代表Header的三种类型:
HEADER_TYPE_CATEGORY代表一个分类,它不能点击
HEADER_TYPE_NORMAL代表一个常规项
HEADER_TYPE_SWITCH代表一种开头形式的类型
getView()方法中也是根据三种不同的类型,加载不同的view以及数据,这时Seting类的界面就显示出来。
3.点击事件
1) header的点击事件触发
看onHeaderClick()方法
@Override
public void onHeaderClick(Header header, int position) {
boolean revert = false;
if (header.id == R.id.account_add) {
revert = true;
}
super.onHeaderClick(header, position);//调用父类的方法响应点击事件
if (revert && mLastHeader != null) {
highlightHeader((int) mLastHeader.id);
} else {
mLastHeader = header;
}
}
2)将fragment包裹到继承了Settings.java的SubSettings.java中
@Override
public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
int titleRes, int shortTitleRes) {
Intent intent = super.onBuildStartFragmentIntent(fragmentName, args,
titleRes, shortTitleRes);//调用父类的方法将fragment包裹到activity中
System.out.println("onBuildStartFragmentIntent3333:"+intent);
// some fragments want to avoid split actionbar
if (DataUsageSummary.class.getName().equals(fragmentName) ||
PowerUsageSummary.class.getName().equals(fragmentName) ||
AccountSyncSettings.class.getName().equals(fragmentName) ||
UserDictionarySettings.class.getName().equals(fragmentName) ||
Memory.class.getName().equals(fragmentName) ||
ManageApplications.class.getName().equals(fragmentName) ||
WirelessSettings.class.getName().equals(fragmentName) ||
PrivacySettings.class.getName().equals(fragmentName) ||
ManageAccountsSettings.class.getName().equals(fragmentName)) {
intent.putExtra(EXTRA_CLEAR_UI_OPTIONS, true);
}
intent.setClass(this, SubSettings.class);
return intent;
}