From c0315fcf78dc966618b8ead1617571436957aba4 Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Sat, 4 Jul 2015 16:32:15 -0400 Subject: [PATCH] Android TV: Implement Save and Load state menus --- .../activities/EmulationActivity.java | 98 ++++++++++++++++++- .../fragments/LoadStateFragment.java | 55 +++++++++++ .../dolphinemu/fragments/MenuFragment.java | 6 +- .../fragments/SaveStateFragment.java | 55 +++++++++++ .../src/main/res/animator/menu_slide_in.xml | 17 ++++ .../src/main/res/animator/menu_slide_out.xml | 18 ++++ .../main/res/layout/fragment_state_load.xml | 65 ++++++++++++ .../main/res/layout/fragment_state_save.xml | 65 ++++++++++++ .../app/src/main/res/values/strings.xml | 1 + 9 files changed, 375 insertions(+), 5 deletions(-) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/LoadStateFragment.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/SaveStateFragment.java create mode 100644 Source/Android/app/src/main/res/animator/menu_slide_in.xml create mode 100644 Source/Android/app/src/main/res/animator/menu_slide_out.xml create mode 100644 Source/Android/app/src/main/res/layout/fragment_state_load.xml create mode 100644 Source/Android/app/src/main/res/layout/fragment_state_save.xml diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java index e2804de9c9..f7608506ed 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java @@ -1,5 +1,6 @@ package org.dolphinemu.dolphinemu.activities; +import android.app.Fragment; import android.content.Intent; import android.os.Bundle; import android.os.Handler; @@ -26,6 +27,8 @@ import com.squareup.picasso.Picasso; import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.fragments.EmulationFragment; +import org.dolphinemu.dolphinemu.fragments.LoadStateFragment; +import org.dolphinemu.dolphinemu.fragments.SaveStateFragment; import java.util.List; @@ -37,13 +40,15 @@ public final class EmulationActivity extends AppCompatActivity private FrameLayout mFrameEmulation; private LinearLayout mMenuLayout; - private boolean mDeviceHasTouchScreen; - private boolean mSystemUiVisible; - private boolean mMenuVisible; + private String mMenuFragmentTag; // So that MainActivity knows which view to invalidate before the return animation. private int mPosition; + private boolean mDeviceHasTouchScreen; + private boolean mSystemUiVisible; + private boolean mMenuVisible; + private static Interpolator sDecelerator = new DecelerateInterpolator(); private static Interpolator sAccelerator = new AccelerateInterpolator(); @@ -235,7 +240,14 @@ public final class EmulationActivity extends AppCompatActivity { if (!mDeviceHasTouchScreen) { - toggleMenu(); + if (mMenuFragmentTag != null) + { + removeMenu(); + } + else + { + toggleMenu(); + } } else { @@ -390,6 +402,15 @@ public final class EmulationActivity extends AppCompatActivity NativeLibrary.LoadState(9); return; + // TV Menu only + case R.id.menu_emulation_save_root: + showMenu(SaveStateFragment.FRAGMENT_ID); + return; + + case R.id.menu_emulation_load_root: + showMenu(LoadStateFragment.FRAGMENT_ID); + return; + // Save state slots case R.id.menu_emulation_save_1: NativeLibrary.SaveState(0); @@ -549,4 +570,73 @@ public final class EmulationActivity extends AppCompatActivity } }); } + + private void showMenu(int menuId) + { + Fragment fragment; + + switch (menuId) + { + case SaveStateFragment.FRAGMENT_ID: + fragment = SaveStateFragment.newInstance(); + mMenuFragmentTag = SaveStateFragment.FRAGMENT_TAG; + break; + + case LoadStateFragment.FRAGMENT_ID: + fragment = LoadStateFragment.newInstance(); + mMenuFragmentTag = LoadStateFragment.FRAGMENT_TAG; + break; + + default: + return; + } + + getFragmentManager().beginTransaction() + .setCustomAnimations(R.animator.menu_slide_in, R.animator.menu_slide_out) + .replace(R.id.frame_submenu, fragment, mMenuFragmentTag) + .commit(); + } + + private void removeMenu() + { + if (mMenuFragmentTag != null) + { + final Fragment fragment = getFragmentManager().findFragmentByTag(mMenuFragmentTag); + + if (fragment != null) + { + // When removing a fragment without replacement, its aniimation must be done + // manually beforehand. + fragment.getView().animate() + .withLayer() + .setDuration(200) + .setInterpolator(sAccelerator) + .alpha(0.0f) + .translationX(600.0f) + .withEndAction(new Runnable() + { + @Override + public void run() + { + if (mMenuVisible) + { + getFragmentManager().beginTransaction() + .remove(fragment) + .commit(); + } + } + }); + } + else + { + Log.e("DolphinEmu", "[EmulationActivity] Fragment not found, can't remove."); + } + + mMenuFragmentTag = null; + } + else + { + Log.e("DolphinEmu", "[EmulationActivity] Fragment Tag empty."); + } + } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/LoadStateFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/LoadStateFragment.java new file mode 100644 index 0000000000..bbd9807b9b --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/LoadStateFragment.java @@ -0,0 +1,55 @@ +package org.dolphinemu.dolphinemu.fragments; + +import android.app.Fragment; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.GridLayout; + +import org.dolphinemu.dolphinemu.BuildConfig; +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.activities.EmulationActivity; + +public final class LoadStateFragment extends Fragment implements View.OnClickListener +{ + public static final String FRAGMENT_TAG = BuildConfig.APPLICATION_ID + ".load_state"; + public static final int FRAGMENT_ID = R.layout.fragment_state_load; + + public static LoadStateFragment newInstance() + { + LoadStateFragment fragment = new LoadStateFragment(); + + // TODO Add any appropriate arguments to this fragment. + + return fragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + View rootView = inflater.inflate(FRAGMENT_ID, container, false); + + GridLayout grid = (GridLayout) rootView.findViewById(R.id.grid_state_slots); + for (int childIndex = 0; childIndex < grid.getChildCount(); childIndex++) + { + Button button = (Button) grid.getChildAt(childIndex); + + button.setOnClickListener(this); + } + + // So that item clicked to start this Fragment is no longer the focused item. + grid.requestFocus(); + + return rootView; + } + + @Override + public void onClick(View button) + { + ((EmulationActivity) getActivity()).onMenuItemClicked(button.getId()); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java index f57ca36ede..5c847ee1b1 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java @@ -9,16 +9,20 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.LinearLayout; +import org.dolphinemu.dolphinemu.BuildConfig; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.activities.EmulationActivity; public final class MenuFragment extends Fragment implements View.OnClickListener { + public static final String FRAGMENT_TAG = BuildConfig.APPLICATION_ID + ".ingame_menu"; + public static final int FRAGMENT_ID = R.layout.fragment_ingame_menu; + @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - LinearLayout rootView = (LinearLayout) inflater.inflate(R.layout.fragment_ingame_menu, container, false); + LinearLayout rootView = (LinearLayout) inflater.inflate(FRAGMENT_ID, container, false); for (int childIndex = 0; childIndex < rootView.getChildCount(); childIndex++) { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/SaveStateFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/SaveStateFragment.java new file mode 100644 index 0000000000..a5e9e6d441 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/SaveStateFragment.java @@ -0,0 +1,55 @@ +package org.dolphinemu.dolphinemu.fragments; + +import android.app.Fragment; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.GridLayout; + +import org.dolphinemu.dolphinemu.BuildConfig; +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.activities.EmulationActivity; + +public final class SaveStateFragment extends Fragment implements View.OnClickListener +{ + public static final String FRAGMENT_TAG = BuildConfig.APPLICATION_ID + ".save_state"; + public static final int FRAGMENT_ID = R.layout.fragment_state_save; + + public static SaveStateFragment newInstance() + { + SaveStateFragment fragment = new SaveStateFragment(); + + // TODO Add any appropriate arguments to this fragment. + + return fragment; + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) + { + View rootView = inflater.inflate(FRAGMENT_ID, container, false); + + GridLayout grid = (GridLayout) rootView.findViewById(R.id.grid_state_slots); + for (int childIndex = 0; childIndex < grid.getChildCount(); childIndex++) + { + Button button = (Button) grid.getChildAt(childIndex); + + button.setOnClickListener(this); + } + + // So that item clicked to start this Fragment is no longer the focused item. + grid.requestFocus(); + + return rootView; + } + + @Override + public void onClick(View button) + { + ((EmulationActivity) getActivity()).onMenuItemClicked(button.getId()); + } +} diff --git a/Source/Android/app/src/main/res/animator/menu_slide_in.xml b/Source/Android/app/src/main/res/animator/menu_slide_in.xml new file mode 100644 index 0000000000..e6f9ae6d8e --- /dev/null +++ b/Source/Android/app/src/main/res/animator/menu_slide_in.xml @@ -0,0 +1,17 @@ + + + + + \ No newline at end of file diff --git a/Source/Android/app/src/main/res/animator/menu_slide_out.xml b/Source/Android/app/src/main/res/animator/menu_slide_out.xml new file mode 100644 index 0000000000..85c2556e48 --- /dev/null +++ b/Source/Android/app/src/main/res/animator/menu_slide_out.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/Source/Android/app/src/main/res/layout/fragment_state_load.xml b/Source/Android/app/src/main/res/layout/fragment_state_load.xml new file mode 100644 index 0000000000..1b04c6ce59 --- /dev/null +++ b/Source/Android/app/src/main/res/layout/fragment_state_load.xml @@ -0,0 +1,65 @@ + + + + + +