PreferencFragment解析:http://blog.csdn.net/lmj623565791/article/details/37970961/
billing_cycle.xml
<?xml version="1.0" encoding="UTF-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/data_usage_summary_title">
<Preference
android:key="billing_cycle"
android:title="@string/billing_cycle"/>
<Preference
android:key="data_warning"
android:title="@string/data_warning"/>
<SwitchPreference
android:key="set_data_limit"
android:title="@string/set_data_limit"/>
<Preference
android:key="data_limit"
android:title="@string/data_limit"/>
</PreferenceScreen>
data_usage_bytes_editor.xml
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android:"http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:gravity="center"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:layout_width="match_parent"
android:layot_height="wrap_content" xmlns:android="http://schemas.android.com/apk/res/android">
<EditText
android:id="@+id/bytes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:minWidth="48dip"
android:layout_gravity="center_vertical"
android:focusable="true"
android:focusableInTouchMode="true"
android:inputType="numberDecimal"/>
<Spinner
android:id="@+id/size_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:entries="@array/bytes_picker_sizes"/>
</LinearLayout>
data_usage_cycle_editor.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/data_usage_cycle_editor_subtitle"/>
<NumberPicker
android:id="@+id/cycle_day"
android:layout_width="48dip"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dip"
android:layout_marginEnd="16dip"
android:focusable="true"
android:focusableInTouchMode="true"/>
</LinearLayout>
BillingCycleSettings.java(这里的DataUsageBase是PreferenceFragment的子类)
package com.example.util;
import android.app.AlertDialog;
import android.net.NetworkTemplate;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.os.Bundle;
import android.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.Preference;
import android.support.v14.preference.SwitchPreference;
import android.text.format.Time;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.NumberPicker;
import android.widget.Spinner;
public class BillingCycleSettings extends DataUsageBase implements
Preference.OnPreferenceChangeListener{
private static final String TAG="BillingCycleSettings";
private static final boolean LOGO=true;
private static final String TAG_CONFIRM_LIMIT="confirmLimit";
private static final String TAG_CYCLE_EDITOR="cycleEditor";
private static final String TAG_WARNING_EDITOR="warningEditor";
private static final String KEY_BILLING_CYCLE="billing_cycle";
private static final String KEY_DATA_WARNING="data_warning";
private static final String KEY_SET_DATA_LIMIT="set_data_limit";
private static final String KEY_DATA_LIMIT="data_limit";
private NetworkTemplate mNetworkTemplate;
private Preference mBillingCycle;
private Preference mDataWarning;
private android.preference.SwitchPreference mEnableDataLimit;
private android.preference.Preference mDataLimit;
private DataUsageController mDataUsageController;
@Override
public void onCreate(Bundle icicle){
super.onCreate(icicle);
mDataUsageController=new DataUsageController(getContext());
Bundle args=getArguments();
mNetworkTemplate=args.getParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE);
addPreferencesFromResource(R.xml.billing_cycle);
mBillingCycle=findPreference(KEY_BILLING_CYCLE);
mDataWarning=findPreference(KEY_DATA_WARNING);
mEnableDataLimit=(SwitchPreference)findPreference(KEY_SET_DATA_LIMIT);
mEnableDataLimit.setOnPreferenceChangeListener(this);
mDataLimit=findPreference(KEY_DATA_LIMIT);
}
@Override
public void onResume(){
super.onResume();
updatePrefs();
}
private void updatePrefs(){
NetworkPolicy policy=services.mPolicyEditor.getPolicy(mNetworkTemplate);
mBillingCycle.setSummary(getString(R.string.billing_cycle_summary,policy!=null?
policy.cycleDay:1));
mDataWarning.setSummary(Formatter.formatFileSize(getContext(),policy!=null?
policy.warningBytes:DataUsageController.DEFAULT_WARNING_LEVEL));
if(policy!=null && policy.limitBytes!=LIMIT_DISABLED){
mDataLimit.setSummary(Formatter.formatFileSize(getContext(),policy.limitBytes));
mDataLimit.setEnabled(true);
mEnableDataLimit.setChecked(true);
}else{
mDataLimit.setSummary(null);
mDataLimit.setEnabled(false);
mEnableDataLimit.setChecked(false);
}
}
@Override
public boolean onPreferenceTreeClick(Preference preference){
if(preference==mBillingCycle){
CycleEditorFragment.show(this);
return true;
}else if(preference==mDataWarning){
BytesEditorFragment.show(this,false);
return true;
}else if(preference==mDataLimit){
BytesEditorFragment.show(this,true);
return true;
}
return super.onPreferenceTreeClick(preference);
}
@Override
public boolean onPreferenceChange(Preference preference,Object newValue){
if(mEnableDataLimit==preference){
boolean enabled=(Boolean)newValue;
if(enabled){
ConfirmLimitFragment.show(this);
}else{
setPolicyLimitBytes(LIMIT_DISABLED);
}
return true;
}
return false;
}
@Override
protected int getMetricsCategory(){
return MetricsEvent.BILLING_CYCLE;
}
private void setPolicyLimitBytes(long limitBytes){
services.mPolicyEditor.setPolicyLimitBytes(mNetworkTemplate,limitBytes);
updatePrefs();
}
public static class BytesEditorFragment extends DialogFragment
implements DialogInterface.OnClickListener{
private static final String EXTRA_TEMPLATE="template";
private static final String EXTRA_LIMIT="limit";
private View mView;
public static void show(BillingCycleSettings parent,boolean isLimit){
if(!parent.isAdded())return;
final Bundle args=new Bundle();
args.putParcelable(EXTRA_TEMPLATE, parent.mNetworkTemplate);
args.putBoolean(EXTRA_LIMIT, isLimit);
final BytesEditorFragment dialog=new BytesEditorFragment();
dialog.setArguments(args);
dialog.setTargetFragment(parent, 0);
dialog.show(parent.getFragmentManager(),TAG_WARNING_EDITOR);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState){
final Context context=getActivity();//Fragment里面的getActivity方法可以得到对应的Context
final LayoutInflater DialogInflater=LayoutInflater.from(context);
final boolean isLimit=getArguments().getBoolean(EXTRA_LIMIT);
mView=DialogInflater.inflate(R.id.data_usage_bytes_editor, null,false);
setupPicker((EditText)mView.findViewById(R.id.bytes),
(Spinner)mView.findViewById(R.id.size_spinner));
return new AlertDialog.Builder(context)
.setTitle(isLimit?R.string.data_usage_limit_editor_title
:R.string.data_usage_warning_editor_title)
.setView(mView)
.setPositiveButton(R.string.data_usage_cycle_editor_positive,this)
.create();
}
private void setupPicker(EditText bytesPicker,Spinner type){
final BillingCycleSettings target=(BillingCycleSettings)getTargetFragment();
final NetworkPolicyEditor editor=target.services.mPolicyEditor;
final NetworkTemplate template=getArguments().getParcelable(EXTRA_TEMPLATE);
final boolean isLimit=getArguments().getBoolean(EXTRA_LIMIT);
final long bytes=isLimit? editor.getPolicyLimitBytes(template):
editor.getPolicyWarningBytes(template);
final long limitDisabled=isLimit? LIMIT_DISABLED:WARNING_DISABLED;
if(bytes>1.5f*GB_IN_BYTES){
bytesPicker.setText(formatText(bytes/(float)GB_IN_BYTES));
type.setSelection(1);
}else{
bytesPicker.setText(formatText(bytes/(float)MB_IN_BYTES));
type.setSelection(0);
}
}
private String formatText(float v){
v=Math.round(v*100)/100f;
//Math.round(float a);将参数加上0.5后返回与参数最近的整数
//其实就是去小数部分取整数部分然后再加一
return String.valueOf(v);//取float型变量的String类型
}
@Override
public void onClick(DialogInterface arg0, int arg1) {
// TODO Auto-generated method stub
if(arg1!=DialogInterface.BUTTON_POSITIVE){
return;
}
final BillingCycleSettings target=(BillingCycleSettings)getTargetFragment();
final NetworkPolicyEditor editor=target.services.mPolicyEditor;
final NetworkTemplate template=getArguments().getParcelable(EXTRA_TEMPLATE);
final boolean isLimit=getArguments().getBoolean(EXTRA_LIMIT);
EditText bytesField=(EditText)mView.findViewById(R.id.bytes);
Spinner spinner=(Spinner)mView.findViewById(R.id.size_spinner);
String bytesString=bytesField.getText().toString();
if(bytesString.isEmpty()||bytesString.equals(".")){
bytesString="0";
}
final long bytes=(long)(Float.valueOf(bytesString)
*(spinner.getSelectedItemPosition()==0? MB_IN_BYTES:GB_IN_BYTES));
if(isLimit){
editor.setPolicyLimitBytes(template,bytes);
}else{
editor.setPolicyWarningBytes(template,bytes);
}
target.updatePrefs();
}
}
public static class CycleEditorFragment extends DialogFragment implements
DialogInterface.OnClickListener{
private static final String EXTRA_TEMPLATE="template";
private NumberPicker mCycleDayPicker;
public static void show(BillingCycleSettings parent){
if(!parent.isAdded()) return;
final Bundle args=new Bundle();
args.putParcelable(EXTRA_TEMPLATE, parent.mNetworkTemplate);
final CycleEditorFragment dialog=new CycleEditorFragment();
dialog.setArguments(args);
//这个方法可以保存Fragment的相关信息,同样是在Fragment中通过getArguments获取保存的信息
dialog.setTargetFragment(parent, 0);
//这个方法可以传递parent给dialog对应的类CycleEditorFragment,我们可以在CycleEditorFragment中通过getTargetFragment()获取parent实例
dialog.show(parent.getFragmentManager(), TAG_CYCLE_EDITOR);
//dialog这个Fragment将会加入到parent.getFragmentManager()得到的FragmentManager中
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Context context=getActivity();//Fragment中获取相关活动的方法
final BillingCycleSettings target=(BillingCycleSettings)getTargetFragment();
final NetworkPolicyEditor editor=target.services.mPolicyEditor;
final AlertDialog.Builder builder=new AlertDialog.Builder(context);
final LayoutInflater dialogInflater=LayoutInflater.from(builder.getContext());
final View view=dialogInflater.inflate(R.layout.data_usage_cycle_editor, null,false);
mCycleDayPicker=view.findViewById(R.id.cycle_day);
final NetWorkTemplate template=getArguments().getParcelable(EXTRA_TEMPLATE);
//在这里获取上一个Fragment保存的信息
final int cycleDay=editor.getPolicyCycleDay(template);
final int cycleDayValue=cycleDay;
if(savedInstanceState!=null){
cycleDayValue=savedInstanceState.getInt("cycleDayValue");
}
mCycleDayPicker.setMinValue(1);
mCycleDayPicker.setMaxValue(31);
mCycleDayPicker.setValue(cycleDayValue);
mCycleDayPicker.setWrapSelectorWheel(true);
return builder.setTitle(R.string.data_usage_cycle_editor_title)
.setView(view)
.setPositiveButton(R.string.data_usage_cycle_editor_positive,this)
.create();
}
@Override
public void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
outState.putInt("cycleDayValue", mCycleDayPicker.getValue());
}
@Override
public void onClick(DialogInterface arg0, int arg1) {
final NetworkTemplate template=getArguments().getParcelable(EXTRA_TEMPLATE);
final BillingCycleSettings target=(BillingCycleSettings)getTargetFragment();
//获取之前传递给CycleEditorFragment的BillingCycleSettings类的对象
final NetworPolicyEditor editor=target.services.mPolicyEditor;
mCycleDayPicker.clearFocus();
final int cycleDay=mCycleDayPicker.getValue();
final String cycleTimezone=new Time().timezone;
editor.setPolicyCycleDay(template,cycleDay,cycleTimezone);
target.updatePrefs();
}
}
public static class ConfirmLimitFragment extends DialogFragment implements
DialogInterface.OnClickListener{
private static final String EXTRA_MESSAGE="message";
private static final String EXTRA_LIMIT_BYTES="limitBytes";
public static final float FLOAT=1.2f;
public static void show(BillingCycleSettings parent){
if(!parent.isAdded()) return;
final NetworkPolicy policy=parent.services.mPolicyEditor
.getPolicy(parent.mNetworkTemplate);
if(policy==null)return;
final Resources res=parent.getResources();
final CharSequence message;
final long minLimitBytes=(long)(policy.warningBytes*FLOAT);
final long limitBytes;
message=res.getString(R.string.data_usage_limit_dialog_mobile);
limitBytes=Math.max(5*GB_IN_BYTES, minLimitBytes);
final Bundle args=new Bundle();
args.putCharSequence(EXTRA_MESSAGE, message);
args.putLong(EXTRA_LIMIT_BYTES, limitBytes);
final ConfirmLimitFragment dialog=new ConfirmLimitFragment();
dialog.setArguments(args);
dialog.setTargetFragment(parent, 0);
dialog.show(parent.getFragmentManager(), TAG_CONFIRM_LIMIT);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Context context=getActivity();
final CharSequence message=getArguments().getCharSequence(EXTRA_MESSAGE);
return new AlertDialog.Builder(context)
.setTitle(R.string.data_usage_limit_dialog_title)
.setMessage(message)
.setPositiveButton(android.R.string.ok,this)
.setNegativeButton(android.R.string.cancel,this)
.create();
}
@Override
public void onClick(DialogInterface dialog,int which){
final BillingCycleSettings target=(BillingCycleSettings)getTargetFragment();
if(which!=DialogInterface.BUTTON_POSITIVE){
if(target!=null){
target.updatePrefs();
}
return;
}
final long limitBytes=getArgument().getLong(EXTRA_LIMIT_BYTES);
if(target!=null){
target.setPolicyLimitBytes(limitBytes);
}
}
}
}