diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java index c9efb0c790..9fcdbe8cd1 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -277,7 +277,7 @@ public final class NativeLibrary public static void endEmulationActivity() { Log.v("DolphinEmu", "Ending EmulationActivity."); - mEmulationActivity.finish(); + mEmulationActivity.exitWithAnimation(); } public static void setEmulationActivity(EmulationActivity emulationActivity) 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 44bfbb8272..6b27c08c4a 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 @@ -29,11 +29,14 @@ public final class EmulationActivity extends AppCompatActivity { private View mDecorView; private ImageView mImageView; - private FrameLayout mFrameLayout; + private FrameLayout mFrameEmulation; private boolean mDeviceHasTouchScreen; private boolean mSystemUiVisible; + // So that MainActivity knows which view to invalidate before the return animation. + private int mPosition; + /** * Handlers are a way to pass a message to an Activity telling it to do something * on the UI thread. This Handler responds to any message, even blank ones, by @@ -47,6 +50,8 @@ public final class EmulationActivity extends AppCompatActivity hideSystemUI(); } }; + private String mScreenPath; + private FrameLayout mFrameContent; @Override protected void onCreate(Bundle savedInstanceState) @@ -92,15 +97,17 @@ public final class EmulationActivity extends AppCompatActivity setContentView(R.layout.activity_emulation); mImageView = (ImageView) findViewById(R.id.image_screenshot); - mFrameLayout = (FrameLayout) findViewById(R.id.frame_content); + mFrameContent = (FrameLayout) findViewById(R.id.frame_content); + mFrameEmulation = (FrameLayout) findViewById(R.id.frame_emulation_fragment); Intent gameToEmulate = getIntent(); String path = gameToEmulate.getStringExtra("SelectedGame"); String title = gameToEmulate.getStringExtra("SelectedTitle"); - String screenPath = gameToEmulate.getStringExtra("ScreenPath"); + mScreenPath = gameToEmulate.getStringExtra("ScreenPath"); + mPosition = gameToEmulate.getIntExtra("GridPosition", -1); Picasso.with(this) - .load(screenPath) + .load(mScreenPath) .noFade() .noPlaceholder() .into(mImageView, new Callback() @@ -120,6 +127,7 @@ public final class EmulationActivity extends AppCompatActivity }); mImageView.animate() + .withLayer() .setStartDelay(2000) .setDuration(500) .alpha(0.0f) @@ -128,7 +136,7 @@ public final class EmulationActivity extends AppCompatActivity @Override public void run() { - mFrameLayout.setVisibility(View.VISIBLE); + mFrameEmulation.setVisibility(View.VISIBLE); } }) .withEndAction(new Runnable() @@ -147,7 +155,7 @@ public final class EmulationActivity extends AppCompatActivity // Add fragment to the activity - this triggers all its lifecycle callbacks. getFragmentManager().beginTransaction() - .add(R.id.frame_content, emulationFragment, EmulationFragment.FRAGMENT_TAG) + .add(R.id.frame_emulation_fragment, emulationFragment, EmulationFragment.FRAGMENT_TAG) .commit(); } @@ -212,6 +220,59 @@ public final class EmulationActivity extends AppCompatActivity } } + public void exitWithAnimation() + { + runOnUiThread(new Runnable() + { + @Override + public void run() + { + Picasso.with(EmulationActivity.this) + .invalidate(mScreenPath); + + Picasso.with(EmulationActivity.this) + .load(mScreenPath) + .noFade() + .noPlaceholder() + .into(mImageView, new Callback() + { + @Override + public void onSuccess() + { + showScreenshot(); + } + + @Override + public void onError() + { + finish(); + } + }); + } + }); + } + + private void showScreenshot() + { + mImageView.setVisibility(View.VISIBLE); + mImageView.animate() + .withLayer() + .setDuration(500) + .alpha(1.0f) + .withEndAction(afterShowingScreenshot); + } + + private Runnable afterShowingScreenshot = new Runnable() + { + @Override + public void run() + { + mFrameContent.removeView(mFrameEmulation); + setResult(mPosition); + finishAfterTransition(); + } + }; + @Override public boolean onCreateOptionsMenu(Menu menu) { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java index 7812e6ead5..33cd0b0c15 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java @@ -36,6 +36,7 @@ import org.dolphinemu.dolphinemu.services.AssetCopyService; public final class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks { private static final int REQUEST_ADD_DIRECTORY = 1; + public static final int REQUEST_EMULATE_GAME = 2; /** * It is important to keep track of loader ID separately from platform ID (see Game.java) @@ -115,15 +116,29 @@ public final class MainActivity extends AppCompatActivity implements LoaderManag @Override protected void onActivityResult(int requestCode, int resultCode, Intent result) { - // If the user picked a file, as opposed to just backing out. - if (resultCode == RESULT_OK) + switch (requestCode) { - // Sanity check to make sure the Activity that just returned was the AddDirectoryActivity; - // other activities might use this callback in the future (don't forget to change Javadoc!) - if (requestCode == REQUEST_ADD_DIRECTORY) - { - refreshFragment(); - } + case REQUEST_ADD_DIRECTORY: + // If the user picked a file, as opposed to just backing out. + if (resultCode == RESULT_OK) + { + // Sanity check to make sure the Activity that just returned was the AddDirectoryActivity; + // other activities might use this callback in the future (don't forget to change Javadoc!) + if (requestCode == REQUEST_ADD_DIRECTORY) + { + refreshFragment(); + } + } + break; + + case REQUEST_EMULATE_GAME: + // Invalidate Picasso image so that the new screenshot is animated in. + PlatformGamesFragment fragment = getPlatformFragment(mViewPager.getCurrentItem()); + + if (fragment != null) + { + fragment.refreshScreenshotAtPosition(resultCode); + } } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java index 3cb832f91b..e74bd6f96d 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java @@ -5,6 +5,7 @@ import android.app.ActivityOptions; import android.content.Intent; import android.database.Cursor; import android.database.DataSetObserver; +import android.graphics.Bitmap; import android.graphics.Rect; import android.support.v7.widget.RecyclerView; import android.util.Log; @@ -16,6 +17,7 @@ import com.squareup.picasso.Picasso; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.activities.EmulationActivity; +import org.dolphinemu.dolphinemu.activities.MainActivity; import org.dolphinemu.dolphinemu.dialogs.GameDetailsDialog; import org.dolphinemu.dolphinemu.model.GameDatabase; import org.dolphinemu.dolphinemu.viewholders.GameViewHolder; @@ -81,14 +83,15 @@ public final class GameAdapter extends RecyclerView.Adapter impl if (mCursor.moveToPosition(position)) { String screenPath = mCursor.getString(GameDatabase.GAME_COLUMN_SCREENSHOT_PATH); - Picasso.with(holder.imageScreenshot.getContext()) - .invalidate(screenPath); // Fill in the view contents. Picasso.with(holder.imageScreenshot.getContext()) .load(screenPath) .fit() .centerCrop() + .noFade() + .noPlaceholder() + .config(Bitmap.Config.RGB_565) .error(R.drawable.no_banner) .into(holder.imageScreenshot); @@ -113,8 +116,6 @@ public final class GameAdapter extends RecyclerView.Adapter impl { Log.e("DolphinEmu", "Can't bind view; dataset is not valid."); } - - } /** @@ -222,13 +223,16 @@ public final class GameAdapter extends RecyclerView.Adapter impl intent.putExtra("SelectedGame", holder.path); intent.putExtra("SelectedTitle", holder.title); intent.putExtra("ScreenPath", holder.screenshotPath); + intent.putExtra("GridPosition", holder.getAdapterPosition()); ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation( (Activity) view.getContext(), holder.imageScreenshot, "image_game_screenshot"); - view.getContext().startActivity(intent, options.toBundle()); + ((Activity) view.getContext()).startActivityForResult(intent, + MainActivity.REQUEST_EMULATE_GAME, + options.toBundle()); } /** diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/PlatformGamesFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/PlatformGamesFragment.java index 4957090ed3..c1d1b1c8e7 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/PlatformGamesFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/PlatformGamesFragment.java @@ -1,12 +1,12 @@ package org.dolphinemu.dolphinemu.fragments; -import android.app.Activity; import android.app.Fragment; import android.app.LoaderManager; import android.content.Loader; import android.database.Cursor; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; @@ -57,6 +57,15 @@ public class PlatformGamesFragment extends Fragment RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getActivity(), getResources().getInteger(R.integer.game_grid_columns)); recyclerView.setLayoutManager(layoutManager); + recyclerView.setItemAnimator(new DefaultItemAnimator() + { + @Override + public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) + { + dispatchChangeFinished(newHolder, false); + return true; + } + }); recyclerView.addItemDecoration(new GameAdapter.SpacesItemDecoration(8)); @@ -70,10 +79,9 @@ public class PlatformGamesFragment extends Fragment return rootView; } - @Override - public void onAttach(Activity activity) + public void refreshScreenshotAtPosition(int position) { - super.onAttach(activity); + mAdapter.notifyItemChanged(position); } public void refresh() diff --git a/Source/Android/app/src/main/res/layout/activity_emulation.xml b/Source/Android/app/src/main/res/layout/activity_emulation.xml index c686c6191e..9e4e84e151 100644 --- a/Source/Android/app/src/main/res/layout/activity_emulation.xml +++ b/Source/Android/app/src/main/res/layout/activity_emulation.xml @@ -1,10 +1,11 @@ diff --git a/Source/Android/app/src/main/res/values/styles.xml b/Source/Android/app/src/main/res/values/styles.xml index dc81c173a7..dcfe4a77b7 100644 --- a/Source/Android/app/src/main/res/values/styles.xml +++ b/Source/Android/app/src/main/res/values/styles.xml @@ -8,17 +8,10 @@ @color/dolphin_blue_dark - + + true + true + true @@ -74,23 +67,17 @@ @color/dolphin_accent_wiiware -