me.zchang.onchart.ui.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for me.zchang.onchart.ui.MainActivity.java

Source

/*
 *    Copyright 2015 Zhehua Chang
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package me.zchang.onchart.ui;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.app.ActionBar;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.NavigationView;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.ScaleAnimation;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;

import me.zchang.onchart.BuildConfig;
import me.zchang.onchart.R;
import me.zchang.onchart.config.ConfigManager;
import me.zchang.onchart.config.MainApp;
import me.zchang.onchart.session.BitJwcSession;
import me.zchang.onchart.session.Session;
import me.zchang.onchart.session.events.HomepageFetchOverEvent;
import me.zchang.onchart.session.events.ScheduleFetchOverEvent;
import me.zchang.onchart.session.events.SessionErrorEvent;
import me.zchang.onchart.session.events.SessionStartOverEvent;
import me.zchang.onchart.session.events.SwitchWeekNumEvent;
import me.zchang.onchart.student.Course;
import me.zchang.onchart.student.LabelCourse;
import me.zchang.onchart.ui.adapter.CoursePagerAdapter;
import me.zchang.onchart.ui.adapter.DiffTransformer;
import me.zchang.onchart.ui.adapter.WeekNumListAdapter;
import zchang.me.uilibrary.SideBarLayout;

public class MainActivity extends AppCompatActivity
        implements LoginFragment.LoginListener, ConfigManager.OnConfigChangeListener {

    public final static int REQ_POSITION = 0;
    public final static int REQ_SETTING = 1;

    public final static long MILLISECONDS_IN_A_DAY = 24 * 3600 * 1000;
    public final static long MILLISECONDS_IN_A_WEEK = MILLISECONDS_IN_A_DAY * 7;

    public final static String TAG = "MainActivity";
    private Toolbar mainToolbar;
    private ViewPager mainListPager;
    private TabLayout weekdayTabs;
    private CoursePagerAdapter mainListAdapter;
    private List<LessonListFragment> fragments;
    private ImageView stuffImage;
    private ActionBarDrawerToggle drawerToggle;
    private DrawerLayout drawerLayout;
    private ViewGroup drawerHeader;
    private TextView nameText;
    private ProgressBar refreshProgress;
    private TextView weekNumText;
    private TextView versionText;
    private NavigationView drawerView;
    private AppBarLayout toolbarContainer;
    private FloatingActionButton addButton;
    private SideBarLayout weekSelectLayout;
    private TextView popupWeekText;

    private Session session;
    private ConfigManager configManager;

    private int curWeek;
    private int numOfWeekdays;
    private Calendar today;
    private boolean firstLaunch = true;

    // debug
    private boolean showAllFlag = false; // if show all the courses, for debug.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState != null)
            firstLaunch = false;
        setContentView(R.layout.activity_main);

        configManager = ((MainApp) getApplication()).getConfigManager();
        today = Calendar.getInstance();
        today.setTimeZone(TimeZone.getDefault());

        session = new BitJwcSession();
        mainToolbar = (Toolbar) findViewById(R.id.tb_main);
        setSupportActionBar(mainToolbar);

        curWeek = configManager.getWeek();

        mainListPager = (ViewPager) findViewById(R.id.vp_lessons);
        weekdayTabs = (TabLayout) findViewById(R.id.tl_weekday);
        stuffImage = (ImageView) findViewById(R.id.iv_stuff);
        drawerLayout = (DrawerLayout) findViewById(R.id.dl_drawer);
        drawerView = (NavigationView) findViewById(R.id.nv_drawer);
        toolbarContainer = (AppBarLayout) findViewById(R.id.appb_container);
        addButton = (FloatingActionButton) findViewById(R.id.fab_add_course);
        weekSelectLayout = (SideBarLayout) findViewById(R.id.sbl_week_num);
        popupWeekText = (TextView) findViewById(R.id.tv_popup_week);
        drawerHeader = (ViewGroup) drawerView.getHeaderView(0);
        nameText = (TextView) drawerHeader.findViewById(R.id.tv_stu_name);
        weekNumText = (TextView) drawerHeader.findViewById(R.id.tv_week);
        versionText = (TextView) drawerHeader.findViewById(R.id.tv_version);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && firstLaunch) {
            // FIXME translation doesn't work
            //         toolbarContainer.setTranslationY(- toolbarContainer.getLayoutParams().height);
            //         toolbarContainer.setTranslationY(-100);
            addButton.setScaleX(0.f);
            addButton.setScaleY(0.f);
            addButton.setAlpha(0.f);
        }

        addButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                getSupportFragmentManager().beginTransaction()
                        .replace(android.R.id.content, new AddCourseFragment()).addToBackStack(null).commit();
            }
        });

        if (versionText != null)
            versionText.setText(BuildConfig.VERSION_NAME);

        nameText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                LoginFragment dialog = new LoginFragment();
                dialog.setListener(MainActivity.this);
                dialog.show(getSupportFragmentManager(), TAG);
            }
        });

        if ((getWindow().getAttributes().flags
                & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) {
            ViewGroup.LayoutParams params = stuffImage.getLayoutParams();
            params.height = getStatusBarHeight(this);
            stuffImage.setLayoutParams(params);
        }

        numOfWeekdays = configManager.getNumOfWeekdays();

        setupDrawer();
        setupSideBar();

        // if haven't refreshed week for a week.
        if (Math.abs(configManager.getLastFetchWeekTime() - today.getTimeInMillis()) > MILLISECONDS_IN_A_WEEK) {
            refreshWeek();
        }

        setupFragments();
        setupList();// ATTENTION, order of refresh and setup
        updateWeekNumDisplay();
        fragments.get(mainListPager.getCurrentItem()).setSlideAnimFlag(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    }

    @Override
    protected void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onStop() {
        EventBus.getDefault().unregister(this);
        super.onStop();
    }

    private void setupFragments() {
        fragments = new ArrayList<>();
        for (int i = 0; i < Math.abs(numOfWeekdays); i++) {
            fragments.add(new LessonListFragment());
        }
        mainListAdapter = new CoursePagerAdapter(this, getSupportFragmentManager(), fragments, numOfWeekdays);
        mainListPager.setPageTransformer(false, new DiffTransformer());
        mainListPager.setAdapter(mainListAdapter);
        mainListPager.setClipChildren(false);
        mainListPager.setClipToPadding(false);

        weekdayTabs.setupWithViewPager(mainListPager);
        weekdayTabs.setTabsFromPagerAdapter(mainListAdapter);
    }

    private void setupList() {
        List<Course> courses = null;
        courses = configManager.getSchedule();
        for (LessonListFragment f : fragments)
            f.clearCourse();
        if (courses != null) {
            for (Course course : courses) {
                int index = course.getWeekDay();
                if (showAllFlag) {
                    //  show all the courses, only for test
                    if (index >= 0 && index < fragments.size())
                        fragments.get(index).addCourse(course);
                } else {
                    if (index >= 0 && index < fragments.size() && curWeek >= course.getStartWeek()
                            && curWeek <= course.getEndWeek()) {
                        if (course.getWeekParity() < 0)
                            fragments.get(index).addCourse(course);
                        else if (curWeek % 2 == course.getWeekParity()) // odd or even week num
                            fragments.get(index).addCourse(course);
                    }
                }
            }

            for (LessonListFragment f : fragments) {
                f.updateList();
            }
        }

        // change to page of this day
        int curWeekDay = today.get(Calendar.DAY_OF_WEEK);
        curWeekDay = (curWeekDay + 5) % 7;
        if (curWeekDay < mainListAdapter.getCount()) {
            mainListPager.setCurrentItem(curWeekDay);
        } else {
            mainListPager.setCurrentItem(mainListAdapter.getCount() - 1);
        }
    }

    private void updateWeekNumDisplay() {
        if (weekNumText != null) {
            weekNumText.setText(String.format(getString(R.string.weekday_week), curWeek));
            weekNumText.setLongClickable(true);
            weekNumText.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    refreshWeek();
                    new AlertDialog.Builder(MainActivity.this).setTitle("Warning")
                            .setMessage("This is a testing function, and the stability is not guaranteed.").show();
                    return false;
                }
            });
        }
    }

    private void setupDrawer() {
        drawerView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem menuItem) {
                drawerLayout.closeDrawers();
                int id = menuItem.getItemId();
                if (id == R.id.item_settings) {
                    Intent intent = new Intent(MainActivity.this, SettingsActivity.class);
                    startActivityForResult(intent, REQ_SETTING);
                } else if (id == R.id.item_exams) {
                    Intent intent = new Intent(MainActivity.this, ExamsActivity.class);
                    startActivity(intent);
                } else if (id == R.id.item_share) {
                    Intent intent = new Intent();
                    intent.setAction(Intent.ACTION_SEND);
                    intent.setType("text/plain");
                    intent.putExtra(Intent.EXTRA_TEXT,
                            getString(R.string.text_share) + "\n\r" + getString(R.string.url_download));
                    startActivity(Intent.createChooser(intent, getString(R.string.action_share)));
                } else if (id == R.id.item_donate) {
                    DonateFragment donateFragment = new DonateFragment();
                    donateFragment.show(getSupportFragmentManager(), TAG);
                }
                return false;
            }
        });

        drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close) {
            @Override
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
                invalidateOptionsMenu();
            }

            @Override
            public void onDrawerClosed(View drawerView) {
                super.onDrawerClosed(drawerView);
                invalidateOptionsMenu();
            }
        };
        drawerToggle.setDrawerIndicatorEnabled(true);
        drawerLayout.setDrawerListener(drawerToggle);
        drawerToggle.syncState();
        updateDrawer();
    }

    private void setupSideBar() {
        View header = getLayoutInflater().inflate(R.layout.header_week_num, weekSelectLayout, false);
        weekSelectLayout.setHeader(header);
        RecyclerView weekNumList = (RecyclerView) header.findViewById(R.id.rv_week_num_options);
        RecyclerView.Adapter adapter = new WeekNumListAdapter(MainActivity.this);
        weekNumList.setAdapter(adapter);
        weekNumList.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
    }

    public void refreshWeek() {
        if (refreshProgress != null)
            refreshProgress.setVisibility(View.VISIBLE);
        session.fetchHomePage();
    }

    @Override
    protected void onResume() {
        super.onResume();
        configManager.registerListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        configManager.unRegisterListener(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);

        refreshProgress = (ProgressBar) menu.findItem(R.id.item_refresh).getActionView()
                .findViewById(R.id.pb_refresh);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        if (drawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        drawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        drawerToggle.onConfigurationChanged(newConfig);
    }

    @Override
    public void onLoginInputFinish(String usrNum, String psw) {
        if (refreshProgress != null)
            refreshProgress.setVisibility(View.VISIBLE);

        if (session.isStarted())
            session = new BitJwcSession();

        session.setStuNum(usrNum);
        session.setPsw(psw);
        session.start();
    }

    public static int getStatusBarHeight(Context context) {
        int result = 0;
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

    private void updateDrawer() {
        String stuName = configManager.getName();
        if (stuName != null && !stuName.equals(getString(R.string.null_stu_name))) {
            nameText.setText(stuName);
            nameText.setClickable(false);
            drawerLayout.closeDrawers();
        } else {
            nameText.setText(getString(R.string.title_login));
            nameText.setClickable(true);
        }
    }

    @TargetApi(21)
    @Override
    public void onEnterAnimationComplete() {
        super.onEnterAnimationComplete();
        //      toolbarContainer.animate()
        //            .translationY(0)
        //            .setStartDelay(50)
        //            .setDuration(200)
        //            .setInterpolator(new AccelerateDecelerateInterpolator());
        RecyclerView recyclerView = fragments.get(mainListPager.getCurrentItem()).getCourseRecyclerView();
        if (recyclerView != null && firstLaunch) {
            recyclerView.scheduleLayoutAnimation();
        }
        addButton.animate().alpha(1.f).scaleX(1.f).scaleY(1.f).setDuration(200).setStartDelay(200);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        switch (requestCode) {
        // returned result from Settings Activity
        case REQ_SETTING:
            if (resultCode == RESULT_OK) {
                int returnWeekday = data.getIntExtra(getString(R.string.key_num_of_weekday), -1);
                int isLogout = data.getIntExtra(getString(R.string.key_logout), SettingsActivity.FLAG_NO_LOGOUT);
                /**
                 * 0 assign num of weekdays and setupFragments
                 * 1 updateDrawer
                 * 2 setupList
                 */
                boolean flags[] = new boolean[4];
                if (returnWeekday != -1) {
                    flags[0] = true;
                    flags[2] = true;
                }
                if (isLogout != SettingsActivity.FLAG_NO_LOGOUT) {
                    flags[1] = true;
                    flags[2] = true;
                }
                for (int i = 0; i < flags.length; i++) {
                    if (flags[i]) {
                        switch (i) {
                        case 0:
                            numOfWeekdays = returnWeekday;
                            setupFragments();
                            break;
                        case 1:
                            updateDrawer();
                            break;
                        case 2:
                            setupList();
                            updateWeekNumDisplay();
                            break;
                        default:
                            break;
                        }
                    }
                }
            }
            break;
        case REQ_POSITION:
            LessonListFragment curFragment = fragments.get(mainListPager.getCurrentItem());
            int pos = data.getIntExtra(getString(R.string.intent_position), 0);

            if (resultCode == RESULT_OK) {
                LabelCourse course = (LabelCourse) curFragment
                        .findCourseById(data.getLongExtra(getString(R.string.intent_course_id), -1));
                if (course != null) {
                    course.setLabelImgIndex(data.getIntExtra(getString(R.string.intent_label_image_index), 0));
                    course.resetColors();
                    curFragment.adapter.notifyItemChanged(pos);
                }

                if (curFragment == null)
                    Log.e(TAG, "curFragment is null");
                if (curFragment.adapter == null)
                    Log.e(TAG, "adapater is null");
            }
            break;
        }
    }

    ConfigManager getConfigManager() {
        return configManager;
    }

    LessonListFragment getListFragment() {
        return fragments.get(mainListPager.getCurrentItem());
    }

    public void onClickThisWeek(View view) {
        popupThisWeek(curWeek);
        setupList();
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if (key.equals(getString(R.string.pref_week_num))) {
            // TODO update changed items
            setupList();
            updateWeekNumDisplay();
        }
    }

    @Override
    public void onInsertCourse(Course course) {
        if (course.getWeekDay() < fragments.size()) {
            fragments.get(course.getWeekDay()).addCourse(course);
            fragments.get(course.getWeekDay()).updateList();
        }
    }

    @Override
    public void onDeleteCourse(long id) {

    }

    private void popupThisWeek(int weekNum) {
        popupWeekText.setText(String.format(getString(R.string.weekday_week), weekNum));
        popupWeekText.setVisibility(View.VISIBLE);
        popupWeekText.setScaleX(.3f);
        popupWeekText.setScaleY(.3f);
        popupWeekText.setAlpha(.7f);
        Animator scaleAnimator = ObjectAnimator.ofFloat(popupWeekText, "scaleX", 1f);
        Animator scaleAnimator2 = ObjectAnimator.ofFloat(popupWeekText, "scaleY", 1f);
        scaleAnimator.setDuration(150);
        scaleAnimator2.setDuration(150);
        Animator alphaAnimator = ObjectAnimator.ofFloat(popupWeekText, "alpha", 0f);
        alphaAnimator.setStartDelay(120);
        alphaAnimator.setDuration(500);
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.play(scaleAnimator).with(scaleAnimator2).with(alphaAnimator);
        animatorSet.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                popupWeekText.setVisibility(View.GONE);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animatorSet.start();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onSessionStartOverEvent(SessionStartOverEvent event) {
        session.fetchSchedule();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onSessionStartErrorEvent(SessionErrorEvent event) {
        switch (event.getEc()) {
        case SESSION_EC_FAIL_TO_CONNECT:
            Toast.makeText(MainActivity.this, getString(R.string.alert_network_error), Toast.LENGTH_SHORT).show();
            break;
        case SESSION_EC_INVALID_ACCOUNT:
            Toast.makeText(MainActivity.this, getString(R.string.alert_invalid_account), Toast.LENGTH_SHORT).show();
            break;
        }

        if (refreshProgress != null)
            refreshProgress.setVisibility(View.GONE);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onScheduleFetchOverEvent(ScheduleFetchOverEvent event) {
        List<Course> courses = event.getCourses();
        if (courses != null) {
            configManager.saveSchedule(courses);
            configManager.saveStuNo(session.getStuNum());
            configManager.savePassword(session.getPsw());
            setupList();
        }

        String stuName = null;
        stuName = session.fetchName();
        Log.i(TAG, "try getting name");
        if (stuName != null) {
            configManager.saveName(stuName);
            Log.i(TAG, "get name " + stuName);
            updateDrawer();
        } else {
            Toast.makeText(MainActivity.this, getString(R.string.alert_invalid_account), Toast.LENGTH_SHORT).show();
        }
        if (refreshProgress != null)
            refreshProgress.setVisibility(View.INVISIBLE);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onHomepageFetchOverEvent(HomepageFetchOverEvent event) {
        int integer = event.getWeek();
        if (integer == 0) {
            Toast.makeText(MainActivity.this, "Unable to fetch week", Toast.LENGTH_SHORT).show();
            return;
        }
        // save the nearest past Monday
        long onePastMonday = 946828800000L; // Jan.3rd, 2000.
        long lastFetchTime = today.getTimeInMillis()
                - (today.getTimeInMillis() - onePastMonday) % MILLISECONDS_IN_A_WEEK;
        configManager.saveLastFetchWeekTime(lastFetchTime);

        if (curWeek != integer && integer > 0) {
            curWeek = integer;
            configManager.saveWeek(curWeek);
        }
        if (refreshProgress != null)
            refreshProgress.setVisibility(View.INVISIBLE);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onSwitchWeekNum(SwitchWeekNumEvent event) {
        int curNumBak = curWeek;
        if (event.getWeekNum() > 0) {
            if (event.getWeekNum() != curWeek)
                curWeek = event.getWeekNum();
            popupThisWeek(curWeek);
        }
        Log.i(TAG, "switch week num");
        setupList();
        curWeek = curNumBak;
    }
}