Java tutorial
/* * Copyright 2016, The Android Open Source Project * * 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 com.agenmate.lollipop.addedit; import android.app.Activity; import android.content.Intent; import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.BottomSheetBehavior; import android.support.design.widget.CoordinatorLayout; import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v4.content.ContextCompat; import android.support.v4.widget.NestedScrollView; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.widget.EditText; import android.widget.ImageButton; import android.widget.TextView; import com.agenmate.lollipop.R; import com.agenmate.lollipop.ui.SnappingSeekBar; import com.agenmate.lollipop.ui.layout.ArcMenu; import com.agenmate.lollipop.ui.layout.timepicker.TimePickerLayout; import com.agenmate.lollipop.util.FontUtils; import com.agenmate.lollipop.util.MarkupUtils; import com.agenmate.lollipop.util.ScreenUtils; import net.danlew.android.joda.DateUtils; import org.joda.time.DateTime; import java.util.List; import butterknife.BindView; import butterknife.BindViews; import butterknife.ButterKnife; import butterknife.Unbinder; import static com.google.common.base.Preconditions.checkNotNull; public class AddEditFragment extends Fragment implements AddEditContract.View { public static final String ARGUMENT_EDIT_TASK_ID = "EDIT_TASK_ID"; private AddEditContract.Presenter presenter; private ImageButton[] colorButtons; private ArcMenu timeMenu; private int[] colorTabIds = { R.color.md_red_700, R.color.md_orange_700, R.color.md_yellow_700, R.color.md_green_700, R.color.md_blue_700, R.color.md_indigo_700, R.color.md_deep_purple_700 }; private int[] colorBackgroundIds = { R.color.md_red_50, R.color.md_orange_50, R.color.md_yellow_50, R.color.md_green_50, R.color.md_blue_50, R.color.md_indigo_50, R.color.md_deep_purple_50 }; private int[] colorDrawables = { R.drawable.red_round_button, R.drawable.orange_round_button, R.drawable.yellow_round_button, R.drawable.green_round_button, R.drawable.blue_round_button, R.drawable.indigo_round_button, R.drawable.violet_round_button }; private int selectedColor; private Unbinder unbinder; private DateTime setTime; private int timeFormat; private int previousState = BottomSheetBehavior.STATE_COLLAPSED; private boolean hasAlarm; private boolean isCompleted; @BindViews({ R.id.title_text_view, R.id.title_card_view, R.id.desc_text_view, R.id.desc_card_view, R.id.priority_text_view, R.id.priority_card_view, R.id.color_text_view }) List<View> bottomViews; @BindView(R.id.arc_menu_color) ArcMenu arcMenu; @BindView(R.id.time_bottom_sheet) NestedScrollView sheet; @BindView(R.id.time_picker_layout) TimePickerLayout timePickerLayout; @BindView(R.id.due_date_text_view) TextView dueDateText; @BindView(R.id.due_date_status) TextView dueDateStatus; @BindView(R.id.due_date_teller) TextView dueDateTeller; @BindView(R.id.task_background) CoordinatorLayout background; @BindView(R.id.title_text_view) TextView titleText; @BindView(R.id.title_edit_text) EditText titleEdit; @BindView(R.id.desc_text_view) TextView descText; @BindView(R.id.desc_edit_text) EditText descEdit; @BindView(R.id.color_text_view) TextView colorText; @BindView(R.id.priority_text_view) TextView priorityText; @BindView(R.id.priority_seek_bar) SnappingSeekBar seekBar; public static AddEditFragment newInstance() { return new AddEditFragment(); } public AddEditFragment() { } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); setRetainInstance(true); colorButtons = new ImageButton[7]; } @Override public void onResume() { super.onResume(); presenter.subscribe(); } @Override public void onPause() { super.onPause(); presenter.unsubscribe(); } @Override public void setPresenter(@NonNull AddEditContract.Presenter presenter) { this.presenter = checkNotNull(presenter); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_edit, container, false); unbinder = ButterKnife.bind(this, rootView); timePickerLayout.setColorArcMenu(colorButtons); formatText(titleText, "<b>T</b>itle"); formatText(titleEdit, null); formatText(descText, "<b>D</b>escription"); formatText(descEdit, null); formatText(colorText, "<b>C</b>olor <b>T</b>ag"); formatText(priorityText, "<b>P</b>riority"); formatText(dueDateText, "<b>D</b>ue <b>D</b>ate"); formatText(dueDateTeller, null); formatText(dueDateStatus, "(Scroll up to set)"); seekBar.setProgressDrawable(R.drawable.progress_bar); seekBar.setItems(new String[] { "Low", "Medium", "High" }); seekBar.setTextIndicatorColor(Color.BLACK); seekBar.setIndicatorColor(ContextCompat.getColor(getActivity(), R.color.md_grey_300)); seekBar.setTextSize(14); seekBar.setIndicatorSize(4); BottomSheetBehavior.from(sheet).setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { @Override public void onStateChanged(@NonNull View bottomSheet, int newState) { switch (newState) { case BottomSheetBehavior.STATE_DRAGGING: dueDateStatus.setText(""); break; case BottomSheetBehavior.STATE_COLLAPSED: if (previousState == BottomSheetBehavior.STATE_EXPANDED) { previousState = newState; ButterKnife.apply(bottomViews, ALPHA_APPEAR); onColorArcExpanded(); setDueDateText(dueDateStatus); if (timeMenu.isExpanded()) timeMenu.switchState(); } break; case BottomSheetBehavior.STATE_EXPANDED: if (previousState == BottomSheetBehavior.STATE_COLLAPSED) { previousState = newState; ButterKnife.apply(bottomViews, ALPHA_FADE); for (int i = 0; i < 7; i++) colorButtons[i].setAlpha(1f); if (!timeMenu.isExpanded()) timePickerLayout.getDayArcMenu().switchState(); } break; } } @Override public void onSlide(View bottomSheet, float slideOffset) { } }); /*ViewUtils.waitForLayoutPrepared(seekBar, new ViewUtils.LayoutPreparedListener() { @Override public void onLayoutPrepared(final View preparedView) { seekBar.setProgressToIndex(1); } });*/ for (int i = 0; i < 7; i++) { final int index = i; final ImageButton button = new ImageButton(getActivity()); button.setBackgroundResource(colorDrawables[i]); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { button.setElevation(ScreenUtils.dpToPx(getActivity(), 2)); } colorButtons[i] = button; arcMenu.addItem(button, v -> { v.setAlpha(0.5f); if (index != selectedColor) { colorButtons[selectedColor].setAlpha(1f); setColor(index); } }); } timeMenu = timePickerLayout.getDayArcMenu(); arcMenu.setOnArcAnimationEndListener(isExpanded -> { if (isExpanded) onColorArcExpanded(); }); arcMenu.switchState(); return rootView; } private static final ButterKnife.Action<View> ALPHA_APPEAR = (view, index) -> { AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1); alphaAnimation.setDuration(250); alphaAnimation.setStartOffset(index * 250); alphaAnimation.setFillAfter(true); view.startAnimation(alphaAnimation); }; private final ButterKnife.Action<View> ALPHA_FADE = (view, index) -> { AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); alphaAnimation.setDuration(250); alphaAnimation.setStartOffset(index * 250); alphaAnimation.setFillAfter(true); if (index == 5) { alphaAnimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { if (timePickerLayout.getDueDateStatus() == TimePickerLayout.NO_DUE_DATE) { timePickerLayout.setDueDateStatus(TimePickerLayout.HAS_DUE_DATE); setDueDateText(dueDateTeller); ButterKnife.apply(dueDateTeller, ALPHA_APPEAR); } } @Override public void onAnimationRepeat(Animation animation) { } }); } view.startAnimation(alphaAnimation); }; @Override public void showEmptyTaskError() { Snackbar.make(titleText, getString(R.string.empty_task_message), Snackbar.LENGTH_LONG).show(); } @Override public void showTasksList(int returnColor) { getActivity().setResult(Activity.RESULT_OK, new Intent().putExtra("color", returnColor)); getActivity().finish(); } @Override public void showMissingTask() { titleEdit.setText(""); } @Override public void setTitle(String title) { titleEdit.setText(title); } @Override public void setDescription(String description) { descEdit.setText(description); } @Override public void setPriority(int priority) { seekBar.setProgress(priority * 50); } @Override public void setColor(int color) { selectedColor = color; boolean isWhiteText = selectedColor == 0 || selectedColor == 5 || selectedColor == 6; if (isWhiteText) { dueDateStatus.setTextColor(Color.WHITE); dueDateText.setTextColor(Color.WHITE); } else { dueDateStatus.setTextColor(Color.BLACK); dueDateText.setTextColor(Color.BLACK); } background.setBackgroundResource(colorBackgroundIds[selectedColor]); dueDateText.setBackgroundResource(colorTabIds[selectedColor]); ((AddEditActivity) getActivity()).setBarColor(selectedColor, isWhiteText); } @Override public void setDueDate(long dueDate) { setTime = timePickerLayout.resetDate(dueDate); setDueDateText(dueDateStatus); timePickerLayout.setOnTimePickerChangeListener(time -> { setTime = time; setDueDateText(dueDateTeller); }); } @Override public void setCompleted(boolean isCompleted) { this.isCompleted = isCompleted; } private void setDueDateText(TextView textView) { int status = timePickerLayout.getDueDateStatus(); if (status != TimePickerLayout.NO_DUE_DATE) { timeFormat = timePickerLayout.isAtMidnight() ? DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY : DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_SHOW_TIME; textView.setText(DateUtils.formatDateTime(getActivity(), setTime, timeFormat)); } } @Override public void showTaskDeleted() { getActivity().finish(); } @Override public void onDestroyView() { super.onDestroyView(); unbinder.unbind(); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); } public void onColorArcExpanded() { for (int i = 0; i < 7; i++) { colorButtons[i].setAlpha(1f); colorButtons[selectedColor].setAlpha(0.2f); } } private void formatText(TextView textView, String string) { if (string != null) { textView.setText(MarkupUtils.fromHtml(string)); } textView.setTextColor(Color.BLACK); textView.setTypeface(FontUtils.get(getActivity(), "Dudu")); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18); } public void onOptionsCreated() { ((AddEditActivity) getActivity()).setBarColor(selectedColor, selectedColor == 0 || selectedColor == 5 || selectedColor == 6); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: getActivity().onBackPressed(); return true; case R.id.action_save: String title = emptyStringChecker(titleEdit.getText().toString()); if (title == null) { Snackbar.make(background, "Title can't be Empty", Snackbar.LENGTH_LONG).show(); return true; } String description = emptyStringChecker(descEdit.getText().toString()); int priority = getPriority(); long dueAt = getDueDate(); if (dueAt < 0) { Snackbar.make(background, "Not enough time to complete task at due date", Snackbar.LENGTH_LONG) .show(); return true; } presenter.saveTask(title, description, priority, selectedColor, dueAt, hasAlarm, isCompleted); return true; case R.id.action_alarm: if (!hasAlarm) { if (getDueDate() < 0) { Snackbar.make(background, "Not enough time to complete task at due date", Snackbar.LENGTH_LONG) .show(); return true; } } boolean setWhite = selectedColor == 0 || selectedColor == 5 || selectedColor == 6; item.setIcon(hasAlarm ? R.drawable.ic_alarm_off : R.drawable.ic_alarm_on); Drawable drawable = item.getIcon(); drawable.mutate(); drawable.setColorFilter(setWhite ? Color.WHITE : Color.BLACK, PorterDuff.Mode.SRC_ATOP); hasAlarm = !hasAlarm; return true; case R.id.action_delete: presenter.deleteTask(); return true; } return super.onOptionsItemSelected(item); } private String emptyStringChecker(String string) { if (string != null) { string = string.trim(); if (!string.isEmpty()) { return string; } } return null; } private int getPriority() { return seekBar.getProgress() / 50; } private long getDueDate() { if (timePickerLayout.getDueDateStatus() == TimePickerLayout.NO_DUE_DATE) return 0; else { long time = timePickerLayout.getTimeFromPicker().getMillis() * 1000; DateTime now = new DateTime().withSecondOfMinute(0).withMillisOfSecond(0).plusMinutes(1); if (now.getMillis() * 1000 < time) return time; else { // TODO turn off alarm return -1; } } } }