Project

General

Profile

« Previous | Next » 

Revision c820515c

Added by Leszek Koltunski 9 months ago

Progress with sorting the objects by various criteria.

View differences:

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