diff --git a/Source/Android/app/build.gradle b/Source/Android/app/build.gradle index 8f5ce60a76..9668d8af95 100644 --- a/Source/Android/app/build.gradle +++ b/Source/Android/app/build.gradle @@ -1,7 +1,8 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 21 + // Leanback support requires >22 + compileSdkVersion 22 buildToolsVersion "22.0.1" lintOptions { @@ -80,6 +81,9 @@ dependencies { compile 'com.android.support:recyclerview-v7:22.2.0' compile 'com.android.support:design:22.2.0' + // Android TV UI libraries. + compile 'com.android.support:leanback-v17:22.2.0' + // For showing the banner as a circle a-la Material Design Guidelines compile 'de.hdodenhof:circleimageview:1.2.2' diff --git a/Source/Android/app/src/main/AndroidManifest.xml b/Source/Android/app/src/main/AndroidManifest.xml index 30fffd11e9..e08b2dd0a8 100644 --- a/Source/Android/app/src/main/AndroidManifest.xml +++ b/Source/Android/app/src/main/AndroidManifest.xml @@ -33,11 +33,22 @@ - + + + + + + + + + + { - private static final int REQUEST_ADD_DIRECTORY = 1; + public static final int REQUEST_ADD_DIRECTORY = 1; public static final int REQUEST_EMULATE_GAME = 2; /** @@ -139,6 +139,7 @@ public final class MainActivity extends AppCompatActivity implements LoaderManag { fragment.refreshScreenshotAtPosition(resultCode); } + break; } } @@ -226,7 +227,7 @@ public final class MainActivity extends AppCompatActivity implements LoaderManag GameProvider.URI_GAME, // URI of table to query null, // Return all columns GameDatabase.KEY_GAME_PLATFORM + " = ?", // Select by platform - new String[]{Integer.toString(id)}, // Platform id is Loader id minus 1 + new String[]{Integer.toString(id)}, // Platform id is Loader id GameDatabase.KEY_GAME_TITLE + " asc" // Sort by game name, ascending order ); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java new file mode 100644 index 0000000000..3f3b8c168d --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java @@ -0,0 +1,290 @@ +package org.dolphinemu.dolphinemu.activities; + +import android.app.Activity; +import android.app.ActivityOptions; +import android.app.FragmentManager; +import android.content.Intent; +import android.content.SharedPreferences; +import android.database.Cursor; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v17.leanback.app.BrowseFragment; +import android.support.v17.leanback.database.CursorMapper; +import android.support.v17.leanback.widget.ArrayObjectAdapter; +import android.support.v17.leanback.widget.CursorObjectAdapter; +import android.support.v17.leanback.widget.HeaderItem; +import android.support.v17.leanback.widget.ListRow; +import android.support.v17.leanback.widget.ListRowPresenter; +import android.support.v17.leanback.widget.OnItemViewClickedListener; +import android.support.v17.leanback.widget.Presenter; +import android.support.v17.leanback.widget.Row; +import android.support.v17.leanback.widget.RowPresenter; +import android.widget.Toast; + +import org.dolphinemu.dolphinemu.NativeLibrary; +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.adapters.GameRowPresenter; +import org.dolphinemu.dolphinemu.adapters.SettingsRowPresenter; +import org.dolphinemu.dolphinemu.model.Game; +import org.dolphinemu.dolphinemu.model.GameDatabase; +import org.dolphinemu.dolphinemu.model.GameProvider; +import org.dolphinemu.dolphinemu.model.TvSettingsItem; +import org.dolphinemu.dolphinemu.services.AssetCopyService; +import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; + +public final class TvMainActivity extends Activity +{ + protected BrowseFragment mBrowseFragment; + + private ArrayObjectAdapter mRowsAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_tv_main); + + final FragmentManager fragmentManager = getFragmentManager(); + mBrowseFragment = (BrowseFragment) fragmentManager.findFragmentById( + R.id.fragment_game_list); + + // Set display parameters for the BrowseFragment + mBrowseFragment.setHeadersState(BrowseFragment.HEADERS_ENABLED); + mBrowseFragment.setTitle(getString(R.string.app_name)); + mBrowseFragment.setBadgeDrawable(getResources().getDrawable( + R.drawable.ic_launcher, null)); + mBrowseFragment.setBrandColor(getResources().getColor(R.color.dolphin_blue_dark)); + + buildRowsAdapter(); + + mBrowseFragment.setOnItemViewClickedListener( + new OnItemViewClickedListener() + { + @Override + public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) + { + // Special case: user clicked on a settings row item. + if (item instanceof TvSettingsItem) + { + TvSettingsItem settingsItem = (TvSettingsItem) item; + + switch (settingsItem.getItemId()) + { + case R.id.menu_refresh: + getContentResolver().insert(GameProvider.URI_REFRESH, null); + + // TODO Let the Activity know the data is refreshed in some other, better way. + recreate(); + break; + + case R.id.menu_settings: + // Launch the Settings Actvity. + Intent settings = new Intent(TvMainActivity.this, SettingsActivity.class); + startActivity(settings); + break; + + case R.id.button_add_directory: + Intent fileChooser = new Intent(TvMainActivity.this, AddDirectoryActivity.class); + + // The second argument to this method is read below in onActivityResult(). + startActivityForResult(fileChooser, MainActivity.REQUEST_ADD_DIRECTORY); + + break; + + default: + Toast.makeText(TvMainActivity.this, "Unimplemented menu option.", Toast.LENGTH_SHORT).show(); + break; + } + } + else + { + TvGameViewHolder holder = (TvGameViewHolder) itemViewHolder; + // Start the emulation activity and send the path of the clicked ISO to it. + Intent intent = new Intent(TvMainActivity.this, EmulationActivity.class); + + intent.putExtra("SelectedGame", holder.path); + intent.putExtra("SelectedTitle", holder.title); + intent.putExtra("ScreenPath", holder.screenshotPath); + + ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation( + TvMainActivity.this, + holder.imageScreenshot, + "image_game_screenshot"); + + startActivity(intent, options.toBundle()); + } + } + }); + + // Stuff in this block only happens when this activity is newly created (i.e. not a rotation) + if (savedInstanceState == null) + { + NativeLibrary.SetUserDirectory(""); // Auto-Detect + + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + boolean assetsCopied = preferences.getBoolean("assetsCopied", false); + + // Only perform these extensive copy operations once. + if (!assetsCopied) + { + // Copy assets into appropriate locations. + Intent copyAssets = new Intent(this, AssetCopyService.class); + startService(copyAssets); + } + } + } + + /** + * Callback from AddDirectoryActivity. Applies any changes necessary to the GameGridActivity. + * + * @param requestCode An int describing whether the Activity that is returning did so successfully. + * @param resultCode An int describing what Activity is giving us this callback. + * @param result The information the returning Activity is providing us. + */ + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent result) + { + switch (requestCode) + { + case MainActivity.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 == MainActivity.REQUEST_ADD_DIRECTORY) + { + // TODO Let the Activity know the data is refreshed in some other, better way. + recreate(); + } + } + break; + } + } + + private void buildRowsAdapter() + { + mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter()); + + // For each platform + for (int platformIndex = 0; platformIndex <= Game.PLATFORM_ALL; ++platformIndex) + { + ListRow row = buildGamesRow(platformIndex); + + // Add row to the adapter only if it is not empty. + if (row != null) + { + mRowsAdapter.add(row); + } + } + + ListRow settingsRow = buildSettingsRow(); + mRowsAdapter.add(settingsRow); + + mBrowseFragment.setAdapter(mRowsAdapter); + } + + private ListRow buildGamesRow(int platform) + { + // Create an adapter for this row. + CursorObjectAdapter row = new CursorObjectAdapter(new GameRowPresenter()); + + Cursor games; + if (platform == Game.PLATFORM_ALL) + { + // Get all games. + games = getContentResolver().query( + GameProvider.URI_GAME, // URI of table to query + null, // Return all columns + null, // Return all games + null, // Return all games + GameDatabase.KEY_GAME_TITLE + " asc" // Sort by game name, ascending order + ); + } + else + { + // Get games for this particular platform. + games = getContentResolver().query( + GameProvider.URI_GAME, // URI of table to query + null, // Return all columns + GameDatabase.KEY_GAME_PLATFORM + " = ?", // Select by platform + new String[]{Integer.toString(platform)}, // Platform id + GameDatabase.KEY_GAME_TITLE + " asc" // Sort by game name, ascending order + ); + } + + // If cursor is empty, don't return a Row. + if (!games.moveToFirst()) + { + return null; + } + + row.changeCursor(games); + row.setMapper(new CursorMapper() + { + @Override + protected void bindColumns(Cursor cursor) + { + // No-op? Not sure what this does. + } + + @Override + protected Object bind(Cursor cursor) + { + return Game.fromCursor(cursor); + } + }); + + String headerName; + switch (platform) + { + case Game.PLATFORM_GC: + headerName = "GameCube Games"; + break; + + case Game.PLATFORM_WII: + headerName = "Wii Games"; + break; + + case Game.PLATFORM_WII_WARE: + headerName = "WiiWare"; + break; + + case Game.PLATFORM_ALL: + headerName = "All Games"; + break; + + default: + headerName = "Error"; + break; + } + + // Create a header for this row. + HeaderItem header = new HeaderItem(platform, headerName); + + // Create the row, passing it the filled adapter and the header, and give it to the master adapter. + return new ListRow(header, row); + } + + private ListRow buildSettingsRow() + { + ArrayObjectAdapter rowItems = new ArrayObjectAdapter(new SettingsRowPresenter()); + + rowItems.add(new TvSettingsItem(R.id.menu_refresh, + R.drawable.ic_refresh_tv, + R.string.grid_menu_refresh)); + + rowItems.add(new TvSettingsItem(R.id.menu_settings, + R.drawable.ic_settings_tv, + R.string.grid_menu_settings)); + + rowItems.add(new TvSettingsItem(R.id.button_add_directory, + R.drawable.ic_add_tv, + R.string.add_directory_title)); + + // Create a header for this row. + HeaderItem header = new HeaderItem(R.string.settings, getString(R.string.settings)); + + return new ListRow(header, rowItems); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java new file mode 100644 index 0000000000..3b0b8095ce --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java @@ -0,0 +1,118 @@ +package org.dolphinemu.dolphinemu.adapters; + +import android.graphics.Bitmap; +import android.support.v17.leanback.widget.ImageCardView; +import android.support.v17.leanback.widget.Presenter; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.squareup.picasso.Picasso; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.Game; +import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; + +/** + * The Leanback library / docs call this a Presenter, but it works very + * similarly to a RecyclerView.ViewHolder. + */ +public final class GameRowPresenter extends Presenter +{ + public ViewHolder onCreateViewHolder(ViewGroup parent) + { + // Create a new view. + ImageCardView gameCard = new ImageCardView(parent.getContext()) + { + @Override + public void setSelected(boolean selected) + { + setCardBackground(this, selected); + super.setSelected(selected); + } + }; + + gameCard.setMainImageAdjustViewBounds(true); + gameCard.setMainImageDimensions(480, 320); + gameCard.setMainImageScaleType(ImageView.ScaleType.CENTER_CROP); + + gameCard.setFocusable(true); + gameCard.setFocusableInTouchMode(true); + + setCardBackground(gameCard, false); + + // Use that view to create a ViewHolder. + return new TvGameViewHolder(gameCard); + } + + public void onBindViewHolder(ViewHolder viewHolder, Object item) + { + TvGameViewHolder holder = (TvGameViewHolder) viewHolder; + Game game = (Game) item; + + String screenPath = game.getScreenshotPath(); + + // 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); + + holder.cardParent.setTitleText(game.getTitle()); + holder.cardParent.setContentText(game.getCompany()); + + // TODO These shouldn't be necessary once the move to a DB-based model is complete. + holder.gameId = game.getGameId(); + holder.path = game.getPath(); + holder.title = game.getTitle(); + holder.description = game.getDescription(); + holder.country = game.getCountry(); + holder.company = game.getCompany(); + holder.screenshotPath = game.getScreenshotPath(); + + switch (game.getPlatform()) + { + case Game.PLATFORM_GC: + holder.cardParent.setTag(R.color.dolphin_accent_gamecube); + break; + + case Game.PLATFORM_WII: + holder.cardParent.setTag(R.color.dolphin_accent_wii); + break; + + case Game.PLATFORM_WII_WARE: + holder.cardParent.setTag(R.color.dolphin_accent_wiiware); + break; + + default: + holder.cardParent.setTag(android.R.color.holo_red_dark); + break; + } + } + + public void onUnbindViewHolder(ViewHolder viewHolder) + { + // no op + } + + public void setCardBackground(ImageCardView view, boolean selected) + { + int backgroundColor; + + if (selected) + { + // TODO: 7/20/15 Try using view tag to set color + backgroundColor = (int) view.getTag(); + } + else + { + backgroundColor = R.color.tv_card_unselected; + } + + view.setInfoAreaBackgroundColor(view.getResources().getColor(backgroundColor)); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/SettingsRowPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/SettingsRowPresenter.java new file mode 100644 index 0000000000..beef06a218 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/SettingsRowPresenter.java @@ -0,0 +1,47 @@ +package org.dolphinemu.dolphinemu.adapters; + + +import android.content.res.Resources; +import android.support.v17.leanback.widget.ImageCardView; +import android.support.v17.leanback.widget.Presenter; +import android.view.ViewGroup; + +import org.dolphinemu.dolphinemu.model.TvSettingsItem; +import org.dolphinemu.dolphinemu.viewholders.TvSettingsViewHolder; + +public final class SettingsRowPresenter extends Presenter +{ + public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent) + { + // Create a new view. + ImageCardView settingsCard = new ImageCardView(parent.getContext()); + + settingsCard.setMainImageAdjustViewBounds(true); + settingsCard.setMainImageDimensions(192, 160); + + + settingsCard.setFocusable(true); + settingsCard.setFocusableInTouchMode(true); + + // Use that view to create a ViewHolder. + return new TvSettingsViewHolder(settingsCard); + } + + public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) + { + TvSettingsViewHolder holder = (TvSettingsViewHolder) viewHolder; + TvSettingsItem settingsItem = (TvSettingsItem) item; + + Resources resources = holder.cardParent.getResources(); + + holder.itemId = settingsItem.getItemId(); + + holder.cardParent.setTitleText(resources.getString(settingsItem.getLabelId())); + holder.cardParent.setMainImage(resources.getDrawable(settingsItem.getIconId(), null)); + } + + public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) + { + // no op + } +} \ No newline at end of file diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java index f3ef6f7514..33a9f27c54 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/Game.java @@ -3,13 +3,12 @@ package org.dolphinemu.dolphinemu.model; import android.content.ContentValues; import android.database.Cursor; -import java.io.File; - public final class Game { public static final int PLATFORM_GC = 0; public static final int PLATFORM_WII = 1; public static final int PLATFORM_WII_WARE = 2; + public static final int PLATFORM_ALL = 3; // Copied from IVolume::ECountry. Update these if that is ever modified. public static final int COUNTRY_EUROPE = 0; @@ -33,13 +32,13 @@ public final class Game private String mDescription; private String mPath; private String mGameId; - private String mScreenshotFolderPath; + private String mScreenshotPath; private String mCompany; private int mPlatform; private int mCountry; - public Game(int platform, String title, String description, int country, String path, String gameId, String company) + public Game(int platform, String title, String description, int country, String path, String gameId, String company, String screenshotPath) { mPlatform = platform; mTitle = title; @@ -48,7 +47,7 @@ public final class Game mPath = path; mGameId = gameId; mCompany = company; - mScreenshotFolderPath = PATH_SCREENSHOT_FOLDER + getGameId() + "/"; + mScreenshotPath = screenshotPath; } public int getPlatform() @@ -86,27 +85,9 @@ public final class Game return mGameId; } - public String getScreenshotFolderPath() + public String getScreenshotPath() { - return mScreenshotFolderPath; - } - - public String getScreenPath() - { - // Count how many screenshots are available, so we can use the most recent one. - File screenshotFolder = new File(mScreenshotFolderPath.substring(mScreenshotFolderPath.indexOf('s') - 1)); - int screenCount = 0; - - if (screenshotFolder.isDirectory()) - { - screenCount = screenshotFolder.list().length; - } - - String screenPath = mScreenshotFolderPath - + getGameId() + "-" - + screenCount + ".png"; - - return screenPath; + return mScreenshotPath; } public static ContentValues asContentValues(int platform, String title, String description, int country, String path, String gameId, String company) @@ -135,6 +116,7 @@ public final class Game cursor.getInt(GameDatabase.GAME_COLUMN_COUNTRY), cursor.getString(GameDatabase.GAME_COLUMN_PATH), cursor.getString(GameDatabase.GAME_COLUMN_GAME_ID), - cursor.getString(GameDatabase.GAME_COLUMN_COMPANY)); + cursor.getString(GameDatabase.GAME_COLUMN_COMPANY), + cursor.getString(GameDatabase.GAME_COLUMN_SCREENSHOT_PATH)); } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.java new file mode 100644 index 0000000000..ccd87bfa4c --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.java @@ -0,0 +1,31 @@ +package org.dolphinemu.dolphinemu.model; + + +public final class TvSettingsItem +{ + private final int mItemId; + private final int mIconId; + private final int mLabelId; + + public TvSettingsItem(int itemId, int iconId, int labelId) + { + mItemId = itemId; + mIconId = iconId; + mLabelId = labelId; + } + + public int getItemId() + { + return mItemId; + } + + public int getIconId() + { + return mIconId; + } + + public int getLabelId() + { + return mLabelId; + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvGameViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvGameViewHolder.java new file mode 100644 index 0000000000..d27a671c2f --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvGameViewHolder.java @@ -0,0 +1,39 @@ +package org.dolphinemu.dolphinemu.viewholders; + +import android.support.v17.leanback.widget.ImageCardView; +import android.support.v17.leanback.widget.Presenter; +import android.view.View; +import android.widget.ImageView; + +/** + * A simple class that stores references to views so that the GameAdapter doesn't need to + * keep calling findViewById(), which is expensive. + */ +public final class TvGameViewHolder extends Presenter.ViewHolder +{ + public ImageCardView cardParent; + + public ImageView imageScreenshot; + + public String gameId; + + // TODO Not need any of this stuff. Currently only the properties dialog needs it. + public String path; + public String title; + public String description; + public int country; + public String company; + public String screenshotPath; + + public int backgroundColor; + + public TvGameViewHolder(View itemView) + { + super(itemView); + + itemView.setTag(this); + + cardParent = (ImageCardView) itemView; + imageScreenshot = cardParent.getMainImageView(); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvSettingsViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvSettingsViewHolder.java new file mode 100644 index 0000000000..3264e93f5b --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/viewholders/TvSettingsViewHolder.java @@ -0,0 +1,23 @@ +package org.dolphinemu.dolphinemu.viewholders; + + +import android.support.v17.leanback.widget.ImageCardView; +import android.support.v17.leanback.widget.Presenter; +import android.view.View; + +public final class TvSettingsViewHolder extends Presenter.ViewHolder +{ + public ImageCardView cardParent; + + // Determines what action to take when this item is clicked. + public int itemId; + + public TvSettingsViewHolder(View itemView) + { + super(itemView); + + itemView.setTag(this); + + cardParent = (ImageCardView) itemView; + } +} diff --git a/Source/Android/app/src/main/res/drawable/ic_add_tv.png b/Source/Android/app/src/main/res/drawable/ic_add_tv.png new file mode 100644 index 0000000000..7332c75727 Binary files /dev/null and b/Source/Android/app/src/main/res/drawable/ic_add_tv.png differ diff --git a/Source/Android/app/src/main/res/drawable/ic_refresh_tv.png b/Source/Android/app/src/main/res/drawable/ic_refresh_tv.png new file mode 100644 index 0000000000..8bae5d34ab Binary files /dev/null and b/Source/Android/app/src/main/res/drawable/ic_refresh_tv.png differ diff --git a/Source/Android/app/src/main/res/drawable/ic_settings_tv.png b/Source/Android/app/src/main/res/drawable/ic_settings_tv.png new file mode 100644 index 0000000000..9e242e7748 Binary files /dev/null and b/Source/Android/app/src/main/res/drawable/ic_settings_tv.png differ diff --git a/Source/Android/app/src/main/res/layout/activity_tv_main.xml b/Source/Android/app/src/main/res/layout/activity_tv_main.xml new file mode 100644 index 0000000000..922d874b02 --- /dev/null +++ b/Source/Android/app/src/main/res/layout/activity_tv_main.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/Source/Android/app/src/main/res/layout/card_game.xml b/Source/Android/app/src/main/res/layout/card_game.xml index 9b172b6871..542969ebd6 100644 --- a/Source/Android/app/src/main/res/layout/card_game.xml +++ b/Source/Android/app/src/main/res/layout/card_game.xml @@ -33,7 +33,6 @@ android:layout_marginLeft="16dp" android:layout_marginRight="16dp" android:layout_marginTop="16dp" - android:layout_toStartOf="@+id/button_details" android:ellipsize="end" android:lines="1" android:maxLines="1" diff --git a/Source/Android/app/src/main/res/values/colors.xml b/Source/Android/app/src/main/res/values/colors.xml index d7b7847125..9052de99d5 100644 --- a/Source/Android/app/src/main/res/values/colors.xml +++ b/Source/Android/app/src/main/res/values/colors.xml @@ -8,4 +8,6 @@ #651fff #bdbdbd + + #444444 \ No newline at end of file diff --git a/Source/Android/app/src/main/res/values/styles.xml b/Source/Android/app/src/main/res/values/styles.xml index 76ee1f8f55..dba853f492 100644 --- a/Source/Android/app/src/main/res/values/styles.xml +++ b/Source/Android/app/src/main/res/values/styles.xml @@ -126,6 +126,21 @@ false + + + + +