/* * Copyright 2015 Google Inc. * * 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.google.samples.apps.topeka.fragment; import android.app.Activity; import android.os.Build; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; import android.support.v4.app.ActivityOptionsCompat; import android.support.v4.app.Fragment; import android.support.v4.util.Pair; import android.support.v4.view.ViewCompat; import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.text.Editable; import android.text.TextWatcher; import android.transition.Transition; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.EditText; import android.widget.GridView; import com.google.samples.apps.topeka.R; import com.google.samples.apps.topeka.activity.CategorySelectionActivity; import com.google.samples.apps.topeka.adapter.AvatarAdapter; import com.google.samples.apps.topeka.helper.ApiLevelHelper; import com.google.samples.apps.topeka.helper.PreferencesHelper; import com.google.samples.apps.topeka.helper.TransitionHelper; import com.google.samples.apps.topeka.model.Avatar; import com.google.samples.apps.topeka.model.Player; import com.google.samples.apps.topeka.widget.TransitionListenerAdapter; /** * Enable selection of an {@link Avatar} and user name. */ public class SignInFragment extends Fragment { private static final String ARG_EDIT = "EDIT"; private static final String KEY_SELECTED_AVATAR_INDEX = "selectedAvatarIndex"; private Player mPlayer; private EditText mFirstName; private EditText mLastInitial; private Avatar mSelectedAvatar; private View mSelectedAvatarView; private GridView mAvatarGrid; private FloatingActionButton mDoneFab; private boolean edit; public static SignInFragment newInstance(boolean edit) { Bundle args = new Bundle(); args.putBoolean(ARG_EDIT, edit); SignInFragment fragment = new SignInFragment(); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { if (savedInstanceState != null) { final int savedAvatarIndex = savedInstanceState.getInt(KEY_SELECTED_AVATAR_INDEX); if (savedAvatarIndex != GridView.INVALID_POSITION) { mSelectedAvatar = Avatar.values()[savedAvatarIndex]; } } super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { final View contentView = inflater.inflate(R.layout.fragment_sign_in, container, false); contentView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { v.removeOnLayoutChangeListener(this); setUpGridView(getView()); } }); return contentView; } @Override public void onSaveInstanceState(Bundle outState) { if (mAvatarGrid != null) { outState.putInt(KEY_SELECTED_AVATAR_INDEX, mAvatarGrid.getCheckedItemPosition()); } else { outState.putInt(KEY_SELECTED_AVATAR_INDEX, GridView.INVALID_POSITION); } super.onSaveInstanceState(outState); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { assurePlayerInit(); checkIsInEditMode(); if (mPlayer == null || edit) { view.findViewById(R.id.empty).setVisibility(View.GONE); view.findViewById(R.id.content).setVisibility(View.VISIBLE); initContentViews(view); initContents(); } else { final Activity activity = getActivity(); CategorySelectionActivity.start(activity, mPlayer); activity.finish(); } super.onViewCreated(view, savedInstanceState); } private void checkIsInEditMode() { final Bundle arguments = getArguments(); //noinspection SimplifiableIfStatement if (arguments == null) { edit = false; } else { edit = arguments.getBoolean(ARG_EDIT, false); } } private void initContentViews(View view) { TextWatcher textWatcher = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { /* no-op */ } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // hiding the floating action button if text is empty if (s.length() == 0) { mDoneFab.hide(); } } @Override public void afterTextChanged(Editable s) { // showing the floating action button if avatar is selected and input data is valid if (isAvatarSelected() && isInputDataValid()) { mDoneFab.show(); } } }; mFirstName = (EditText) view.findViewById(R.id.first_name); mFirstName.addTextChangedListener(textWatcher); mLastInitial = (EditText) view.findViewById(R.id.last_initial); mLastInitial.addTextChangedListener(textWatcher); mDoneFab = (FloatingActionButton) view.findViewById(R.id.done); mDoneFab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.done: savePlayer(getActivity()); removeDoneFab(new Runnable() { @Override public void run() { if (null == mSelectedAvatarView) { performSignInWithTransition(mAvatarGrid.getChildAt( mSelectedAvatar.ordinal())); } else { performSignInWithTransition(mSelectedAvatarView); } } }); break; default: throw new UnsupportedOperationException( "The onClick method has not been implemented for " + getResources() .getResourceEntryName(v.getId())); } } }); } private void removeDoneFab(@Nullable Runnable endAction) { ViewCompat.animate(mDoneFab) .scaleX(0) .scaleY(0) .setInterpolator(new FastOutSlowInInterpolator()) .withEndAction(endAction) .start(); } private void setUpGridView(View container) { mAvatarGrid = (GridView) container.findViewById(R.id.avatars); mAvatarGrid.setAdapter(new AvatarAdapter(getActivity())); mAvatarGrid.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { mSelectedAvatarView = view; mSelectedAvatar = Avatar.values()[position]; // showing the floating action button if input data is valid if (isInputDataValid()) { mDoneFab.show(); } } }); mAvatarGrid.setNumColumns(calculateSpanCount()); if (mSelectedAvatar != null) { mAvatarGrid.setItemChecked(mSelectedAvatar.ordinal(), true); } } private void performSignInWithTransition(View v) { final Activity activity = getActivity(); if (v == null || ApiLevelHelper.isLowerThan(Build.VERSION_CODES.LOLLIPOP)) { // Don't run a transition if the passed view is null CategorySelectionActivity.start(activity, mPlayer); activity.finish(); return; } if (ApiLevelHelper.isAtLeast(Build.VERSION_CODES.LOLLIPOP)) { activity.getWindow().getSharedElementExitTransition().addListener( new TransitionListenerAdapter() { @Override public void onTransitionEnd(Transition transition) { activity.finish(); } }); final Pair[] pairs = TransitionHelper.createSafeTransitionParticipants(activity, true, new Pair<>(v, activity.getString(R.string.transition_avatar))); @SuppressWarnings("unchecked") ActivityOptionsCompat activityOptions = ActivityOptionsCompat .makeSceneTransitionAnimation(activity, pairs); CategorySelectionActivity.start(activity, mPlayer, activityOptions); } } private void initContents() { assurePlayerInit(); if (mPlayer != null) { mFirstName.setText(mPlayer.getFirstName()); mLastInitial.setText(mPlayer.getLastInitial()); mSelectedAvatar = mPlayer.getAvatar(); } } private void assurePlayerInit() { if (mPlayer == null) { mPlayer = PreferencesHelper.getPlayer(getActivity()); } } private void savePlayer(Activity activity) { mPlayer = new Player(mFirstName.getText().toString(), mLastInitial.getText().toString(), mSelectedAvatar); PreferencesHelper.writeToPreferences(activity, mPlayer); } private boolean isAvatarSelected() { return mSelectedAvatarView != null || mSelectedAvatar != null; } private boolean isInputDataValid() { return PreferencesHelper.isInputDataValid(mFirstName.getText(), mLastInitial.getText()); } /** * Calculates spans for avatars dynamically. * * @return The recommended amount of columns. */ private int calculateSpanCount() { int avatarSize = getResources().getDimensionPixelSize(R.dimen.size_fab); int avatarPadding = getResources().getDimensionPixelSize(R.dimen.spacing_double); return mAvatarGrid.getWidth() / (avatarSize + avatarPadding); } }