Java tutorial
package com.kunze.androidlocaltodo; /* Copyright (c) 2014 Aaron Kunze (boilerpdx@gmail.com) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ import android.app.AlertDialog; import android.content.DialogInterface; import android.database.Cursor; import android.graphics.Color; import android.os.Bundle; import android.support.v4.app.Fragment; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.DatePicker; import android.widget.EditText; import android.widget.RadioButton; import android.widget.Spinner; import android.widget.TextView; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Locale; public class TaskActivityFragment extends Fragment implements ProgrammaticViewPager.ProgrammaticViewPagerNotify { @Override public void onSaveInstanceState(Bundle outState) { Log("onSaveInstanceState"); mProgrammaticChange = true; outState.putSerializable("mNewTask", mNewTask); super.onSaveInstanceState(outState); } @Override public void onActivityCreated(Bundle savedInstanceState) { Log("onActivityCreated"); super.onActivityCreated(savedInstanceState); } @Override public void onStart() { Log("onStart"); super.onStart(); } @Override public void onResume() { Log("onResume"); super.onResume(); mProgrammaticChange = false; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log("onCreateView"); mProgrammaticChange = true; TaskDatabase db = new TaskDatabase(getActivity()); View rootView = inflater.inflate(R.layout.activity_task, container, false); Bundle args = getArguments(); long id = args.getLong(TaskActivity.TASK_ID, 0); Task task = db.LoadTask(id); mOriginalTask = task; if (savedInstanceState != null) { mNewTask = (Task) savedInstanceState.getSerializable("mNewTask"); if (!mOriginalTask.equals(mNewTask)) { mProgrammaticChange = false; TaskChanged(rootView); mProgrammaticChange = true; } } else { mNewTask = new Task(task); } InitializeView(rootView); InitializeViewFields(rootView, task); return rootView; } private void InitializeView(final View rootView) { final View activityView = rootView; TextWatcher textWatcher = new TextWatcher() { @Override public void afterTextChanged(Editable s) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { TaskChanged(activityView); } }; final EditText nameEdit = (EditText) rootView.findViewById(R.id.task_name_edit); final TextView nameStatic = (TextView) rootView.findViewById(R.id.task_name_static); nameStatic.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { nameEdit.setVisibility(View.VISIBLE); nameStatic.setVisibility(View.INVISIBLE); } }); nameEdit.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { nameEdit.setVisibility(View.INVISIBLE); nameStatic.setVisibility(View.VISIBLE); } } }); nameEdit.addTextChangedListener(textWatcher); final TextView descriptionEdit = (TextView) rootView.findViewById(R.id.task_description_edit); descriptionEdit.addTextChangedListener(textWatcher); final TextView dueDateView = (TextView) rootView.findViewById(R.id.due_date_text); final DatePicker datePicker = (DatePicker) rootView.findViewById(R.id.due_date_calendar); datePicker.init(0, 0, 0, new DatePicker.OnDateChangedListener() { @Override public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) { Calendar calendar = Calendar.getInstance(); calendar.set(year, monthOfYear, dayOfMonth, 0, 0, 0); SetFriendlyDueDateText(dueDateView, calendar); TaskChanged(activityView); } }); Button todayButton = (Button) rootView.findViewById(R.id.today_button); todayButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Calendar now = Calendar.getInstance(); datePicker.updateDate(now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DAY_OF_MONTH)); SetFriendlyDueDateText(dueDateView, now); } }); Button plusDayButton = (Button) rootView.findViewById(R.id.plus_day_button); plusDayButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Calendar calendar = Calendar.getInstance(); calendar.set(datePicker.getYear(), datePicker.getMonth(), datePicker.getDayOfMonth()); calendar.add(Calendar.DATE, 1); datePicker.updateDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH)); SetFriendlyDueDateText(dueDateView, calendar); } }); Button thisWeekendButton = (Button) rootView.findViewById(R.id.this_weekend_button); thisWeekendButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Calendar weekend = Calendar.getInstance(); while (weekend.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY) { weekend.add(Calendar.DATE, 1); } datePicker.updateDate(weekend.get(Calendar.YEAR), weekend.get(Calendar.MONTH), weekend.get(Calendar.DAY_OF_MONTH)); SetFriendlyDueDateText(dueDateView, weekend); } }); Button plusWeekButton = (Button) rootView.findViewById(R.id.plus_week_button); plusWeekButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Calendar calendar = Calendar.getInstance(); calendar.set(datePicker.getYear(), datePicker.getMonth(), datePicker.getDayOfMonth()); calendar.add(Calendar.DATE, 7); datePicker.updateDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH)); SetFriendlyDueDateText(dueDateView, calendar); } }); final CheckBox repeatCheck = (CheckBox) rootView.findViewById(R.id.repeat); repeatCheck.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { View dialog = (View) buttonView.getParent(); SetRepeatVisibility(dialog, isChecked); TaskChanged(activityView); } }); final EditText repeatTimeEdit = (EditText) rootView.findViewById(R.id.repeat_time); repeatTimeEdit.addTextChangedListener(textWatcher); final Spinner repeatUnitSpinner = (Spinner) rootView.findViewById(R.id.repeat_unit); String[] repeatUnits = { "Days", "Weeks", "Months", "Years" }; repeatUnitSpinner.setAdapter( new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_item, repeatUnits)); repeatUnitSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (mRow != -1 && mRow != id) { TaskChanged(activityView); } mRow = id; } @Override public void onNothingSelected(AdapterView<?> arg0) { TaskChanged(activityView); } private long mRow = -1; }); final RadioButton repeatFromComplete = (RadioButton) rootView.findViewById(R.id.repeat_from_complete); final RadioButton repeatFromDue = (RadioButton) rootView.findViewById(R.id.repeat_from_due); Button revertButton = (Button) rootView.findViewById(R.id.revert_button); Button acceptButton = (Button) rootView.findViewById(R.id.accept_button); final Button doneButton = (Button) rootView.findViewById(R.id.done_button); Button deleteButton = (Button) rootView.findViewById(R.id.delete_button); revertButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mNewTask = new Task(mOriginalTask); mProgrammaticChange = true; InitializeViewFields(activityView, mOriginalTask); mProgrammaticChange = false; TaskReverted(activityView); } }); doneButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AlertDialog.Builder builder = new AlertDialog.Builder(doneButton.getContext()); builder.setTitle("Done?"); builder.setMessage("Mark task \"" + mNewTask.mName + "\" as done?"); builder.setNegativeButton("No", null); builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mNewTask.Done(); TaskDatabase db = new TaskDatabase(getActivity()); db.SaveTask(mNewTask); InitializeViewFields(rootView, mNewTask); } }); builder.show(); } }); } private void InitializeViewFields(View rootView, Task task) { final EditText nameEdit = (EditText) rootView.findViewById(R.id.task_name_edit); final TextView nameStatic = (TextView) rootView.findViewById(R.id.task_name_static); nameStatic.setText(task.mName); nameEdit.setText(task.mName); final TextView descriptionEdit = (TextView) rootView.findViewById(R.id.task_description_edit); descriptionEdit.setText(task.mDescription); final TextView dueDateView = (TextView) rootView.findViewById(R.id.due_date_text); SetFriendlyDueDateText(dueDateView, task.mDueDate); final Calendar dueDate = task.mDueDate; final DatePicker datePicker = (DatePicker) rootView.findViewById(R.id.due_date_calendar); datePicker.updateDate(dueDate.get(Calendar.YEAR), dueDate.get(Calendar.MONTH), dueDate.get(Calendar.DAY_OF_MONTH)); final CheckBox repeatCheck = (CheckBox) rootView.findViewById(R.id.repeat); Boolean repeat = task.mRepeatUnit != Task.RepeatUnit.NONE; repeatCheck.setChecked(repeat); SetRepeatVisibility(rootView, repeat); final EditText repeatTimeEdit = (EditText) rootView.findViewById(R.id.repeat_time); repeatTimeEdit.setText(Integer.toString(task.mRepeatTime)); final Spinner repeatUnitSpinner = (Spinner) rootView.findViewById(R.id.repeat_unit); int repeatUnitPos = 0; switch (task.mRepeatUnit) { case DAYS: repeatUnitPos = 0; break; case WEEKS: repeatUnitPos = 1; break; case MONTHS: repeatUnitPos = 2; break; case YEARS: repeatUnitPos = 3; break; case NONE: repeatUnitPos = 0; } repeatUnitSpinner.setSelection(repeatUnitPos); final RadioButton repeatFromComplete = (RadioButton) rootView.findViewById(R.id.repeat_from_complete); final RadioButton repeatFromDue = (RadioButton) rootView.findViewById(R.id.repeat_from_due); if (task.mRepeatFromComplete) { repeatFromComplete.setChecked(true); } else { repeatFromDue.setChecked(true); } } private void TaskChanged(View rootView) { if (!mProgrammaticChange) { Button revertButton = (Button) rootView.findViewById(R.id.revert_button); Button acceptButton = (Button) rootView.findViewById(R.id.accept_button); Button doneButton = (Button) rootView.findViewById(R.id.done_button); Button deleteButton = (Button) rootView.findViewById(R.id.delete_button); doneButton.setVisibility(Button.INVISIBLE); deleteButton.setVisibility(Button.INVISIBLE); revertButton.setVisibility(Button.VISIBLE); acceptButton.setVisibility(Button.VISIBLE); ProgrammaticViewPager pager = (ProgrammaticViewPager) getActivity() .findViewById(R.id.activity_task_pager); pager.Disable(this); } } private void TaskReverted(View rootView) { Button revertButton = (Button) rootView.findViewById(R.id.revert_button); Button acceptButton = (Button) rootView.findViewById(R.id.accept_button); Button doneButton = (Button) rootView.findViewById(R.id.done_button); Button deleteButton = (Button) rootView.findViewById(R.id.delete_button); doneButton.setVisibility(Button.VISIBLE); deleteButton.setVisibility(Button.VISIBLE); revertButton.setVisibility(Button.INVISIBLE); acceptButton.setVisibility(Button.INVISIBLE); ProgrammaticViewPager pager = (ProgrammaticViewPager) getActivity().findViewById(R.id.activity_task_pager); pager.Enable(); } @Override public void SwipedWhileDisabled() { AlphaAnimation animation = new AlphaAnimation(1.0f, 0.0f); animation.setDuration(50); animation.setRepeatCount(5); animation.setRepeatMode(Animation.REVERSE); Button revertButton = (Button) getView().findViewById(R.id.revert_button); Button acceptButton = (Button) getView().findViewById(R.id.accept_button); revertButton.startAnimation(animation); acceptButton.startAnimation(animation); } private static void SetFriendlyDueDateText(TextView dueDateView, Calendar dueDate) { SimpleDateFormat dateFormatDisplay = new SimpleDateFormat("MM-dd-yyyy", Locale.US); Calendar now = Calendar.getInstance(); int nowDay = TaskDatabase.ConvertDateToInt(now); int dueDay = TaskDatabase.ConvertDateToInt(dueDate); int dayDiff = nowDay - dueDay; if (dayDiff == 0) { dueDateView.setText("Today"); dueDateView.setTextColor(Color.RED); } else if (dueDate.before(now)) { dueDateView.setText("+ " + dayDiff + " days!"); dueDateView.setTextColor(Color.RED); } else if (dayDiff > -7) { dueDateView.setText(dueDate.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, Locale.US)); dueDateView.setTextColor(Color.BLACK); } else if (dayDiff > -14) { dueDateView.setText("Next " + dueDate.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, Locale.US)); dueDateView.setTextColor(Color.BLACK); } else { dueDateView.setText(dateFormatDisplay.format(dueDate.getTime())); dueDateView.setTextColor(Color.BLACK); } } private static void SetRepeatVisibility(View view, Boolean visible) { View[] repeatViews = { view.findViewById(R.id.repeat_label), view.findViewById(R.id.repeat_time), view.findViewById(R.id.repeat_unit), view.findViewById(R.id.repeat_from_label), view.findViewById(R.id.repeat_from), view.findViewById(R.id.repeat_from_complete), view.findViewById(R.id.repeat_from_due), view.findViewById(R.id.repeat_top_divider), view.findViewById(R.id.repeat_bottom_divider), }; if (visible) { for (View repeatView : repeatViews) { repeatView.setVisibility(View.VISIBLE); } } else { for (View repeatView : repeatViews) { repeatView.setVisibility(View.GONE); } } } private void Log(String message) { Bundle args = getArguments(); long id = args.getLong(TaskActivity.TASK_ID, 0); Log.v("TaskActivityFragment", message + " (" + Long.toString(id) + ")"); } private Task mOriginalTask; private Task mNewTask; private Boolean mProgrammaticChange; }