Merge branch 'heads/final-ui' into ui

This commit is contained in:
Gabriel BR Developer 2023-12-18 17:30:10 -04:00
commit 9ca7e88b6c
27 changed files with 384 additions and 50 deletions

View file

@ -1,5 +1,44 @@
package com.panda3ds.pandroid.app;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class BaseActivity extends AppCompatActivity {}
import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.data.config.GlobalConfig;
public class BaseActivity extends AppCompatActivity {
private int currentTheme = GlobalConfig.get(GlobalConfig.KEY_APP_THEME);
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
applyTheme();
super.onCreate(savedInstanceState);
}
@Override
protected void onResume() {
super.onResume();
if (GlobalConfig.get(GlobalConfig.KEY_APP_THEME) != currentTheme){
recreate();
}
}
private void applyTheme(){
switch (GlobalConfig.get(GlobalConfig.KEY_APP_THEME)){
case GlobalConfig.VALUE_THEME_ANDROID:
setTheme(R.style.Theme_Pandroid);
break;
case GlobalConfig.VALUE_THEME_LIGHT:
setTheme(R.style.Theme_Pandroid_Light);
break;
case GlobalConfig.VALUE_THEME_DARK:
setTheme(R.style.Theme_Pandroid_Dark);
break;
case GlobalConfig.VALUE_THEME_BLACK:
setTheme(R.style.Theme_Pandroid_Black);
break;
}
currentTheme = GlobalConfig.get(GlobalConfig.KEY_APP_THEME);
}
}

View file

@ -8,11 +8,13 @@ import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.app.PreferenceActivity;
import com.panda3ds.pandroid.app.base.BasePreferenceFragment;
import com.panda3ds.pandroid.app.preferences.InputMapPreferences;
import com.panda3ds.pandroid.app.preferences.AppearancePreferences;
public class SettingsFragment extends BasePreferenceFragment {
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
setPreferencesFromResource(R.xml.start_preferences, rootKey);
setItemClick("inputMap", (item) -> PreferenceActivity.launch(requireContext(), InputMapPreferences.class));
setItemClick("appearance", (item)-> PreferenceActivity.launch(requireContext(), AppearancePreferences.class));
}
}

View file

@ -0,0 +1,28 @@
package com.panda3ds.pandroid.app.preferences;
import android.app.Activity;
import android.os.Bundle;
import androidx.annotation.Nullable;
import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.app.BaseActivity;
import com.panda3ds.pandroid.app.base.BasePreferenceFragment;
import com.panda3ds.pandroid.data.config.GlobalConfig;
import com.panda3ds.pandroid.view.preferences.SingleSelectionPreferences;
public class AppearancePreferences extends BasePreferenceFragment {
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
setPreferencesFromResource(R.xml.appearance_preference, rootKey);
((BaseActivity) requireActivity()).getSupportActionBar().setTitle(R.string.appearance);
SingleSelectionPreferences themePreference = findPreference("theme");
themePreference.setSelectedItem(GlobalConfig.get(GlobalConfig.KEY_APP_THEME));
themePreference.setOnPreferenceChangeListener((preference, value) -> {
GlobalConfig.set(GlobalConfig.KEY_APP_THEME, (int) value);
return false;
});
}
}

View file

@ -8,8 +8,10 @@ import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.SeekBarPreference;
import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.app.BaseActivity;
import com.panda3ds.pandroid.app.base.BasePreferenceFragment;
import com.panda3ds.pandroid.input.InputMap;
import com.panda3ds.pandroid.input.KeyName;
@ -19,16 +21,35 @@ public class InputMapPreferences extends BasePreferenceFragment implements Activ
private ActivityResultLauncher<String> requestKey;
private String currentKey;
private SeekBarPreference deadZonePreference;
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
setPreferencesFromResource(R.xml.input_map_preferences, rootKey);
((BaseActivity) requireActivity()).getSupportActionBar().setTitle(R.string.controller_mapping);
for (KeyName key : KeyName.values()) {
if (key == KeyName.NULL) return;
if (key == KeyName.NULL) continue;
setItemClick(key.name(), this::onItemPressed);
}
deadZonePreference = getPreferenceScreen().findPreference("dead_zone");
deadZonePreference.setOnPreferenceChangeListener((preference, value) -> {
InputMap.setDeadZone(((int)value/100.0f));
refreshList();
return false;
});
refreshList();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
@ -56,6 +77,8 @@ public class InputMapPreferences extends BasePreferenceFragment implements Activ
}
private void refreshList() {
deadZonePreference.setValue((int)(InputMap.getDeadZone()*100));
deadZonePreference.setSummary(deadZonePreference.getValue()+"%");
for (KeyName key : KeyName.values()) {
if (key == KeyName.NULL) continue;
findPreference(key.name()).setSummary(InputMap.relative(key));

View file

@ -11,6 +11,13 @@ import java.io.Serializable;
public class GlobalConfig {
private static SharedPreferences data;
public static final int VALUE_THEME_ANDROID = 0;
public static final int VALUE_THEME_LIGHT = 1;
public static final int VALUE_THEME_DARK = 2;
public static final int VALUE_THEME_BLACK = 3;
public static final Key<Integer> KEY_APP_THEME = new Key<>("app.theme", VALUE_THEME_ANDROID);
public static void initialize() {
data = PandroidApplication.getAppContext()
.getSharedPreferences(Constants.PREF_GLOBAL_CONFIG, Context.MODE_PRIVATE);

View file

@ -1,5 +1,7 @@
package com.panda3ds.pandroid.data.game;
import android.graphics.Bitmap;
import java.util.UUID;
public class GameMetadata {
@ -7,7 +9,7 @@ public class GameMetadata {
private final String id;
private final String romPath;
private final String title;
private final int[] icon = new int[48 * 48];
private transient final Bitmap icon = Bitmap.createBitmap(48,48, Bitmap.Config.RGB_565);
private final String publisher;
private final GameRegion[] regions = new GameRegion[]{GameRegion.None};
@ -34,7 +36,7 @@ public class GameMetadata {
return publisher;
}
public int[] getIcon() {
public Bitmap getIcon() {
return icon;
}

View file

@ -36,7 +36,7 @@ public class InputMap {
}
public static void setDeadZone(float value) {
data.edit().putFloat(KEY_DEAD_ZONE, Math.max(0, Math.min(1.0F, value))).apply();
data.edit().putFloat(KEY_DEAD_ZONE, Math.max(0.0f, Math.min(1.0f, value))).apply();
}
}

View file

@ -3,8 +3,6 @@ package com.panda3ds.pandroid.utils;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import androidx.documentfile.provider.DocumentFile;
@ -27,15 +25,6 @@ public class FileUtils {
return file.getName();
}
public static long getSize(String path) {
return DocumentFile.fromSingleUri(getContext(), parseUri(path)).length();
}
public static String getCacheDir() {
return getContext().getCacheDir().getAbsolutePath();
}
public static void makeUriPermanent(String uri, String mode) {
int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
@ -44,20 +33,4 @@ public class FileUtils {
getContext().getContentResolver().takePersistableUriPermission(parseUri(uri), flags);
}
public static int openContentUri(String path, String mode) {
try {
Uri uri = parseUri(path);
ParcelFileDescriptor descriptor = getContext().getContentResolver().openFileDescriptor(uri, mode);
int fd = descriptor.getFd();
descriptor.detachFd();
descriptor.close();
return fd;
} catch (Exception e) {
Log.e(Constants.LOG_TAG, "Error on openContentUri: " + e);
}
return -1;
}
}

View file

@ -18,6 +18,8 @@ class ItemHolder extends RecyclerView.ViewHolder {
public void apply(GameMetadata game) {
((AppCompatTextView) itemView.findViewById(R.id.title))
.setText(game.getTitle());
((GameIconView) itemView.findViewById(R.id.icon))
.setImageBitmap(game.getIcon());
((AppCompatTextView) itemView.findViewById(R.id.description))
.setText(game.getPublisher());

View file

@ -0,0 +1,84 @@
package com.panda3ds.pandroid.view.preferences;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import com.panda3ds.pandroid.R;
import com.panda3ds.pandroid.utils.Constants;
public class SingleSelectionPreferences extends PreferenceCategory implements Preference.OnPreferenceClickListener {
private final Drawable transparent = new ColorDrawable(Color.TRANSPARENT);
private final Drawable doneDrawable = ContextCompat.getDrawable(getContext(), R.drawable.ic_done);
public SingleSelectionPreferences(@NonNull Context context) {
super(context);
}
public SingleSelectionPreferences(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public SingleSelectionPreferences(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public SingleSelectionPreferences(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
{
try {
TypedArray color = getContext().obtainStyledAttributes(new int[]{
android.R.attr.textColorSecondary
});
doneDrawable.setTint(color.getColor(0, Color.RED));
color.recycle();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
color.close();
}
} catch (Exception e) {
Log.e(Constants.LOG_TAG, "Error on obtain text color secondary: ", e);
}
}
@Override
public void onAttached() {
super.onAttached();
for (int i = 0; i < getPreferenceCount();i++) {
getPreference(i).setOnPreferenceClickListener(this);
}
}
public void setSelectedItem(int index){
onPreferenceClick(getPreference(index));
}
@Override
public boolean onPreferenceClick(@NonNull Preference preference) {
int index = 0;
for (int i = 0; i < getPreferenceCount(); i++){
Preference item = getPreference(i);
if (item == preference){
index = i;
item.setIcon(R.drawable.ic_done);
} else {
item.setIcon(transparent);
}
}
callChangeListener(index);
return false;
}
}

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?colorOnSecondary" android:state_checked="true"/>
<item android:color="?colorOnSurface"/>
</selector>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_enabled="true" android:color="#000"/>
<item android:state_activated="false" android:color="#8000"/>
<item android:state_enabled="false" android:color="#8000"/>
<item android:color="#000"/>
</selector>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_enabled="true" android:color="#FFF"/>
<item android:state_activated="false" android:color="#AFFF"/>
<item android:state_enabled="false" android:color="#AFFF"/>
<item android:color="#FFF"/>
</selector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,3c-4.97,0 -9,4.03 -9,9s4.03,9 9,9c0.83,0 1.5,-0.67 1.5,-1.5 0,-0.39 -0.15,-0.74 -0.39,-1.01 -0.23,-0.26 -0.38,-0.61 -0.38,-0.99 0,-0.83 0.67,-1.5 1.5,-1.5L16,16c2.76,0 5,-2.24 5,-5 0,-4.42 -4.03,-8 -9,-8zM6.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S5.67,9 6.5,9 8,9.67 8,10.5 7.33,12 6.5,12zM9.5,8C8.67,8 8,7.33 8,6.5S8.67,5 9.5,5s1.5,0.67 1.5,1.5S10.33,8 9.5,8zM14.5,8c-0.83,0 -1.5,-0.67 -1.5,-1.5S13.67,5 14.5,5s1.5,0.67 1.5,1.5S15.33,8 14.5,8zM17.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S16.67,9 17.5,9s1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5z"/>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

View file

@ -24,6 +24,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/main_activity_navigation"
app:labelVisibilityMode="selected"/>
app:labelVisibilityMode="selected"
style="@style/ThemedNavigationBottom"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -23,6 +23,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/fragment_container"
app:labelVisibilityMode="selected"
app:menu="@menu/main_activity_navigation"/>
app:menu="@menu/main_activity_navigation"
style="@style/ThemedNavigationBottom"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -13,11 +13,11 @@
app:cardCornerRadius="16dp">
<com.panda3ds.pandroid.view.gamesgrid.GameIconView
android:id="@+id/cover"
android:id="@+id/icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:src="@drawable/temp_thumb"/>
android:background="?colorSurfaceVariant"/>
</androidx.cardview.widget.CardView>

View file

@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_marginVertical="10dp"
android:layout_marginVertical="4dp"
android:layout_marginHorizontal="10dp"
android:background="@drawable/simple_card_background"
android:backgroundTint="?colorSurfaceVariant">

View file

@ -13,4 +13,15 @@
<string name="others">Outros</string>
<string name="press_any_key">Pressione qualquer tecla</string>
<string name="axis">Eixos</string>
<string name="dead_zone">Zona Morta</string>
<string name="options">Opções</string>
<string name="pref_input_map_summary">Mapeie um controle ou teclado</string>
<string name="controller_mapping">Mapeamento de controle</string>
<string name="theme">Tema</string>
<string name="pref_appearance_summary">Defina a aparência do aplicativo</string>
<string name="appearance">Aparência</string>
<string name="theme_device">Mesmo do dispositivo</string>
<string name="light">Claro</string>
<string name="dark">Escuro</string>
<string name="black">Preto</string>
</resources>

View file

@ -14,4 +14,15 @@
<string name="others">Others</string>
<string name="press_any_key">Press any key</string>
<string name="axis">Axis</string>
<string name="dead_zone">Dead zone</string>
<string name="options">Options</string>
<string name="pref_input_map_summary">Map physics controller or keyboard</string>
<string name="controller_mapping">Controller Mapping</string>
<string name="theme">Theme</string>
<string name="pref_appearance_summary">Set application theme</string>
<string name="appearance">Appearance</string>
<string name="theme_device">Device</string>
<string name="light">Light</string>
<string name="dark">Dark</string>
<string name="black">Black</string>
</resources>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Pandroid"/>
<style name="ControllerStyle"/>
<style name="ControllerStyle.SimpleButton">
<item name="android:layout_height">19pt</item>
@ -9,7 +12,19 @@
<item name="android:backgroundTintMode">multiply</item>
<item name="android:backgroundTint">#FFF</item>
</style>
<style name="HiddenTextAppearance">
<item name="android:textSize">0.1px</item>
<style name="ThemedNavigationBottom">
<item name="itemActiveIndicatorStyle">@style/ThemedNavigationBottom.Indicator</item>
<item name="labelVisibilityMode">selected</item>
<item name="android:background">#0000</item>
<item name="itemIconTint">@color/bottom_navigation_indicator_tint</item>
</style>
<style name="ThemedNavigationBottom.Indicator" parent="Widget.Material3.BottomNavigationView.ActiveIndicator">
<item name="color">?colorSecondary</item>
<item name="android:color">?colorSecondary</item>
</style>
<style name="Pandroid.SeekbarPreference" parent="Preference.SeekBarPreference">
<item name="android:textColorSecondary">#C00</item>
</style>
</resources>

View file

@ -1,9 +1,76 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<resources>
<!-- Base application theme. -->
<style name="Base.Theme.Pandroid" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your light theme here. -->
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
<item name="alertDialogTheme">@style/Theme.AppCompat.DayNight.Dialog</item>
</style>
<style name="Theme.Pandroid" parent="Base.Theme.Pandroid" />
<style name="Theme.Pandroid.Custom" parent="Theme.Pandroid">
<item name="android:textColor">?colorOnSurface</item>
<item name="android:textSize">16sp</item>
<item name="android:textColorHint">?colorOnSurfaceVariant</item>
<item name="android:statusBarColor">?colorSurfaceVariant</item>
<item name="android:windowBackground">?colorSurface</item>
<item name="titleTextColor">?colorOnSurface</item>
<item name="hintTextColor">?colorOnSurfaceVariant</item>
<item name="colorOnBackground">?colorOnSurface</item>
</style>
<style name="Theme.Pandroid.Dark" parent="Theme.Pandroid.Custom">
<item name="colorSurface">#222</item>
<item name="colorOnSurface">#FFF</item>
<item name="colorSurfaceVariant">#333</item>
<item name="colorOnSurfaceVariant">#BBB</item>
<item name="colorPrimary">#FF6D00</item>
<item name="colorOnPrimary">#FFF</item>
<item name="colorSecondary">#B37749</item>
<item name="colorOnSecondary">#FFF</item>
<item name="android:textColorPrimary">@color/text_secondary_light</item>
<item name="android:textColorSecondary">@color/text_secondary_light</item>
<item name="android:windowLightStatusBar">false</item>
</style>
<style name="Theme.Pandroid.Black" parent="Theme.Pandroid.Custom">
<item name="colorSurface">#000000</item>
<item name="colorOnSurface">#FFF</item>
<item name="colorSurfaceVariant">#202020</item>
<item name="colorOnSurfaceVariant">#BBB</item>
<item name="colorPrimary">#FF6D00</item>
<item name="colorOnPrimary">#000000</item>
<item name="colorSecondary">#B37749</item>
<item name="colorOnSecondary">#000000</item>
<item name="android:textColorPrimary">@color/text_secondary_light</item>
<item name="android:textColorSecondary">@color/text_secondary_light</item>
<item name="android:windowLightStatusBar">false</item>
</style>
<style name="Theme.Pandroid.Light" parent="Theme.Pandroid.Custom">
<item name="colorSurface">#FFF</item>
<item name="colorOnSurface">#111</item>
<item name="colorSurfaceVariant">#EEE</item>
<item name="colorOnSurfaceVariant">#222</item>
<item name="colorPrimary">#FF6D00</item>
<item name="colorOnPrimary">#FFF</item>
<item name="colorSecondary">#B37749</item>
<item name="colorOnSecondary">#FFF</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:textColorPrimary">@color/text_secondary_dark</item>
<item name="android:textColorSecondary">@color/text_secondary_dark</item>
</style>
</resources>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<com.panda3ds.pandroid.view.preferences.SingleSelectionPreferences
app:key="theme"
app:title="@string/theme"
app:iconSpaceReserved="false">
<Preference app:title="@string/theme_device"/>
<Preference app:title="@string/light"/>
<Preference app:title="@string/dark"/>
<Preference app:title="@string/black"/>
</com.panda3ds.pandroid.view.preferences.SingleSelectionPreferences>
</PreferenceScreen>

View file

@ -2,6 +2,19 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
app:title="@string/options"
app:iconSpaceReserved="false">
<SeekBarPreference
android:key="dead_zone"
android:title="@string/dead_zone"
app:iconSpaceReserved="false"
android:summary="0%"
android:max="100"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/axis"
app:iconSpaceReserved="false">

View file

@ -1,17 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:divider="#F00">
<Preference
android:title="@string/app_name"
android:enabled="false"
android:summary="1.0"
android:layout="@layout/preference_simple_about"/>
app:title="@string/app_name"
app:enabled="false"
app:summary="1.0"
app:layout="@layout/preference_simple_about"/>
<Preference
android:key="inputMap"
android:icon="@drawable/ic_key_a"
android:title="Controller Mapping"
android:summary="Map physics controller or keyboard"
android:layout="@layout/preference_start_item"/>
app:key="inputMap"
app:icon="@drawable/ic_key_a"
app:title="@string/controller_mapping"
app:summary="@string/pref_input_map_summary"
app:layout="@layout/preference_start_item"/>
<Preference
app:key="appearance"
app:icon="@drawable/ic_theme"
app:title="@string/appearance"
app:summary="@string/pref_appearance_summary"
app:layout="@layout/preference_start_item"/>
</PreferenceScreen>