Android: Add game grid view
This commit is contained in:
parent
2106197418
commit
5bd39bc2c7
|
@ -0,0 +1,159 @@
|
|||
package com.github.stenzek.duckstation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class GameGridFragment extends Fragment implements GameList.OnRefreshListener {
|
||||
private static final int SPACING_DIPS = 25;
|
||||
private static final int WIDTH_DIPS = 160;
|
||||
|
||||
private MainActivity mParent;
|
||||
private RecyclerView mRecyclerView;
|
||||
private ViewAdapter mAdapter;
|
||||
private GridAutofitLayoutManager mLayoutManager;
|
||||
|
||||
public GameGridFragment(MainActivity parent) {
|
||||
super(R.layout.fragment_game_grid);
|
||||
this.mParent = parent;
|
||||
}
|
||||
|
||||
private GameList getGameList() {
|
||||
return mParent.getGameList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
mAdapter = new ViewAdapter(mParent, getGameList());
|
||||
getGameList().addRefreshListener(this);
|
||||
|
||||
mRecyclerView = view.findViewById(R.id.game_list_view);
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
|
||||
final int columnWidth = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
||||
WIDTH_DIPS + SPACING_DIPS, getResources().getDisplayMetrics()));
|
||||
mLayoutManager = new GridAutofitLayoutManager(getContext(), columnWidth);
|
||||
mRecyclerView.setLayoutManager(mLayoutManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
getGameList().removeRefreshListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGameListRefresh() {
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
||||
private MainActivity mParent;
|
||||
private ImageView mImageView;
|
||||
private GameListEntry mEntry;
|
||||
|
||||
public ViewHolder(@NonNull MainActivity parent, @NonNull View itemView) {
|
||||
super(itemView);
|
||||
mParent = parent;
|
||||
mImageView = itemView.findViewById(R.id.imageView);
|
||||
mImageView.setOnClickListener(this);
|
||||
mImageView.setOnLongClickListener(this);
|
||||
}
|
||||
|
||||
public void bindToEntry(GameListEntry entry) {
|
||||
mEntry = entry;
|
||||
|
||||
final String coverPath = entry.getCoverPath();
|
||||
if (coverPath == null) {
|
||||
mImageView.setImageDrawable(ContextCompat.getDrawable(mParent, R.drawable.ic_media_cdrom));
|
||||
return;
|
||||
}
|
||||
|
||||
new ImageLoadTask(mImageView).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, coverPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mParent.startEmulation(mEntry.getPath(), mParent.shouldResumeStateByDefault());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
PopupMenu menu = new PopupMenu(mParent, v, Gravity.RIGHT | Gravity.TOP);
|
||||
menu.getMenuInflater().inflate(R.menu.menu_game_list_entry, menu.getMenu());
|
||||
menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == R.id.game_list_entry_menu_start_game) {
|
||||
mParent.startEmulation(mEntry.getPath(), false);
|
||||
return true;
|
||||
} else if (id == R.id.game_list_entry_menu_resume_game) {
|
||||
mParent.startEmulation(mEntry.getPath(), true);
|
||||
return true;
|
||||
} else if (id == R.id.game_list_entry_menu_properties) {
|
||||
mParent.openGameProperties(mEntry.getPath());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
menu.show();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ViewAdapter extends RecyclerView.Adapter<ViewHolder> {
|
||||
private MainActivity mParent;
|
||||
private LayoutInflater mInflater;
|
||||
private GameList mGameList;
|
||||
|
||||
public ViewAdapter(@NonNull MainActivity parent, @NonNull GameList gameList) {
|
||||
mParent = parent;
|
||||
mInflater = LayoutInflater.from(parent);
|
||||
mGameList = gameList;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(mParent, mInflater.inflate(R.layout.layout_game_grid_entry, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
GameListEntry entry = mGameList.getEntry(position);
|
||||
holder.bindToEntry(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mGameList.getEntryCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return R.layout.layout_game_grid_entry;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,13 +8,19 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class GameList {
|
||||
public interface OnRefreshListener {
|
||||
void onGameListRefresh();
|
||||
}
|
||||
|
||||
private Activity mContext;
|
||||
private GameListEntry[] mEntries;
|
||||
private ListViewAdapter mAdapter;
|
||||
private ArrayList<OnRefreshListener> mRefreshListeners = new ArrayList<>();
|
||||
|
||||
public GameList(Activity context) {
|
||||
mContext = context;
|
||||
|
@ -22,6 +28,13 @@ public class GameList {
|
|||
mEntries = new GameListEntry[0];
|
||||
}
|
||||
|
||||
public void addRefreshListener(OnRefreshListener listener) {
|
||||
mRefreshListeners.add(listener);
|
||||
}
|
||||
public void removeRefreshListener(OnRefreshListener listener) {
|
||||
mRefreshListeners.remove(listener);
|
||||
}
|
||||
|
||||
private class GameListEntryComparator implements Comparator<GameListEntry> {
|
||||
@Override
|
||||
public int compare(GameListEntry left, GameListEntry right) {
|
||||
|
@ -29,7 +42,6 @@ public class GameList {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public void refresh(boolean invalidateCache, boolean invalidateDatabase, Activity parentActivity) {
|
||||
// Search and get entries from native code
|
||||
AndroidProgressCallback progressCallback = new AndroidProgressCallback(mContext);
|
||||
|
@ -47,6 +59,8 @@ public class GameList {
|
|||
}
|
||||
mEntries = newEntries;
|
||||
mAdapter.notifyDataSetChanged();
|
||||
for (OnRefreshListener listener : mRefreshListeners)
|
||||
listener.onGameListRefresh();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -96,6 +96,8 @@ public class GameListEntry {
|
|||
return mCompatibilityRating;
|
||||
}
|
||||
|
||||
public String getCoverPath() { return mCoverPath; }
|
||||
|
||||
public static String getFileNameForPath(String path) {
|
||||
int lastSlash = path.lastIndexOf('/');
|
||||
if (lastSlash > 0 && lastSlash < path.length() - 1)
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package com.github.stenzek.duckstation;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.Gravity;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.PopupMenu;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
public class GameListFragment extends Fragment {
|
||||
private MainActivity mParent;
|
||||
private ListView mGameListView;
|
||||
|
||||
public GameListFragment(MainActivity parent) {
|
||||
super(R.layout.fragment_game_list);
|
||||
this.mParent = parent;
|
||||
}
|
||||
|
||||
private GameList getGameList() {
|
||||
return mParent.getGameList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
mGameListView = view.findViewById(R.id.game_list_view);
|
||||
mGameListView.setAdapter(getGameList().getListViewAdapter());
|
||||
mGameListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
mParent.startEmulation(getGameList().getEntry(position).getPath(), mParent.shouldResumeStateByDefault());
|
||||
}
|
||||
});
|
||||
mGameListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
|
||||
@Override
|
||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position,
|
||||
long id) {
|
||||
PopupMenu menu = new PopupMenu(getContext(), view, Gravity.RIGHT | Gravity.TOP);
|
||||
menu.getMenuInflater().inflate(R.menu.menu_game_list_entry, menu.getMenu());
|
||||
menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == R.id.game_list_entry_menu_start_game) {
|
||||
mParent.startEmulation(getGameList().getEntry(position).getPath(), false);
|
||||
return true;
|
||||
} else if (id == R.id.game_list_entry_menu_resume_game) {
|
||||
mParent.startEmulation(getGameList().getEntry(position).getPath(), true);
|
||||
return true;
|
||||
} else if (id == R.id.game_list_entry_menu_properties) {
|
||||
mParent.openGameProperties(getGameList().getEntry(position).getPath());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
menu.show();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package com.github.stenzek.duckstation;
|
||||
|
||||
// https://stackoverflow.com/questions/26666143/recyclerview-gridlayoutmanager-how-to-auto-detect-span-count
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.TypedValue;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class GridAutofitLayoutManager extends GridLayoutManager
|
||||
{
|
||||
private int columnWidth;
|
||||
private boolean isColumnWidthChanged = true;
|
||||
private int lastWidth;
|
||||
private int lastHeight;
|
||||
|
||||
public GridAutofitLayoutManager(@NonNull final Context context, final int columnWidth) {
|
||||
/* Initially set spanCount to 1, will be changed automatically later. */
|
||||
super(context, 1);
|
||||
setColumnWidth(checkedColumnWidth(context, columnWidth));
|
||||
}
|
||||
|
||||
public GridAutofitLayoutManager(
|
||||
@NonNull final Context context,
|
||||
final int columnWidth,
|
||||
final int orientation,
|
||||
final boolean reverseLayout) {
|
||||
|
||||
/* Initially set spanCount to 1, will be changed automatically later. */
|
||||
super(context, 1, orientation, reverseLayout);
|
||||
setColumnWidth(checkedColumnWidth(context, columnWidth));
|
||||
}
|
||||
|
||||
private int checkedColumnWidth(@NonNull final Context context, int columnWidth) {
|
||||
if (columnWidth <= 0) {
|
||||
/* Set default columnWidth value (48dp here). It is better to move this constant
|
||||
to static constant on top, but we need context to convert it to dp, so can't really
|
||||
do so. */
|
||||
columnWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48,
|
||||
context.getResources().getDisplayMetrics());
|
||||
}
|
||||
return columnWidth;
|
||||
}
|
||||
|
||||
public void setColumnWidth(final int newColumnWidth) {
|
||||
if (newColumnWidth > 0 && newColumnWidth != columnWidth) {
|
||||
columnWidth = newColumnWidth;
|
||||
isColumnWidthChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayoutChildren(@NonNull final RecyclerView.Recycler recycler, @NonNull final RecyclerView.State state) {
|
||||
final int width = getWidth();
|
||||
final int height = getHeight();
|
||||
if (columnWidth > 0 && width > 0 && height > 0 && (isColumnWidthChanged || lastWidth != width || lastHeight != height)) {
|
||||
final int totalSpace;
|
||||
if (getOrientation() == VERTICAL) {
|
||||
totalSpace = width - getPaddingRight() - getPaddingLeft();
|
||||
} else {
|
||||
totalSpace = height - getPaddingTop() - getPaddingBottom();
|
||||
}
|
||||
final int spanCount = Math.max(1, totalSpace / columnWidth);
|
||||
setSpanCount(spanCount);
|
||||
isColumnWidthChanged = false;
|
||||
}
|
||||
lastWidth = width;
|
||||
lastHeight = height;
|
||||
super.onLayoutChildren(recycler, state);
|
||||
}
|
||||
}
|
|
@ -12,30 +12,28 @@ import android.net.Uri;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentFactory;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
private static final int REQUEST_EXTERNAL_STORAGE_PERMISSIONS = 1;
|
||||
|
@ -47,7 +45,32 @@ public class MainActivity extends AppCompatActivity {
|
|||
|
||||
private GameList mGameList;
|
||||
private ListView mGameListView;
|
||||
private GameListFragment mGameListFragment;
|
||||
private GameGridFragment mGameGridFragment;
|
||||
private boolean mHasExternalStoragePermissions = false;
|
||||
private boolean mIsShowingGameGrid = false;
|
||||
|
||||
public MainActivity() {
|
||||
getSupportFragmentManager().setFragmentFactory(createFragmentFactory());
|
||||
}
|
||||
|
||||
private static String getTitleString() {
|
||||
String scmVersion = AndroidHostInterface.getScmVersion();
|
||||
final int gitHashPos = scmVersion.indexOf("-g");
|
||||
if (gitHashPos > 0)
|
||||
scmVersion = scmVersion.substring(0, gitHashPos);
|
||||
|
||||
return String.format("DuckStation %s", scmVersion);
|
||||
}
|
||||
|
||||
public GameList getGameList() {
|
||||
return mGameList;
|
||||
}
|
||||
|
||||
public boolean shouldResumeStateByDefault() {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
return prefs.getBoolean("Main/SaveStateOnExit", true);
|
||||
}
|
||||
|
||||
private void setLanguage() {
|
||||
String language = PreferenceManager.getDefaultSharedPreferences(this).getString("Main/Language", "none");
|
||||
|
@ -86,20 +109,42 @@ public class MainActivity extends AppCompatActivity {
|
|||
private void loadSettings() {
|
||||
setLanguage();
|
||||
setTheme();
|
||||
|
||||
mIsShowingGameGrid = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("Main/GameGridView", false);
|
||||
}
|
||||
|
||||
private boolean shouldResumeStateByDefault() {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
return prefs.getBoolean("Main/SaveStateOnExit", true);
|
||||
private FragmentFactory createFragmentFactory() {
|
||||
return new FragmentFactory() {
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment instantiate(@NonNull ClassLoader classLoader, @NonNull String className) {
|
||||
if (className == GameListFragment.class.getName())
|
||||
return new GameListFragment(MainActivity.this);
|
||||
else if (className == GameGridFragment.class.getName())
|
||||
return new GameGridFragment(MainActivity.this);
|
||||
|
||||
return super.instantiate(classLoader, className);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static String getTitleString() {
|
||||
String scmVersion = AndroidHostInterface.getScmVersion();
|
||||
final int gitHashPos = scmVersion.indexOf("-g");
|
||||
if (gitHashPos > 0)
|
||||
scmVersion = scmVersion.substring(0, gitHashPos);
|
||||
private void switchGameListView() {
|
||||
mIsShowingGameGrid = !mIsShowingGameGrid;
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.edit()
|
||||
.putBoolean("Main/GameGridView", mIsShowingGameGrid)
|
||||
.commit();
|
||||
|
||||
return String.format("DuckStation %s", scmVersion);
|
||||
updateGameListFragment();
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
private void updateGameListFragment() {
|
||||
getSupportFragmentManager()
|
||||
.beginTransaction()
|
||||
.setReorderingAllowed(true).
|
||||
replace(R.id.content_fragment, mIsShowingGameGrid ? mGameGridFragment : mGameListFragment)
|
||||
.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -127,42 +172,9 @@ public class MainActivity extends AppCompatActivity {
|
|||
|
||||
// Set up game list view.
|
||||
mGameList = new GameList(this);
|
||||
mGameListView = findViewById(R.id.game_list_view);
|
||||
mGameListView.setAdapter(mGameList.getListViewAdapter());
|
||||
mGameListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
startEmulation(mGameList.getEntry(position).getPath(), shouldResumeStateByDefault());
|
||||
}
|
||||
});
|
||||
mGameListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
|
||||
@Override
|
||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position,
|
||||
long id) {
|
||||
PopupMenu menu = new PopupMenu(MainActivity.this, view,
|
||||
Gravity.RIGHT | Gravity.TOP);
|
||||
menu.getMenuInflater().inflate(R.menu.menu_game_list_entry, menu.getMenu());
|
||||
menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == R.id.game_list_entry_menu_start_game) {
|
||||
startEmulation(mGameList.getEntry(position).getPath(), false);
|
||||
return true;
|
||||
} else if (id == R.id.game_list_entry_menu_resume_game) {
|
||||
startEmulation(mGameList.getEntry(position).getPath(), true);
|
||||
return true;
|
||||
} else if (id == R.id.game_list_entry_menu_properties) {
|
||||
openGameProperties(mGameList.getEntry(position).getPath());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
menu.show();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
mGameListFragment = new GameListFragment(this);
|
||||
mGameGridFragment = new GameGridFragment(this);
|
||||
updateGameListFragment();
|
||||
|
||||
mHasExternalStoragePermissions = checkForExternalStoragePermissions();
|
||||
if (mHasExternalStoragePermissions)
|
||||
|
@ -194,6 +206,13 @@ public class MainActivity extends AppCompatActivity {
|
|||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||
|
||||
final MenuItem switchViewItem = menu.findItem(R.id.action_switch_view);
|
||||
if (switchViewItem != null) {
|
||||
switchViewItem.setTitle(mIsShowingGameGrid ? R.string.action_show_game_list : R.string.action_show_game_grid);
|
||||
switchViewItem.setIcon(mIsShowingGameGrid ? R.drawable.ic_baseline_view_list_24 : R.drawable.ic_baseline_grid_view_24);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -227,6 +246,9 @@ public class MainActivity extends AppCompatActivity {
|
|||
Intent intent = new Intent(this, ControllerMappingActivity.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} else if (id == R.id.action_switch_view) {
|
||||
switchGameListView();
|
||||
return true;
|
||||
} else if (id == R.id.action_show_version) {
|
||||
showVersion();
|
||||
return true;
|
||||
|
@ -325,14 +347,14 @@ public class MainActivity extends AppCompatActivity {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean openGameProperties(String path) {
|
||||
public boolean openGameProperties(String path) {
|
||||
Intent intent = new Intent(this, GamePropertiesActivity.class);
|
||||
intent.putExtra("path", path);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean startEmulation(String bootPath, boolean resumeState) {
|
||||
public boolean startEmulation(String bootPath, boolean resumeState) {
|
||||
if (!doBIOSCheck())
|
||||
return false;
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M3,3v8h8L11,3L3,3zM9,9L5,9L5,5h4v4zM3,13v8h8v-8L3,13zM9,19L5,19v-4h4v4zM13,3v8h8L21,3h-8zM19,9h-4L15,5h4v4zM13,13v8h8v-8h-8zM19,19h-4v-4h4v4z"/>
|
||||
</vector>
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M4,14h4v-4L4,10v4zM4,19h4v-4L4,15v4zM4,9h4L8,5L4,5v4zM9,14h12v-4L9,10v4zM9,19h12v-4L9,15v4zM9,5v4h12L21,5L9,5z"/>
|
||||
</vector>
|
|
@ -33,7 +33,12 @@
|
|||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_main" />
|
||||
<FrameLayout
|
||||
android:id="@+id/content_fragment"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_weight="1"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab_resume"
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/game_list_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -3,10 +3,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:context=".MainActivity"
|
||||
tools:showIn="@layout/activity_main">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/game_list_view"
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="160dp"
|
||||
android:layout_height="160dp"
|
||||
android:layout_margin="25dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
app:srcCompat="@drawable/ic_media_cdrom"
|
||||
tools:layout_editor_absoluteX="1dp"
|
||||
tools:layout_editor_absoluteY="1dp" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -14,6 +14,12 @@
|
|||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:icon="@drawable/ic_baseline_settings_24"
|
||||
android:orderInCategory="101"
|
||||
android:title="@string/action_settings"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/action_switch_view"
|
||||
android:icon="@drawable/ic_baseline_settings_24"
|
||||
android:orderInCategory="100"
|
||||
android:title="@string/action_settings"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
|
|
@ -227,4 +227,6 @@
|
|||
<string name="dialog_touchscreen_controller_buttons">Touchscreen Controller Buttons</string>
|
||||
<string name="dialog_touchscreen_controller_settings">Touchscreen Controller Settings</string>
|
||||
<string name="settings_summary_console_tty_output">Logs debug messages printed by games.</string>
|
||||
<string name="action_show_game_list">List View</string>
|
||||
<string name="action_show_game_grid">Grid View</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue