Project

General

Profile

Download (7.33 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / main / MainSettingsPopup.java @ a5972f92

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.content.res.Resources;
14
import android.os.Build;
15
import android.util.TypedValue;
16
import android.view.Gravity;
17
import android.view.LayoutInflater;
18
import android.view.View;
19
import android.widget.AdapterView;
20
import android.widget.ArrayAdapter;
21
import android.widget.ListPopupWindow;
22
import android.widget.PopupWindow;
23
import android.widget.Spinner;
24
import android.widget.TextView;
25

    
26
import java.lang.ref.WeakReference;
27
import java.lang.reflect.Field;
28

    
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30

    
31
public class MainSettingsPopup implements AdapterView.OnItemSelectedListener
32
  {
33
  public static final int SORT_CLASSIC    = 0;
34
  public static final int SORT_SHAPE      = 1;
35
  public static final int SORT_DIFFICULTY = 2;
36
  public static final int SORT_AUTHOR     = 3;
37
  public static final int SORT_YEAR       = 4;
38

    
39
  public static final int SORT_DEFAULT    = SORT_SHAPE;
40

    
41
  private static final float MENU_TITLE_SIZE= 0.070f;
42
  private static final float MENU_TEXT_SIZE = 0.060f;
43
  private static final int[] mLocation = new int[2];
44

    
45
  private final PopupWindow mPopup;
46
  private final WeakReference<MainActivity> mAct;
47
  private int mCurrMethod;
48
  private String[] mSortNames;
49

    
50
///////////////////////////////////////////////////////////////////////////////////////////////////
51
// this is supposed to prevent showing the navigational bar when we show the drop down list,
52
// but it doesn't quite work... At least not in the emulator.
53
// see https://gist.github.com/kakajika/a236ba721a5c0ad3c1446e16a7423a63
54
//
55
// EDIT: the bar does not appear on API 34 without the need to call this method. Must have been
56
// fixed by Android developers.
57

    
58
  public static void avoidSpinnerDropdownFocus(Spinner spinner)
59
    {
60
    try
61
      {
62
      Field listPopupField = Spinner.class.getDeclaredField("mPopup");
63
      listPopupField.setAccessible(true);
64
      Object listPopup = listPopupField.get(spinner);
65

    
66
      if( listPopup instanceof ListPopupWindow )
67
        {
68
        Field popupField = ListPopupWindow.class.getDeclaredField("mPopup");
69
        popupField.setAccessible(true);
70
        Object popup = popupField.get((ListPopupWindow) listPopup);
71

    
72
        if( popup instanceof PopupWindow )
73
          {
74
          ((PopupWindow) popup).setFocusable(false);
75
          }
76
        }
77
      }
78
    catch (NoSuchFieldException | IllegalAccessException ignored)
79
      {
80

    
81
      }
82
    }
83

    
84
///////////////////////////////////////////////////////////////////////////////////////////////////
85

    
86
  MainSettingsPopup(MainActivity act, int sortMethod, int width, int height)
87
    {
88
    mAct = new WeakReference<>(act);
89

    
90
    // due to bugs in Android API <=25, a Spinner inside a PopupWindow will crash once you click on it.
91
    // solution: on those APIs, use a special Spinner in dialog mode (this does not crash)
92
    int id = android.os.Build.VERSION.SDK_INT <= 25 ? R.layout.settings_popup_android25 : R.layout.settings_popup;
93

    
94
    LayoutInflater layoutInflater = (LayoutInflater) act.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
95
    final View layout = layoutInflater.inflate(id, null);
96

    
97
    mPopup = new PopupWindow(act);
98
    mPopup.setContentView(layout);
99
    mPopup.setFocusable(true);
100

    
101
    int titleSize = (int)(MENU_TITLE_SIZE*width);
102
    int textSize  = (int)(MENU_TEXT_SIZE*width);
103

    
104
    TextView title = layout.findViewById(R.id.sortTitle);
105
    title.setTextSize(TypedValue.COMPLEX_UNIT_PX, titleSize);
106
    TextView text = layout.findViewById(R.id.sortText);
107
    text.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
108

    
109
    Spinner actSpinner  = layout.findViewById(R.id.sortMethod);
110
    actSpinner.setOnItemSelectedListener(this);
111

    
112
    mCurrMethod = sortMethod;
113
    buildSortOptions(act);
114

    
115
    ArrayAdapter<String> actAdapter = new ArrayAdapter<>(act, android.R.layout.simple_spinner_item, mSortNames);
116
    actAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
117
    actSpinner.setAdapter(actAdapter);
118

    
119
    if( sortMethod>=0 && sortMethod<mSortNames.length ) actSpinner.setSelection(sortMethod);
120
    }
121

    
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123

    
124
  private void buildSortOptions(MainActivity act)
125
    {
126
    Resources res = act.getResources();
127
    mSortNames = new String[5];
128

    
129
    mSortNames[0] = res.getString(R.string.sort_classic);
130
    mSortNames[1] = res.getString(R.string.sort_shape);
131
    mSortNames[2] = res.getString(R.string.sort_difficulty);
132
    mSortNames[3] = res.getString(R.string.sort_author);
133
    mSortNames[4] = res.getString(R.string.sort_year);
134
    }
135

    
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137
// work around lame bugs in Android's version <= 10 pop-up and split-screen modes
138

    
139
  public void displayPopup(MainActivity act, View view, int w, int h, int xoff, int yoff)
140
    {
141
    View v = mPopup.getContentView();
142
    v.setSystemUiVisibility(MainActivity.FLAGS);
143

    
144
    View topLayout = act.findViewById(R.id.relativeLayout);
145

    
146
    boolean isFullScreen;
147

    
148
    if( topLayout!=null )
149
      {
150
      topLayout.getLocationOnScreen(mLocation);
151
      isFullScreen = (mLocation[1]==0);
152
      }
153
    else
154
      {
155
      isFullScreen = true;
156
      }
157

    
158
    try
159
      {
160
      // if on Android 11 or we are fullscreen
161
      if (Build.VERSION_CODES.R<=Build.VERSION.SDK_INT || isFullScreen )
162
        {
163
        mPopup.showAsDropDown(view, xoff, yoff, Gravity.CENTER);
164
        mPopup.update(view, w, h);
165
        }
166
      else  // Android 10 or below in pop-up mode or split-screen mode
167
        {
168
        view.getLocationOnScreen(mLocation);
169
        int width  = view.getWidth();
170
        int height = view.getHeight();
171
        int x = mLocation[0]+(width-w)/2;
172
        int y = mLocation[1]+height+yoff;
173
        mPopup.showAsDropDown(view);
174
        mPopup.update(x,y,w,h);
175
        }
176
      }
177
    catch( IllegalArgumentException iae )
178
      {
179
      // ignore, this means window is 'not attached to window manager' -
180
      // which most probably is because we are already exiting the app.
181
      }
182
    }
183

    
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185

    
186
  public void onItemSelected(AdapterView<?> parent, View view, int pos, long id)
187
    {
188
    if( parent.getId()==R.id.sortMethod && mCurrMethod!=pos )
189
      {
190
      mCurrMethod = pos;
191
      MainActivity act = mAct.get();
192
      act.sortObjectsBy(pos);
193
      mPopup.dismiss();
194
      }
195
    }
196

    
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198

    
199
  public void onNothingSelected(AdapterView<?> parent)
200
    {
201

    
202
    }
203
  }
204

    
(4-4/4)