TopFragment.java 11.6 KB
package com.dinhcv.lifelogpedometer.activity;

import android.app.DatePickerDialog;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.DatePicker;
import android.widget.ImageView;
import android.widget.TextView;

import com.dinhcv.lifelogpedometer.R;
import com.dinhcv.lifelogpedometer.feature.Database;
import com.dinhcv.lifelogpedometer.model.StepModel;
import com.dinhcv.lifelogpedometer.utils.Const;
import com.dinhcv.lifelogpedometer.utils.DayAxisValueFormatter;
import com.dinhcv.lifelogpedometer.utils.Utils;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;

import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;

import org.eazegraph.lib.charts.PieChart;
import org.eazegraph.lib.models.PieModel;

import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import static com.github.mikephil.charting.utils.ColorTemplate.rgb;


public class TopFragment extends FragmentBase implements SettingFragmentPresenter {

    private TextView stepsView;
    private TextView tvDistance;
    private TextView tvStepRemain;
    private TextView tvStepRateDone;
    private boolean showSteps = true;
    private PieModel sliceGoal, sliceCurrent;
    private PieChart pg;
    private TextView tvDate;
    private ImageView ivBack;
    private ImageView ivNext;
    private ImageView ivPlay;


    private Date mAnaDate;
    private Calendar mCalendar;

    private int mAnaDay;
    private int mAnaMonth;
    private int mAnaYear;

    private int todayOffset, total_start, since_boot;
    public final static NumberFormat formatter = NumberFormat.getInstance(Locale.getDefault());
    public static int STEP_SIZE = 75;
    private StepModel mStepModel;
    private TextView tvSmallRemain;

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
                             final Bundle savedInstanceState) {
        final View v = inflater.inflate(com.dinhcv.lifelogpedometer.R.layout.fragment_top, null);
        stepsView = (TextView) v.findViewById(R.id.steps);
        tvDistance = (TextView) v.findViewById(R.id.tv_distance);
        tvStepRemain = (TextView) v.findViewById(R.id.tv_stepRemain);
        tvStepRateDone = (TextView) v.findViewById(R.id.tv_stepRateDone);
        tvSmallRemain = (TextView) v.findViewById(R.id.tv_smallRemain);
        tvDate = (TextView) v.findViewById(R.id.tv_date);
        ivBack = (ImageView) v.findViewById(R.id.iv_back);
        ivNext = (ImageView) v.findViewById(R.id.iv_next);
        ivPlay = (ImageView) v.findViewById(R.id.iv_play);

        mChart = (BarChart) v.findViewById(R.id.chart);
        pg = (PieChart) v.findViewById(R.id.graph);

        // slice for the steps taken today
        sliceCurrent = new PieModel("", 0, Color.parseColor("#6FE7F7"));
        pg.addPieSlice(sliceCurrent);

        // slice for the "missing" steps until reaching the goal
        sliceGoal = new PieModel("", Const.STEP_GOAL, Color.parseColor("#B7B8B6"));
        pg.addPieSlice(sliceGoal);
        pg.setDrawValueInPie(false);
        pg.setUsePieRotation(false);
        pg.startAnimation();
        pg.setAutoCenterInSlice(false);

        mCalendar = Calendar.getInstance();
        mCalendar.setTime(new Date());
        mAnaDate = mCalendar.getTime();
        mAnaYear = mCalendar.get(Calendar.YEAR);
        mAnaMonth = mCalendar.get(Calendar.MONTH);
        mAnaDay = mCalendar.get(Calendar.DAY_OF_MONTH);

        tvDate.setText(Utils.dateToStringFormatDayMonthYearJp(mAnaDate));

        handleEvent();

        return v;
    }

    private void stepsDistanceChanged() {
        updatePie();
        updateBars();
    }


    @Override
    public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
        inflater.inflate(R.menu.main, menu);
    }


    private void updatePie() {
        // todayOffset might still be Integer.MIN_VALUE on first start
        int steps_today = Math.max(todayOffset + since_boot, 0);
        sliceCurrent.setValue(steps_today);
        if (Const.STEP_GOAL - steps_today > 0) {
            // goal not reached yet
            if (pg.getData().size() == 1) {
                pg.addPieSlice(sliceGoal);
            }
            sliceGoal.setValue(Const.STEP_GOAL - steps_today);
        } else {
            // goal reached
            pg.clearChart();
            pg.addPieSlice(sliceCurrent);
        }
        pg.update();

        stepsView.setText(formatter.format(steps_today));
        int remain = Const.STEP_GOAL - steps_today;
        tvStepRemain.setText(String.valueOf(remain));
        tvStepRateDone.setText(getResources().getString(R.string.percent_unit, Utils.convert2String2Decimal(steps_today *100/ Const.STEP_GOAL)));
        tvSmallRemain.setText(getResources().getString(R.string.pie_text_content3a, remain));

        double distance_today = steps_today * STEP_SIZE;
        distance_today /= 100000;
        tvDistance.setText(Utils.convert2String2Decimal(distance_today));

    }

    /**
     * Updates the bar graph to show the steps/distance of the last week. Should
     * be called when switching from step count to distance.
     */
    private void updateBars() {

        dateList = new ArrayList<>();
        List<Integer> stepList = new ArrayList<>();

        Database db = Database.getInstance(getActivity());
        List<Pair<Long, Integer>> last = db.getLastEntries(8, mAnaDate);
        db.close();
        for (int i = last.size() - 1; i > 0; i--) {
            Pair<Long, Integer> current = last.get(i);
            int step = current.second;
            Date date = new Date(current.first);
            stepList.add(step);
            dateList.add(String.valueOf(Utils.getDay(date)));
        }

        mStep = stepList.toArray(new Integer[0]);
        mParties = dateList.toArray(new String[0]);

        initGraph();
    }

    private BarChart mChart;

    private List<String> dateList;
    private String[] mParties;
    private Integer[] mStep;

    private void initGraph(){

        mChart.setDrawBarShadow(false);
        mChart.setDrawValueAboveBar(true);

        // if more than 60 entries are displayed in the chart, no values will be
        // drawn
        mChart.setMaxVisibleValueCount(60);

        mChart.getDescription().setEnabled(false);
        // scaling can now only be done on x- and y-axis separately
        mChart.setPinchZoom(false);

        mChart.setDrawGridBackground(false);
        // mChart.setDrawYLabels(false);

        DayAxisValueFormatter xValueFormatter = new DayAxisValueFormatter(dateList);

        XAxis xAxis = mChart.getXAxis();
        xAxis.setLabelRotationAngle(0);
        xAxis.setPosition(XAxis.XAxisPosition.TOP);
        xAxis.setDrawGridLines(true);
        xAxis.setLabelCount(10);
        xAxis.setTextColor(Color.WHITE);
        xAxis.setValueFormatter(xValueFormatter);


        YAxis leftAxis = mChart.getAxisLeft();
        leftAxis.setDrawLabels(false);
        leftAxis.setDrawGridLines(false);
        leftAxis.setAxisMinimum(0f);
        leftAxis.setAxisMaximum(10000f);
        leftAxis.setDrawZeroLine(false);

        leftAxis.setEnabled(false);
        mChart.setDrawValueAboveBar(false);
        mChart.getAxisRight().setEnabled(false);

        // set auto scale min max
        mChart.setAutoScaleMinMaxEnabled(true);
        mChart.notifyDataSetChanged();

        // Set enimate y
        mChart.animateY(2000);

        setData();

        mChart.getLegend().setEnabled(false);
    }


    private void setData() {

        ArrayList<String> xVals = new ArrayList<>();
        for (int i = 0; i < mStep.length; i++) {
            xVals.add(mParties[i % mStep.length]);
        }

        ArrayList<BarEntry> yVals1 = new ArrayList<>();
        for (int i = 0; i < mStep.length; i++) {
            float val = (float) (mStep[i]*1);
            yVals1.add(new BarEntry(i, val));
        }

        BarDataSet set1;

        if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) {
            set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0);
            set1.setValues(yVals1);
            mChart.getData().notifyDataChanged();
            mChart.notifyDataSetChanged();
        } else {
            ArrayList<Integer> colors = new ArrayList<>();


            int[] MATERIAL_COLORS = {rgb("#40CDEF")};

            for (int c : MATERIAL_COLORS)
                colors.add(c);

            set1 = new BarDataSet(yVals1, null);

            set1.setColors(colors);

            ArrayList<IBarDataSet> dataSets = new ArrayList<>();
            dataSets.add(set1);

            BarData data = new BarData(dataSets);
            data.setValueTextSize(10f);

            mChart.setData(data);
        }
    }



    private void handleEvent(){
        tvDate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                handleAnaDatePicker();
            }
        });

        ivBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mCalendar = Calendar.getInstance();
                mCalendar.setTime(mAnaDate);
                mCalendar.add(Calendar.DAY_OF_MONTH, -1);
                Date date = mCalendar.getTime();
                tvDate.setText(Utils.dateToStringFormatDayMonthYearJp(date));
                mAnaDate = date;
            }
        });

        ivNext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mCalendar = Calendar.getInstance();
                mCalendar.setTime(mAnaDate);
                mCalendar.add(Calendar.DAY_OF_MONTH, +1);
                Date date = mCalendar.getTime();
                tvDate.setText(Utils.dateToStringFormatDayMonthYearJp(date));
                mAnaDate = date;
            }
        });


    }


    /**
     * Show date picker dialog
     */
    private void handleAnaDatePicker() {

        new DatePickerDialog(getActivity(), new DatePickerDialog.OnDateSetListener() {
            @Override
            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {

                mCalendar = Calendar.getInstance();
                mCalendar.set(year, monthOfYear, dayOfMonth);
                mAnaYear = year;
                mAnaMonth = monthOfYear;
                mAnaDay = dayOfMonth;
                Date date = mCalendar.getTime();
                tvDate.setText(Utils.dateToStringFormatDayMonthYearJp(date));
                mAnaDate = date;
            }
        }, mAnaYear, mAnaMonth, mAnaDay).show();

    }



    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

    }

    private void initData() {

    }

    @Override
    public void onSaveData() {

    }

    @Override
    public void onInvalidate(boolean isInit) {
        initData();
    }

    @Override
    public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
        super.onViewStateRestored(savedInstanceState);

        initData();
    }

}