package com.classic.car.ui.fragment; import android.annotation.SuppressLint; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; import com.classic.car.R; import com.classic.car.app.CarApplication; import com.classic.car.consts.Consts; import com.classic.car.db.dao.ConsumerDao; import com.classic.car.entity.ChartType; import com.classic.car.entity.ConsumerDetail; import com.classic.car.ui.activity.ChartActivity; import com.classic.car.ui.activity.MainActivity; import com.classic.car.ui.base.AppBaseFragment; import com.classic.car.ui.chart.BarChartDisplayImpl; import com.classic.car.ui.chart.IChartDisplay; import com.classic.car.ui.chart.LineChartDisplayImpl; import com.classic.car.ui.chart.PieChartDisplayImpl; import com.classic.car.ui.widget.RelativePopupWindow; import com.classic.car.ui.widget.YearsPopup; import com.classic.car.utils.DataUtil; import com.classic.car.utils.DateUtil; import com.classic.car.utils.RxUtil; import com.classic.car.utils.ToastUtil; import com.classic.car.utils.Util; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.charts.Chart; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.jakewharton.rxbinding.view.RxView; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.concurrent.TimeUnit; import javax.inject.Inject; import butterknife.BindView; import rx.Observable; import rx.Subscription; import rx.functions.Action1; import rx.functions.Func1; /** * 应用名称: CarAssistant * 包 名 称: com.classic.car.ui.fragment * * 文件描述:图表统计页面 * 创 建 人:续写经典 * 创建时间:16/5/29 下午2:21 */ @SuppressWarnings("unchecked") public class ChartFragment extends AppBaseFragment { private static final int ANIMATE_DURATION = 400; private static final String EMPTY_VALUE = "0"; @BindView(R.id.chart_fuel_linechart) LineChart mFuelLineChart; @BindView(R.id.chart_consumer_barchart) BarChart mConsumerBarChart; @BindView(R.id.chart_percentage_piechart) PieChart mPercentagePieChart; @BindView(R.id.chart_min_money) TextView mMinMoney; @BindView(R.id.chart_max_money) TextView mMaxMoney; @BindView(R.id.chart_min_oilmess) TextView mMinOilMess; @BindView(R.id.chart_max_oilmess) TextView mMaxOilMess; @BindView(R.id.chart_consumer_save) TextView mSaveConsumer; @BindView(R.id.chart_fuel_save) TextView mSaveFuel; @BindView(R.id.chart_percentage_save) TextView mSavePercentage; @BindView(R.id.chart_percentage_detail) LinearLayout mPercentageDetail; @Inject ConsumerDao mConsumerDao; private LayoutInflater mLayoutInflater; private IChartDisplay mBarChartDisplay; private IChartDisplay mPieChartDisplay; private IChartDisplay mLineChartDisplay; private long mStartTime; private long mEndTime; private int mCurrentYear; private YearsPopup mYearsPopup; public static ChartFragment newInstance() { return new ChartFragment(); } @Override public int getLayoutResId() { return R.layout.fragment_chart; } @Override public void initView(View parentView, Bundle savedInstanceState) { ((CarApplication) mActivity.getApplicationContext()).getAppComponent().inject(this); super.initView(parentView, savedInstanceState); setHasOptionsMenu(true); mCurrentYear = Calendar.getInstance().get(Calendar.YEAR); initChart(); loadData(mCurrentYear); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.chart_menu, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.action_date) { showYears(); return true; } return super.onOptionsItemSelected(item); } @Override public void onFragmentShow() { super.onFragmentShow(); setHasOptionsMenu(true); mActivity.setTitle(getString(R.string.consumer_title, mCurrentYear)); } @Override public void onFragmentHide() { super.onFragmentHide(); setHasOptionsMenu(false); mActivity.setTitle(R.string.app_name); } private void showYears() { if (null == mYearsPopup) { mYearsPopup = new YearsPopup.Builder() .context(mActivity) .years(Consts.YEARS) .fitInScreen(true) .horizontalPosition(RelativePopupWindow.HorizontalPosition.RIGHT) .verticalPosition(RelativePopupWindow.VerticalPosition.BELOW) .listener(new YearsPopup.Listener() { @Override public void onYearSelected(int year) { // ToastUtil.showToast(mAppContext, String.valueOf(year)); if (mCurrentYear != year) { mCurrentYear = year; loadData(mCurrentYear); } } }) .build(); } if (mYearsPopup.isShowing()) { mYearsPopup.dismiss(); } else { mYearsPopup.show(((MainActivity)mActivity).getToolbar()); } } @SuppressWarnings("unchecked") private void initChart() { mBarChartDisplay = new BarChartDisplayImpl(); mPieChartDisplay = new PieChartDisplayImpl(); mLineChartDisplay = new LineChartDisplayImpl(); mBarChartDisplay.init(mConsumerBarChart, true); mPieChartDisplay.init(mPercentagePieChart, true); mLineChartDisplay.init(mFuelLineChart, true); addSubscription(processAccidentalClick(mSaveConsumer, mConsumerBarChart)); addSubscription(processAccidentalClick(mSaveFuel, mFuelLineChart)); addSubscription(processAccidentalClick(mSavePercentage, mPercentagePieChart)); mConsumerBarChart.setOnChartValueSelectedListener(new ChartValueSelectedListener(ChartType.BAR_CHART)); mPercentagePieChart.setOnChartValueSelectedListener(new ChartValueSelectedListener(ChartType.PIE_CHART)); mFuelLineChart.setOnChartValueSelectedListener(new ChartValueSelectedListener(ChartType.LINE_CHART)); } private final class ChartValueSelectedListener implements OnChartValueSelectedListener { private @ChartType int type; public ChartValueSelectedListener(@ChartType int type) { this.type = type; } @Override public void onValueSelected(Entry entry, Highlight highlight) { ChartActivity.start(mActivity, type, mStartTime, mEndTime); } @Override public void onNothingSelected() { } } private void loadData(int year) { mActivity.setTitle(getString(R.string.consumer_title, mCurrentYear)); mStartTime = DateUtil.getTime(year); mEndTime = DateUtil.getTime(year + 1) - 1; addSubscription(loadConsumerDetail(mStartTime, mEndTime)); addSubscription(loadFuelConsumption(mStartTime, mEndTime)); } /** 加载消费信息 */ private Subscription loadConsumerDetail(long startTime, long endTime) { return mConsumerDao.queryBetween(startTime, endTime) .compose(RxUtil.<List<ConsumerDetail>>applySchedulers(RxUtil.IO_ON_UI_TRANSFORMER)) .flatMap(new Func1<List<ConsumerDetail>, Observable<Object>>() { @Override public Observable<Object> call(List<ConsumerDetail> consumerDetails) { if (DataUtil.isEmpty(consumerDetails)) { return Observable.just(null); } return Observable.just(mBarChartDisplay.convert(consumerDetails), mPieChartDisplay.convert(consumerDetails)); } }) .subscribe(new Action1<Object>() { @Override public void call(Object data) { if (null == data) { mConsumerBarChart.clear(); mPercentagePieChart.clear(); refreshConsumerView(null); refreshPercentageView(null); return; } if (data instanceof BarData) { mBarChartDisplay.animationDisplay(mConsumerBarChart, data, ANIMATE_DURATION); refreshConsumerView((BarData)data); } else if (data instanceof PieChartDisplayImpl.PieChartData) { mPieChartDisplay.animationDisplay(mPercentagePieChart, data, ANIMATE_DURATION); refreshPercentageView((PieChartDisplayImpl.PieChartData)data); } } }); } /** 加载油耗信息 */ private Subscription loadFuelConsumption(long startTime, long endTime) { return mConsumerDao.query(Consts.TYPE_FUEL, startTime, endTime, false, true) .compose(RxUtil.<List<ConsumerDetail>>applySchedulers(RxUtil.IO_ON_UI_TRANSFORMER)) .map(new Func1<List<ConsumerDetail>, LineChartDisplayImpl.LineChartData>() { @Override public LineChartDisplayImpl.LineChartData call(List<ConsumerDetail> list) { return (LineChartDisplayImpl.LineChartData)mLineChartDisplay.convert(list); } }) .subscribe(new Action1<LineChartDisplayImpl.LineChartData>() { @Override public void call(LineChartDisplayImpl.LineChartData lineChartData) { mLineChartDisplay.animationDisplay(mFuelLineChart, lineChartData, ANIMATE_DURATION); refreshOilMessView(lineChartData); } }, RxUtil.ERROR_ACTION); } private Subscription processAccidentalClick(TextView view, final Chart chart){ return RxView.clicks(view) .throttleFirst(Consts.SHIELD_TIME, TimeUnit.SECONDS) .subscribe(new Action1<Void>() { @Override public void call(Void aVoid) { ToastUtil.showToast(mAppContext, chart.saveToGallery(Util.createImageName(), IChartDisplay.QUALITY) ? R.string.chart_save_success : R.string.chart_save_fail); } }); } private void refreshConsumerView(BarData barData) { mSaveConsumer.setVisibility(null != barData ? View.VISIBLE : View.GONE); } /** * 添加消费百分比详细信息 */ private void refreshPercentageView(PieChartDisplayImpl.PieChartData pieChartData) { if (mPercentageDetail.getChildCount() > 0) { mPercentageDetail.removeAllViews(); } mSavePercentage.setVisibility(null != pieChartData && null != pieChartData.pieData ? View.VISIBLE : View.GONE); if (null == pieChartData || null == pieChartData.groupMoney) { return; } if(null == mLayoutInflater){ mLayoutInflater = LayoutInflater.from(mActivity); } List<Float> values = new ArrayList<>(); for(int i =0; i < pieChartData.groupMoney.size();i++){ values.add(pieChartData.groupMoney.valueAt(i)); } // 顺序 // Collections.sort(values); // 倒序 Collections.sort(values, new Comparator<Float>() { @Override public int compare(Float o1, Float o2) { return o2.compareTo(o1); } }); int rows = 1; for (Float item : values) { int key = pieChartData.groupMoney.keyAt(pieChartData.groupMoney.indexOfValue(item)); @SuppressLint("InflateParams") View itemView = mLayoutInflater.inflate(R.layout.item_table, null); ((TextView) itemView.findViewById(R.id.item_table_lable)).setText(Consts.TYPE_MENUS[key]); ((TextView) itemView.findViewById(R.id.item_table_total_money)).setText( Util.formatRMB(item)); ((TextView) itemView.findViewById(R.id.item_table_percentage)).setText( Util.formatPercentage(item, pieChartData.totalMoney)); itemView.findViewById(R.id.item_table_bottom_divider) .setVisibility(rows == values.size() ? View.VISIBLE : View.GONE); mPercentageDetail.addView(itemView, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); rows++; } @SuppressLint("InflateParams") View totalView = mLayoutInflater.inflate(R.layout.item_total_table, null); ((TextView) totalView.findViewById(R.id.item_total_table_value)).setText( Util.formatRMB(pieChartData.totalMoney)); mPercentageDetail.addView(totalView, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); } private void refreshOilMessView(LineChartDisplayImpl.LineChartData lineChartData) { if (null != lineChartData && null != lineChartData.minFuelConsumption) { mMinMoney.setText(Util.formatRMB(lineChartData.minFuelConsumption.getMoney())); mMinOilMess.setText(Util.formatOilMess(lineChartData.minFuelConsumption.getOilMass())); } else { mMinMoney.setText(EMPTY_VALUE); mMinOilMess.setText(EMPTY_VALUE); } if (null != lineChartData && null != lineChartData.maxFuelConsumption) { mMaxMoney.setText(Util.formatRMB(lineChartData.maxFuelConsumption.getMoney())); mMaxOilMess.setText(Util.formatOilMess(lineChartData.maxFuelConsumption.getOilMass())); } else { mMaxMoney.setText(EMPTY_VALUE); mMaxOilMess.setText(EMPTY_VALUE); } mSaveFuel.setVisibility(null != lineChartData && null != lineChartData.lineData ? View.VISIBLE : View.GONE); } }