Project

General

Profile

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

magiccube / src / main / java / org / distorted / main / MainSettingsPopup.java @ 417d51b6

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.ref.WeakReference;
26
import java.lang.reflect.Field;
27

    
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29

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

    
38
  public static final int SORT_DEFAULT    = SORT_CLASSIC;
39

    
40
  private static final String[] mSortNames = { "Classic" , "Category" , "Difficulty", "Author" , "Year" };
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

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

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

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

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

    
80
      }
81
    }
82

    
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84

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

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

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

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

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

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

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

    
111
    mCurrMethod = -1;
112

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

    
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119
// work around lame bugs in Android's version <= 10 pop-up and split-screen modes
120

    
121
  public void displayPopup(MainActivity act, View view, int w, int h, int xoff, int yoff)
122
    {
123
    View v = mPopup.getContentView();
124
    v.setSystemUiVisibility(MainActivity.FLAGS);
125

    
126
    View topLayout = act.findViewById(R.id.relativeLayout);
127

    
128
    boolean isFullScreen;
129

    
130
    if( topLayout!=null )
131
      {
132
      topLayout.getLocationOnScreen(mLocation);
133
      isFullScreen = (mLocation[1]==0);
134
      }
135
    else
136
      {
137
      isFullScreen = true;
138
      }
139

    
140
    try
141
      {
142
      // if on Android 11 or we are fullscreen
143
      if (Build.VERSION_CODES.R<=Build.VERSION.SDK_INT || isFullScreen )
144
        {
145
        mPopup.showAsDropDown(view, xoff, yoff, Gravity.CENTER);
146
        mPopup.update(view, w, h);
147
        }
148
      else  // Android 10 or below in pop-up mode or split-screen mode
149
        {
150
        view.getLocationOnScreen(mLocation);
151
        int width  = view.getWidth();
152
        int height = view.getHeight();
153
        int x = mLocation[0]+(width-w)/2;
154
        int y = mLocation[1]+height+yoff;
155
        mPopup.showAsDropDown(view);
156
        mPopup.update(x,y,w,h);
157
        }
158
      }
159
    catch( IllegalArgumentException iae )
160
      {
161
      // ignore, this means window is 'not attached to window manager' -
162
      // which most probably is because we are already exiting the app.
163
      }
164
    }
165

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

    
168
  public void onItemSelected(AdapterView<?> parent, View view, int pos, long id)
169
    {
170
    if( parent.getId()==R.id.sortMethod && mCurrMethod!=pos )
171
      {
172
      mCurrMethod = pos;
173
      MainActivity act = mAct.get();
174
      act.sortObjectsBy(pos);
175
      }
176
    }
177

    
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179

    
180
  public void onNothingSelected(AdapterView<?> parent)
181
    {
182

    
183
    }
184
  }
185

    
(4-4/4)