Revision c820515c
Added by Leszek Koltunski 12 months ago
src/main/java/org/distorted/main/MainActivity.java | ||
---|---|---|
66 | 66 |
private FirebaseAnalytics mFirebaseAnalytics; |
67 | 67 |
private int mCurrentApiVersion; |
68 | 68 |
private String mOldVersion, mCurrVersion; |
69 |
private int mScreenWidth; |
|
69 |
private int mScreenWidth, mScreenHeight;
|
|
70 | 70 |
private TextView mBubbleUpdates; |
71 | 71 |
private int mNumUpdates; |
72 | 72 |
private int mCurrentObject; |
... | ... | |
199 | 199 |
float conv = ((float) dpi/DisplayMetrics.DENSITY_DEFAULT); |
200 | 200 |
|
201 | 201 |
mScreenWidth = (int) (conf.screenWidthDp*conv + 0.5f); |
202 |
mScreenHeight= (int) (conf.screenHeightDp*conv + 0.5f); |
|
202 | 203 |
} |
203 | 204 |
|
204 | 205 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
456 | 457 |
|
457 | 458 |
public void onSettings(View v) |
458 | 459 |
{ |
460 |
int sw = (int)(mScreenWidth*0.7); |
|
461 |
int sh = (int)(mScreenHeight*0.2f); |
|
459 | 462 |
|
463 |
int vw = v.getWidth(); |
|
464 |
|
|
465 |
MainSettingsPopup popup = new MainSettingsPopup(this,mScreenWidth,mScreenHeight); |
|
466 |
popup.displayPopup(this,v,sw,sh,(int)((vw-sw)/2),0); |
|
460 | 467 |
} |
461 | 468 |
|
462 | 469 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
src/main/java/org/distorted/main/MainSettingsPopup.java | ||
---|---|---|
1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
2 |
// Copyright 2023 Leszek Koltunski // |
|
3 |
// // |
|
4 |
// This file is part of Magic Cube. // |
|
5 |
// // |
|
6 |
// Magic Cube is proprietary software licensed under an EULA which you should have received // |
|
7 |
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html // |
|
8 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
9 |
|
|
10 |
package org.distorted.main; |
|
11 |
|
|
12 |
import android.content.Context; |
|
13 |
import android.os.Build; |
|
14 |
import android.util.TypedValue; |
|
15 |
import android.view.Gravity; |
|
16 |
import android.view.LayoutInflater; |
|
17 |
import android.view.View; |
|
18 |
import android.widget.AdapterView; |
|
19 |
import android.widget.ArrayAdapter; |
|
20 |
import android.widget.ListPopupWindow; |
|
21 |
import android.widget.PopupWindow; |
|
22 |
import android.widget.Spinner; |
|
23 |
import android.widget.TextView; |
|
24 |
|
|
25 |
import java.lang.reflect.Field; |
|
26 |
|
|
27 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
28 |
|
|
29 |
public class MainSettingsPopup implements AdapterView.OnItemSelectedListener |
|
30 |
{ |
|
31 |
private static final float MENU_TITLE_SIZE= 0.070f; |
|
32 |
private static final float MENU_TEXT_SIZE = 0.060f; |
|
33 |
|
|
34 |
private final PopupWindow mPopup; |
|
35 |
private static final int[] mLocation = new int[2]; |
|
36 |
private int mCurrMethod; |
|
37 |
|
|
38 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
39 |
// this is supposed to prevent showing the navigational bar when we show the drop down list, |
|
40 |
// but it doesn't quite work... At least not in the emulator. |
|
41 |
// see https://gist.github.com/kakajika/a236ba721a5c0ad3c1446e16a7423a63 |
|
42 |
// |
|
43 |
// EDIT: the bar does not appear on API 34 without the need to call this method. Must have been |
|
44 |
// fixed by Android developers. |
|
45 |
|
|
46 |
public static void avoidSpinnerDropdownFocus(Spinner spinner) |
|
47 |
{ |
|
48 |
try |
|
49 |
{ |
|
50 |
Field listPopupField = Spinner.class.getDeclaredField("mPopup"); |
|
51 |
listPopupField.setAccessible(true); |
|
52 |
Object listPopup = listPopupField.get(spinner); |
|
53 |
|
|
54 |
if( listPopup instanceof ListPopupWindow ) |
|
55 |
{ |
|
56 |
Field popupField = ListPopupWindow.class.getDeclaredField("mPopup"); |
|
57 |
popupField.setAccessible(true); |
|
58 |
Object popup = popupField.get((ListPopupWindow) listPopup); |
|
59 |
|
|
60 |
if( popup instanceof PopupWindow ) |
|
61 |
{ |
|
62 |
((PopupWindow) popup).setFocusable(false); |
|
63 |
} |
|
64 |
} |
|
65 |
} |
|
66 |
catch (NoSuchFieldException | IllegalAccessException ignored) |
|
67 |
{ |
|
68 |
|
|
69 |
} |
|
70 |
} |
|
71 |
|
|
72 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
73 |
|
|
74 |
MainSettingsPopup(MainActivity act, int width, int height) |
|
75 |
{ |
|
76 |
// due to bugs in Android API <=25, a Spinner inside a PopupWindow will crash once you click on it. |
|
77 |
// solution: on those APIs, use a special Spinner in dialog mode (this does not crash) |
|
78 |
int id = android.os.Build.VERSION.SDK_INT <= 25 ? R.layout.settings_popup_android25 : R.layout.settings_popup; |
|
79 |
|
|
80 |
LayoutInflater layoutInflater = (LayoutInflater) act.getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
|
81 |
final View layout = layoutInflater.inflate(id, null); |
|
82 |
|
|
83 |
mPopup = new PopupWindow(act); |
|
84 |
mPopup.setContentView(layout); |
|
85 |
mPopup.setFocusable(true); |
|
86 |
|
|
87 |
int titleSize = (int)(MENU_TITLE_SIZE*width); |
|
88 |
int textSize = (int)(MENU_TEXT_SIZE*width); |
|
89 |
|
|
90 |
TextView title = layout.findViewById(R.id.sortTitle); |
|
91 |
title.setTextSize(TypedValue.COMPLEX_UNIT_PX, titleSize); |
|
92 |
TextView text = layout.findViewById(R.id.sortText); |
|
93 |
text.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); |
|
94 |
|
|
95 |
Spinner actSpinner = layout.findViewById(R.id.sortMethod); |
|
96 |
actSpinner.setOnItemSelectedListener(this); |
|
97 |
|
|
98 |
mCurrMethod = -1; |
|
99 |
|
|
100 |
String[] actNames = { "Classic" , "Category" , "Difficulty", "Author" , "Year" }; |
|
101 |
ArrayAdapter<String> actAdapter = new ArrayAdapter<>(act, android.R.layout.simple_spinner_item, actNames); |
|
102 |
actAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); |
|
103 |
actSpinner.setAdapter(actAdapter); |
|
104 |
} |
|
105 |
|
|
106 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
107 |
// work around lame bugs in Android's version <= 10 pop-up and split-screen modes |
|
108 |
|
|
109 |
public void displayPopup(MainActivity act, View view, int w, int h, int xoff, int yoff) |
|
110 |
{ |
|
111 |
View v = mPopup.getContentView(); |
|
112 |
v.setSystemUiVisibility(MainActivity.FLAGS); |
|
113 |
|
|
114 |
View topLayout = act.findViewById(R.id.relativeLayout); |
|
115 |
|
|
116 |
boolean isFullScreen; |
|
117 |
|
|
118 |
if( topLayout!=null ) |
|
119 |
{ |
|
120 |
topLayout.getLocationOnScreen(mLocation); |
|
121 |
isFullScreen = (mLocation[1]==0); |
|
122 |
} |
|
123 |
else |
|
124 |
{ |
|
125 |
isFullScreen = true; |
|
126 |
} |
|
127 |
|
|
128 |
try |
|
129 |
{ |
|
130 |
// if on Android 11 or we are fullscreen |
|
131 |
if (Build.VERSION_CODES.R<=Build.VERSION.SDK_INT || isFullScreen ) |
|
132 |
{ |
|
133 |
mPopup.showAsDropDown(view, xoff, yoff, Gravity.CENTER); |
|
134 |
mPopup.update(view, w, h); |
|
135 |
} |
|
136 |
else // Android 10 or below in pop-up mode or split-screen mode |
|
137 |
{ |
|
138 |
view.getLocationOnScreen(mLocation); |
|
139 |
int width = view.getWidth(); |
|
140 |
int height = view.getHeight(); |
|
141 |
int x = mLocation[0]+(width-w)/2; |
|
142 |
int y = mLocation[1]+height+yoff; |
|
143 |
mPopup.showAsDropDown(view); |
|
144 |
mPopup.update(x,y,w,h); |
|
145 |
} |
|
146 |
} |
|
147 |
catch( IllegalArgumentException iae ) |
|
148 |
{ |
|
149 |
// ignore, this means window is 'not attached to window manager' - |
|
150 |
// which most probably is because we are already exiting the app. |
|
151 |
} |
|
152 |
} |
|
153 |
|
|
154 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
155 |
|
|
156 |
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) |
|
157 |
{ |
|
158 |
if( parent.getId()==R.id.sortMethod && mCurrMethod!=pos ) |
|
159 |
{ |
|
160 |
mCurrMethod = pos; |
|
161 |
} |
|
162 |
} |
|
163 |
|
|
164 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
165 |
|
|
166 |
public void onNothingSelected(AdapterView<?> parent) |
|
167 |
{ |
|
168 |
|
|
169 |
} |
|
170 |
} |
|
171 |
|
src/main/res/layout/settings_popup.xml | ||
---|---|---|
1 |
<?xml version="1.0" encoding="utf-8"?> |
|
2 |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
|
3 |
android:id="@+id/settingsGrid" |
|
4 |
android:layout_width="wrap_content" |
|
5 |
android:layout_height="wrap_content" |
|
6 |
android:gravity="center" |
|
7 |
android:orientation="vertical"> |
|
8 |
|
|
9 |
<TextView |
|
10 |
android:id="@+id/sortTitle" |
|
11 |
android:layout_width="match_parent" |
|
12 |
android:layout_height="wrap_content" |
|
13 |
android:text="@string/settings_title" |
|
14 |
android:background="@color/light_grey" |
|
15 |
android:gravity="center"/> |
|
16 |
|
|
17 |
<LinearLayout |
|
18 |
android:layout_width="wrap_content" |
|
19 |
android:layout_height="match_parent" |
|
20 |
android:gravity="center" |
|
21 |
android:orientation="horizontal"> |
|
22 |
|
|
23 |
<TextView |
|
24 |
android:id="@+id/sortText" |
|
25 |
android:layout_marginStart="5dp" |
|
26 |
android:layout_marginEnd="25dp" |
|
27 |
android:layout_width="wrap_content" |
|
28 |
android:layout_height="match_parent" |
|
29 |
android:text="@string/sort_by" |
|
30 |
android:gravity="start|center_vertical"/> |
|
31 |
|
|
32 |
<Spinner |
|
33 |
android:id="@+id/sortMethod" |
|
34 |
android:layout_width="wrap_content" |
|
35 |
android:layout_height="match_parent" |
|
36 |
android:gravity="end|center_vertical"/> |
|
37 |
|
|
38 |
</LinearLayout> |
|
39 |
</LinearLayout> |
src/main/res/layout/settings_popup_android25.xml | ||
---|---|---|
1 |
<?xml version="1.0" encoding="utf-8"?> |
|
2 |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
|
3 |
android:id="@+id/settingsGrid" |
|
4 |
android:layout_width="wrap_content" |
|
5 |
android:layout_height="wrap_content" |
|
6 |
android:gravity="center" |
|
7 |
android:orientation="vertical"> |
|
8 |
|
|
9 |
<TextView |
|
10 |
android:id="@+id/sortTitle" |
|
11 |
android:layout_width="match_parent" |
|
12 |
android:layout_height="wrap_content" |
|
13 |
android:text="@string/settings_title" |
|
14 |
android:background="@color/light_grey" |
|
15 |
android:gravity="center"/> |
|
16 |
|
|
17 |
<LinearLayout |
|
18 |
android:layout_width="wrap_content" |
|
19 |
android:layout_height="match_parent" |
|
20 |
android:gravity="center" |
|
21 |
android:orientation="horizontal"> |
|
22 |
|
|
23 |
<TextView |
|
24 |
android:id="@+id/sortText" |
|
25 |
android:layout_marginStart="5dp" |
|
26 |
android:layout_marginEnd="25dp" |
|
27 |
android:layout_width="wrap_content" |
|
28 |
android:layout_height="match_parent" |
|
29 |
android:text="@string/sort_by" |
|
30 |
android:gravity="start|center_vertical"/> |
|
31 |
|
|
32 |
<Spinner |
|
33 |
android:id="@+id/sortMethod" |
|
34 |
android:layout_width="wrap_content" |
|
35 |
android:layout_height="match_parent" |
|
36 |
android:spinnerMode="dialog" |
|
37 |
android:gravity="end|center_vertical"/> |
|
38 |
|
|
39 |
</LinearLayout> |
|
40 |
</LinearLayout> |
src/main/res/values-de/strings.xml | ||
---|---|---|
53 | 53 |
<string name="contact">Kontakt</string> |
54 | 54 |
<string name="email">Melden Sie einen Fehler, schlagen Sie eine Funktion vor:</string> |
55 | 55 |
<string name="exit_app">App beenden?</string> |
56 |
<string name="sort_by">Ordnung</string> |
|
57 |
<string name="settings_title">Einstellungen</string> |
|
56 | 58 |
|
57 | 59 |
<string name="object_solver">Löser</string> |
58 | 60 |
<string name="object_pattern">Muster</string> |
src/main/res/values-es/strings.xml | ||
---|---|---|
53 | 53 |
<string name="contact">Contacto</string> |
54 | 54 |
<string name="email">Reportar un error, sugerir una función:</string> |
55 | 55 |
<string name="exit_app">¿Salir de la aplicación?</string> |
56 |
<string name="sort_by">Ordenar</string> |
|
57 |
<string name="settings_title">Ajustes</string> |
|
56 | 58 |
|
57 | 59 |
<string name="object_solver">Solucionador</string> |
58 | 60 |
<string name="object_pattern">Patrones</string> |
src/main/res/values-fr/strings.xml | ||
---|---|---|
53 | 53 |
<string name="contact">Contactez-nous</string> |
54 | 54 |
<string name="email">Signaler un bug, suggérer une fonctionnalité :</string> |
55 | 55 |
<string name="exit_app">Quitter l\'application ?</string> |
56 |
<string name="sort_by">Trier par</string> |
|
57 |
<string name="settings_title">Paramètres</string> |
|
56 | 58 |
|
57 | 59 |
<string name="object_solver">Solveur</string> |
58 | 60 |
<string name="object_pattern">Motifs</string> |
src/main/res/values-ja/strings.xml | ||
---|---|---|
53 | 53 |
<string name="contact">お問い合わせ</string> |
54 | 54 |
<string name="email">バグを報告し、機能を提案してください:</string> |
55 | 55 |
<string name="exit_app">アプリを終了しますか?</string> |
56 |
<string name="sort_by">並べ替え</string> |
|
57 |
<string name="settings_title">設定</string> |
|
56 | 58 |
|
57 | 59 |
<string name="object_solver">ソルバー</string> |
58 | 60 |
<string name="object_pattern">パターン</string> |
src/main/res/values-ko/strings.xml | ||
---|---|---|
53 | 53 |
<string name="contact">문의하기</string> |
54 | 54 |
<string name="email">버그 신고, 기능 제안:</string> |
55 | 55 |
<string name="exit_app">앱을 종료하시겠습니까?</string> |
56 |
<string name="sort_by">정렬 기준</string> |
|
57 |
<string name="settings_title">설정</string> |
|
56 | 58 |
|
57 | 59 |
<string name="object_solver">솔버</string> |
58 | 60 |
<string name="object_pattern">패턴</string> |
src/main/res/values-pl/strings.xml | ||
---|---|---|
53 | 53 |
<string name="contact">Kontakt</string> |
54 | 54 |
<string name="email">Zaraportuj błąd, zadaj pytanie:</string> |
55 | 55 |
<string name="exit_app">Wyjść z apki?</string> |
56 |
<string name="sort_by">Sortuj po</string> |
|
57 |
<string name="settings_title">Ustawienia</string> |
|
56 | 58 |
|
57 | 59 |
<string name="object_solver">Rozwiązywacz</string> |
58 | 60 |
<string name="object_pattern">Wzory</string> |
src/main/res/values-ru/strings.xml | ||
---|---|---|
53 | 53 |
<string name="contact">Контакт</string> |
54 | 54 |
<string name="email">Сообщить об ошибке, задать вопрос:</string> |
55 | 55 |
<string name="exit_app">Выйти из приложения?</string> |
56 |
<string name="sort_by">Группа по</string> |
|
57 |
<string name="settings_title">Настройки</string> |
|
56 | 58 |
|
57 | 59 |
<string name="object_solver">Решатель</string> |
58 | 60 |
<string name="object_pattern">Узоры</string> |
src/main/res/values-zh-rCN/strings.xml | ||
---|---|---|
53 | 53 |
<string name="contact">联系我们</string> |
54 | 54 |
<string name="email">报告错误,提出问题:</string> |
55 | 55 |
<string name="exit_app">退出应用程序?</string> |
56 |
<string name="sort_by">排序方式</string> |
|
57 |
<string name="settings_title">设置</string> |
|
56 | 58 |
|
57 | 59 |
<string name="object_solver">求解器</string> |
58 | 60 |
<string name="object_pattern">图案</string> |
src/main/res/values-zh-rTW/strings.xml | ||
---|---|---|
53 | 53 |
<string name="contact">聯繫我們</string> |
54 | 54 |
<string name="email">报告错误,提出问题:</string> |
55 | 55 |
<string name="exit_app">退出應用程式?</string> |
56 |
<string name="sort_by">排序方式</string> |
|
57 |
<string name="settings_title">設定</string> |
|
56 | 58 |
|
57 | 59 |
<string name="object_solver">求解器</string> |
58 | 60 |
<string name="object_pattern">圖案</string> |
src/main/res/values/strings.xml | ||
---|---|---|
55 | 55 |
<string name="contact">Contact us</string> |
56 | 56 |
<string name="email">Report a bug, suggest a feature:</string> |
57 | 57 |
<string name="exit_app">Exit App?</string> |
58 |
<string name="sort_by">Sort by</string> |
|
59 |
<string name="settings_title">Settings</string> |
|
58 | 60 |
|
59 | 61 |
<string name="stars">Stars</string> |
60 | 62 |
<string name="scores">High Scores</string> |
Also available in: Unified diff
Progress with sorting the objects by various criteria.