Android: Add custom aspect ratio support

This commit is contained in:
Connor McLaughlin 2021-05-24 20:44:51 +10:00
parent daf2fd327f
commit a67f77d2a1
11 changed files with 247 additions and 1 deletions

View file

@ -3,7 +3,6 @@
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />

View file

@ -0,0 +1,198 @@
package com.github.stenzek.duckstation;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceDataStore;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceViewHolder;
public class RatioPreference extends Preference {
private String mNumeratorKey;
private String mDenominatorKey;
private int mNumeratorValue = 1;
private int mDenominatorValue = 1;
private int mMinimumNumerator = 1;
private int mMaximumNumerator = 50;
private int mDefaultNumerator = 1;
private int mMinimumDenominator = 1;
private int mMaximumDenominator = 50;
private int mDefaultDenominator = 1;
private void initAttributes(AttributeSet attrs) {
for (int i = 0; i < attrs.getAttributeCount(); i++) {
final String key = attrs.getAttributeName(i);
if (key.equals("numeratorKey")) {
mNumeratorKey = attrs.getAttributeValue(i);
} else if (key.equals("minimumNumerator")) {
mMinimumNumerator = attrs.getAttributeIntValue(i, 1);
} else if (key.equals("maximumNumerator")) {
mMaximumNumerator = attrs.getAttributeIntValue(i, 1);
} else if (key.equals("defaultNumerator")) {
mDefaultNumerator = attrs.getAttributeIntValue(i, 1);
} else if(key.equals("denominatorKey")) {
mDenominatorKey = attrs.getAttributeValue(i);
} else if (key.equals("minimumDenominator")) {
mMinimumDenominator = attrs.getAttributeIntValue(i, 1);
} else if (key.equals("maximumDenominator")) {
mMaximumDenominator = attrs.getAttributeIntValue(i, 1);
} else if (key.equals("defaultDenominator")) {
mDefaultDenominator = attrs.getAttributeIntValue(i, 1);
}
}
}
public RatioPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setWidgetLayoutResource(R.layout.layout_ratio_preference);
initAttributes(attrs);
}
public RatioPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setWidgetLayoutResource(R.layout.layout_ratio_preference);
initAttributes(attrs);
}
public RatioPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setWidgetLayoutResource(R.layout.layout_ratio_preference);
initAttributes(attrs);
}
public RatioPreference(Context context) {
super(context);
setWidgetLayoutResource(R.layout.layout_ratio_preference);
}
private void persistValues() {
final PreferenceDataStore dataStore = getPreferenceDataStore();
if (dataStore != null) {
if (mNumeratorKey != null)
dataStore.putInt(mNumeratorKey, mNumeratorValue);
if (mDenominatorKey != null)
dataStore.putInt(mDenominatorKey, mDenominatorValue);
} else {
SharedPreferences.Editor editor = getPreferenceManager().getSharedPreferences().edit();
if (mNumeratorKey != null)
editor.putInt(mNumeratorKey, mNumeratorValue);
if (mDenominatorKey != null)
editor.putInt(mDenominatorKey, mDenominatorValue);
editor.commit();
}
}
@Override
protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
super.onAttachedToHierarchy(preferenceManager);
setInitialValue();
}
private void setInitialValue() {
final PreferenceDataStore dataStore = getPreferenceDataStore();
if (dataStore != null) {
if (mNumeratorKey != null)
mNumeratorValue = dataStore.getInt(mNumeratorKey, mDefaultNumerator);
if (mDenominatorKey != null)
mDenominatorValue = dataStore.getInt(mDenominatorKey, mDefaultDenominator);
} else {
final SharedPreferences pm = getPreferenceManager().getSharedPreferences();
if (mNumeratorKey != null)
mNumeratorValue = pm.getInt(mNumeratorKey, mDefaultNumerator);
if (mDenominatorKey != null)
mDenominatorValue = pm.getInt(mDenominatorKey, mDefaultDenominator);
}
}
private static BaseAdapter generateDropdownItems(int min, int max) {
return new BaseAdapter() {
@Override
public int getCount() {
return (max - min) + 1;
}
@Override
public Object getItem(int position) {
return Integer.toString(min + position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView view;
if (convertView != null) {
view = (TextView) convertView;
} else {
view = new TextView(parent.getContext());
Resources r = parent.getResources();
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10.0f, r.getDisplayMetrics());
view.setPadding((int) px, (int) px, (int) px, (int) px);
}
view.setText(Integer.toString(min + position));
return view;
}
};
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
holder.itemView.setClickable(false);
Spinner numeratorSpinner = (Spinner) holder.findViewById(R.id.numerator);
numeratorSpinner.setAdapter(generateDropdownItems(mMinimumNumerator, mMaximumNumerator));
numeratorSpinner.setSelection(mNumeratorValue - mMinimumNumerator);
numeratorSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
final int newValue = position + mMinimumNumerator;
if (newValue != mNumeratorValue) {
mNumeratorValue = newValue;
persistValues();
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Spinner denominatorSpinner = (Spinner) holder.findViewById(R.id.denominator);
denominatorSpinner.setAdapter(generateDropdownItems(mMinimumDenominator, mMaximumDenominator));
denominatorSpinner.setSelection(mDenominatorValue - mMinimumDenominator);
denominatorSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
final int newValue = position + mMinimumDenominator;
if (newValue != mDenominatorValue) {
mDenominatorValue = newValue;
persistValues();
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Spinner
android:id="@+id/numerator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text=":" />
<Spinner
android:id="@+id/denominator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" />
</LinearLayout>

View file

@ -46,6 +46,7 @@
<string-array name="settings_display_aspect_ratio_names">
<item>Auto (Nativo del juego)</item>
<item>Auto (Match Display)</item>
<item>Custom</item>
<item>4:3</item>
<item>16:9</item>
<item>19:9</item>

View file

@ -46,6 +46,7 @@
<string-array name="settings_display_aspect_ratio_names">
<item>Auto (Game Native)</item>
<item>Auto (Match Display)</item>
<item>Custom</item>
<item>4:3</item>
<item>16:9</item>
<item>19:9</item>

View file

@ -46,6 +46,7 @@
<string-array name="settings_display_aspect_ratio_names">
<item>Auto (Game Native)</item>
<item>Auto (Match Display)</item>
<item>Custom</item>
<item>4:3</item>
<item>16:9</item>
<item>19:9</item>

View file

@ -46,6 +46,7 @@
<string-array name="settings_display_aspect_ratio_names">
<item>Auto (Nativo)</item>
<item>Auto (Corresponder a Janela)</item>
<item>Custom</item>
<item>4:3</item>
<item>16:9</item>
<item>19:9</item>

View file

@ -46,6 +46,7 @@
<string-array name="settings_display_aspect_ratio_names">
<item>Автонастройка (нативно игре)</item>
<item>Автонастройка (под экран)</item>
<item>Custom</item>
<item>4:3</item>
<item>16:9</item>
<item>19:9</item>

View file

@ -90,6 +90,7 @@
<string-array name="settings_display_aspect_ratio_names">
<item>Auto (Game Native)</item>
<item>Auto (Match Display)</item>
<item>Custom</item>
<item>4:3</item>
<item>16:9</item>
<item>19:9</item>
@ -99,6 +100,7 @@
<string-array name="settings_display_aspect_ratio_values">
<item>Auto (Game Native)</item>
<item>Auto (Match Window)</item>
<item>Custom</item>
<item>4:3</item>
<item>16:9</item>
<item>19:9</item>

View file

@ -352,4 +352,6 @@
<string name="settings_disable_widescreen">Disable Widescreen</string>
<string name="settings_cdrom_seek_speedup">CD-ROM Seek Speedup</string>
<string name="settings_summary_cdrom_seek_speedup">Speeds up CD-ROM seeks by the specified factor. May improve loading speeds in some games, at the cost of breaking others.</string>
<string name="settings_custom_aspect_ratio">Custom Aspect Ratio</string>
<string name="settings_summary_custom_aspect_ratio">Used when aspect ratio is set to Custom.</string>
</resources>

View file

@ -34,6 +34,20 @@
app:useSimpleSummaryProvider="true"
app:iconSpaceReserved="false" />
<com.github.stenzek.duckstation.RatioPreference
numeratorKey="Display/CustomAspectRatioNumerator"
defaultNumerator="4"
minimumNumerator="1"
maximumNunerator="100"
denominatorKey="Display/CustomAspectRatioDenominator"
defaultDenominator="3"
minimumDenominator="1"
maximumDenominator="100"
app:title="@string/settings_custom_aspect_ratio"
app:summary="@string/settings_summary_custom_aspect_ratio"
app:useSimpleSummaryProvider="true"
app:iconSpaceReserved="false" />
<ListPreference
app:key="GPU/DownsampleMode"
app:title="@string/settings_downsample_mode"