Remove the last AsyncTask objects

Julien LepillerSun Jun 26 16:49:17+0200 2022

23e18c4

Remove the last AsyncTask objects

.idea/misc.xml

77
        <entry key="app/src/main/res/drawable/ic_pitch.xml" value="0.1535" />
88
        <entry key="app/src/main/res/drawable/ic_rad.xml" value="0.1535" />
99
        <entry key="app/src/main/res/drawable/ic_reading.xml" value="0.1535" />
10+
        <entry key="app/src/main/res/layout/activity_main.xml" value="0.2078125" />
11+
        <entry key="app/src/main/res/layout/content_main.xml" value="0.2078125" />
12+
        <entry key="app/src/main/res/layout/content_radicals.xml" value="0.2078125" />
1013
        <entry key="app/src/main/res/layout/fragment_results.xml" value="0.2078125" />
1114
        <entry key="app/src/main/res/layout/layout_result.xml" value="0.2078125" />
1215
        <entry key="app/src/main/res/xml/preferences.xml" value="0.2078125" />

app/src/main/java/eu/lepiller/nani/MainActivity.java

88
99
import androidx.appcompat.app.AppCompatActivity;
1010
import androidx.appcompat.widget.Toolbar;
11+
import androidx.fragment.app.FragmentContainerView;
12+
import androidx.lifecycle.ViewModelProvider;
1113
import androidx.preference.PreferenceManager;
1214
import androidx.viewpager2.widget.ViewPager2;
1315

3739
import eu.lepiller.nani.result.Result;
3840
3941
import static java.lang.Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS;
42+
import static eu.lepiller.nani.RadicalSelectorFragment.*;
4043
4144
public class MainActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
4245
    private LinearLayout result_layout;
4346
    private TextView feedback_text;
4447
    private SearchView search_form;
45-
    private RadicalSelectorView radical_selector;
48+
    private FragmentContainerView radical_selector;
4649
    private String readingStyle = "furigana";
4750
    private String pitchStyle = "box";
4851
    private String intentSearch = null;

9396
        ).attach();
9497
9598
        try {
96-
            radical_selector.setRadSize(radSizePref);
97-
            radical_selector.setDictionary(DictionaryFactory.getRadicalDictionary(getApplicationContext()));
99+
            RadicalSelectorFragment.RadicalSelectorViewModel viewModel = new ViewModelProvider(this).get(RadicalSelectorFragment.RadicalSelectorViewModel.class);
100+
            viewModel.setPreferences(new RadicalSelectorProperties(DictionaryFactory.getRadicalDictionary(getApplicationContext()), radSizePref));
98101
        } catch (NoDictionaryException e) {
99102
            e.printStackTrace();
100103
        }

110113
            }
111114
        });
112115
113-
        radical_selector.setOnCloseEventListener(v -> closeRadicals());
114-
115-
        radical_selector.setOnClickEventListener(v -> {
116-
            String k = ((Button)v).getText().toString();
117-
            search_form.setQuery(search_form.getQuery() + k, false);
118-
        });
119-
120-
        radical_selector.setOnHelpEventListener(v -> {
121-
            Intent intent = new Intent(MainActivity.this, HelpRadicalActivity.class);
122-
            startActivity(intent);
116+
        getSupportFragmentManager().setFragmentResultListener("selectRadicals", this, (requestKey, bundle) -> {
117+
            int event = bundle.getInt("event");
118+
            Log.d(TAG, "received result: " + event);
119+
            if(event == CLOSE_EVENT) {
120+
                closeRadicals();
121+
            } else if(event == HELP_EVENT) {
122+
                Intent intent = new Intent(MainActivity.this, HelpRadicalActivity.class);
123+
                startActivity(intent);
124+
            } else if(event == KANJI_EVENT) {
125+
                String k = bundle.getString("kanji");
126+
                search_form.setQuery(search_form.getQuery() + k, false);
127+
            }
123128
        });
124129
125130
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {

138143
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
139144
        Log.d("MAIN", key + " preference changed.");
140145
        if(key.compareTo(SettingsActivity.KEY_PREF_RAD_SIZE) == 0) {
141-
            radical_selector.setRadSize(getRadSizePref(sharedPreferences));
146+
            RadicalSelectorFragment.RadicalSelectorViewModel viewModel = new ViewModelProvider(this).get(RadicalSelectorFragment.RadicalSelectorViewModel.class);
147+
            viewModel.setPreferences(new RadicalSelectorProperties(null, getRadSizePref(sharedPreferences)));
142148
        } else if(key.compareTo(SettingsActivity.KEY_PREF_READING_STYLE) == 0) {
143149
            readingStyle = getReadingStylePref(sharedPreferences);
144150
            pagerAdapter.setReadingStyle(readingStyle);

409415
    @Override
410416
    public void onBackPressed() {
411417
        if(radical_selector.getVisibility() == View.VISIBLE) {
412-
            radical_selector.close();
418+
            closeRadicals();
413419
        } else {
414420
            super.onBackPressed();
415421
        }

app/src/main/java/eu/lepiller/nani/RadicalSelectorFragment.java unknown status 1

1+
package eu.lepiller.nani;
2+
3+
import static android.view.View.TEXT_ALIGNMENT_CENTER;
4+
5+
import android.app.Activity;
6+
import android.os.Build;
7+
import android.os.Bundle;
8+
import android.util.Log;
9+
import android.util.Pair;
10+
import android.view.View;
11+
import android.widget.Button;
12+
import android.widget.LinearLayout;
13+
import android.widget.TextView;
14+
import android.widget.ToggleButton;
15+
16+
import androidx.fragment.app.Fragment;
17+
import androidx.lifecycle.LiveData;
18+
import androidx.lifecycle.MutableLiveData;
19+
import androidx.lifecycle.ViewModel;
20+
import androidx.lifecycle.ViewModelProvider;
21+
22+
import com.google.android.flexbox.FlexWrap;
23+
import com.google.android.flexbox.FlexboxLayout;
24+
25+
import java.text.NumberFormat;
26+
import java.util.ArrayList;
27+
import java.util.Collections;
28+
import java.util.List;
29+
import java.util.Map;
30+
import java.util.Set;
31+
32+
import eu.lepiller.nani.dictionary.IncompatibleFormatException;
33+
import eu.lepiller.nani.dictionary.RadicalDict;
34+
35+
public class RadicalSelectorFragment extends Fragment {
36+
    public static final int CLOSE_EVENT = 1;
37+
    public static final int HELP_EVENT = 2;
38+
    public static final int KANJI_EVENT = 3;
39+
40+
    private LinearLayout kanji_row1, kanji_row2;
41+
    private LinearLayout radical_table;
42+
43+
    final List<String> selected = new ArrayList<>();
44+
45+
    RadicalDict dictionary;
46+
    private int radSize = 122;
47+
48+
    public RadicalSelectorFragment() {
49+
        super(R.layout.content_radicals);
50+
    }
51+
52+
    @Override
53+
    public void onViewStateRestored(Bundle bundle) {
54+
        super.onViewStateRestored(bundle);
55+
56+
        if (getView() == null)
57+
            return;
58+
59+
        Button close_button = getView().findViewById(R.id.close_button);
60+
        Button help_button = getView().findViewById(R.id.help_button);
61+
        kanji_row1 = getView().findViewById(R.id.kanji_row1);
62+
        kanji_row2 = getView().findViewById(R.id.kanji_row2);
63+
        radical_table = getView().findViewById(R.id.radical_table);
64+
65+
        close_button.setOnClickListener((View v) -> {
66+
            Bundle result = new Bundle();
67+
            result.putInt("event", CLOSE_EVENT);
68+
            getParentFragmentManager().setFragmentResult("selectRadicals", result);
69+
        });
70+
71+
        help_button.setOnClickListener((View v) -> {
72+
            Bundle result = new Bundle();
73+
            result.putInt("event", HELP_EVENT);
74+
            getParentFragmentManager().setFragmentResult("selectRadicals", result);
75+
        });
76+
77+
        RadicalSelectorViewModel viewModel = new ViewModelProvider(requireActivity()).get(RadicalSelectorViewModel.class);
78+
        viewModel.getPreferences().observe(getViewLifecycleOwner(), pref -> {
79+
            if (pref.dictionary != null) {
80+
                setDictionary(pref.dictionary);
81+
            }
82+
            if (pref.radSize != null) {
83+
                setRadSize(radSize);
84+
            }
85+
        });
86+
    }
87+
88+
    private final Runnable dictionarySearch = () -> {
89+
        Pair<Map<Integer, List<String>>, Set<String>> result;
90+
        try {
91+
            result = new Pair<>(dictionary.match(selected), dictionary.availableRadicals(selected));
92+
        } catch (IncompatibleFormatException e) {
93+
            e.printStackTrace();
94+
            return;
95+
        }
96+
        Activity activity = getActivity();
97+
        if(activity == null)
98+
            return;
99+
100+
        activity.runOnUiThread(() -> {
101+
            Map<Integer, List<String>> kanji = result.first;
102+
            Set<String> availableRadicals = result.second;
103+
104+
            updateSelection(kanji);
105+
            updateRadicals(availableRadicals);
106+
        });
107+
    };
108+
109+
    private final Runnable dictionaryUpdate = () -> {
110+
        Map<Integer, List<String>> radicals;
111+
        try {
112+
            radicals = dictionary.getAllRadicals();
113+
        } catch (IncompatibleFormatException e) {
114+
            e.printStackTrace();
115+
            return;
116+
        }
117+
118+
        Activity activity = getActivity();
119+
        if(activity == null)
120+
            return;
121+
122+
        activity.runOnUiThread(() -> createButtons(radicals));
123+
    };
124+
125+
    public static class RadicalSelectorProperties {
126+
        RadicalSelectorProperties(RadicalDict d, int s) {
127+
            this.dictionary = d;
128+
            this.radSize = s;
129+
        }
130+
        public RadicalDict dictionary;
131+
        public Integer radSize;
132+
    }
133+
134+
    public static class RadicalSelectorViewModel extends ViewModel {
135+
        private final MutableLiveData<RadicalSelectorProperties> preferences = new MutableLiveData<>();
136+
        public void setPreferences(RadicalSelectorProperties item) {
137+
            preferences.setValue(item);
138+
        }
139+
        public LiveData<RadicalSelectorProperties> getPreferences() {
140+
            return preferences;
141+
        }
142+
    }
143+
144+
    public void setDictionary(RadicalDict dict) {
145+
        dictionary = dict;
146+
        new Thread(dictionaryUpdate).start();
147+
    }
148+
149+
    public void setRadSize(int size) {
150+
        radSize = size;
151+
        resizeRadicals();
152+
    }
153+
154+
    public int getRadFontSize() {
155+
        return radSize / 8;
156+
    }
157+
158+
    private void createButtons(Map<Integer, List<String>> radicals) {
159+
        if(radicals == null)
160+
            return;
161+
162+
        if(getContext() == null)
163+
            return;
164+
165+
        ArrayList<Integer> strokes = new ArrayList<>(radicals.keySet());
166+
        Collections.sort(strokes);
167+
        for (int stroke : strokes) {
168+
            TextView strokeView = new TextView(getContext());
169+
            NumberFormat nf = NumberFormat.getInstance();
170+
            strokeView.setText(nf.format(stroke));
171+
            radical_table.addView(strokeView);
172+
173+
            FlexboxLayout box = new FlexboxLayout(getContext());
174+
            radical_table.addView(box);
175+
176+
            List<String> lst = radicals.get(stroke);
177+
            if(lst == null)
178+
                continue;
179+
180+
            for (final String radical : lst) {
181+
                ToggleButton radicalButton = new ToggleButton(getContext());
182+
                radicalButton.setTextOff(radical);
183+
                radicalButton.setTextOn(radical);
184+
                radicalButton.setText(radical);
185+
                radicalButton.setTextSize(getRadFontSize());
186+
                radicalButton.setLayoutParams(new FlexboxLayout.LayoutParams(radSize, radSize));
187+
188+
                radicalButton.setOnClickListener(v -> {
189+
                    boolean checked = ((ToggleButton) v).isChecked();
190+
                    if (checked) {
191+
                        selected.add(radical);
192+
                    } else {
193+
                        selected.remove(radical);
194+
                    }
195+
196+
                    new Thread(dictionarySearch).start();
197+
                });
198+
                box.addView(radicalButton);
199+
            }
200+
201+
            box.setFlexWrap(FlexWrap.WRAP);
202+
            box.invalidate();
203+
        }
204+
    }
205+
206+
    private void updateRadicals(Set<String> available) {
207+
        Log.v("SELECTOR", Integer.toString(radical_table.getChildCount()));
208+
        for(int row = 0; row < radical_table.getChildCount(); row++) {
209+
            View r = radical_table.getChildAt(row);
210+
            if(r instanceof FlexboxLayout) {
211+
                for (int col = 0; col < ((FlexboxLayout) r).getChildCount(); col++) {
212+
                    View child = ((FlexboxLayout) r).getChildAt(col);
213+
                    if (child instanceof ToggleButton) {
214+
                        child.setEnabled(available == null || available.contains(((ToggleButton) child).getText().toString()));
215+
                    }
216+
                }
217+
            }
218+
        }
219+
    }
220+
221+
    public void updateSelection(Map<Integer, List<String>> kanji) {
222+
        LinearLayout row = kanji_row1;
223+
        kanji_row1.removeAllViews();
224+
        kanji_row2.removeAllViews();
225+
226+
        if(kanji == null)
227+
            return;
228+
229+
        int total = 0;
230+
        int number = 0;
231+
        for (int stroke : kanji.keySet()) {
232+
            List<String> s = kanji.get(stroke);
233+
            if(s != null)
234+
                total += s.size();
235+
        }
236+
        for (int stroke : kanji.keySet()) {
237+
            TextView strokeView = new TextView(getContext());
238+
            NumberFormat nf = NumberFormat.getInstance();
239+
            strokeView.setText(nf.format(stroke));
240+
            strokeView.setLayoutParams(new LinearLayout.LayoutParams(66, 66));
241+
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
242+
                if(getContext() != null)
243+
                    strokeView.setTextColor(getContext().getColor(R.color.colorAccent));
244+
            }
245+
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
246+
                strokeView.setTextAlignment(TEXT_ALIGNMENT_CENTER);
247+
            }
248+
            row.addView(strokeView);
249+
250+
            List<String> kanjis = kanji.get(stroke);
251+
            if(kanjis == null)
252+
                continue;
253+
254+
            for (String k : kanjis) {
255+
                number++;
256+
                Button kanji_button = new Button(getContext());
257+
                kanji_button.setText(k);
258+
                kanji_button.setOnClickListener((View v) -> {
259+
                    Bundle result = new Bundle();
260+
                    result.putInt("event", KANJI_EVENT);
261+
                    result.putString("kanji", k);
262+
                    getParentFragmentManager().setFragmentResult("selectRadicals", result);
263+
                });
264+
                kanji_button.setLayoutParams(new LinearLayout.LayoutParams(radSize, radSize));
265+
                kanji_button.setTextSize(getRadFontSize());
266+
                row.addView(kanji_button);
267+
268+
                if (number > total / 2)
269+
                    row = kanji_row2;
270+
            }
271+
        }
272+
    }
273+
274+
    private void resizeRadicals() {
275+
        for(int row=0; row < radical_table.getChildCount(); row++) {
276+
            View r = radical_table.getChildAt(row);
277+
            if(r instanceof FlexboxLayout) {
278+
                for(int col = 0; col < ((FlexboxLayout) r).getChildCount(); col++) {
279+
                    View child = ((FlexboxLayout) r).getChildAt(col);
280+
                    if(child instanceof ToggleButton) {
281+
                        child.setLayoutParams(new FlexboxLayout.LayoutParams(radSize, radSize));
282+
                        ((ToggleButton)child).setTextSize(getRadFontSize());
283+
                    }
284+
                }
285+
            }
286+
        }
287+
        for(int kanji = 0; kanji < kanji_row1.getChildCount(); kanji++) {
288+
            View k = kanji_row1.getChildAt(kanji);
289+
            if(k instanceof Button) {
290+
                ((Button) k).setTextSize(getRadFontSize());
291+
                k.setLayoutParams(new LinearLayout.LayoutParams(radSize, radSize));
292+
            }
293+
        }
294+
        for(int kanji = 0; kanji < kanji_row2.getChildCount(); kanji++) {
295+
            View k = kanji_row2.getChildAt(kanji);
296+
            if(k instanceof Button) {
297+
                ((Button) k).setTextSize(getRadFontSize());
298+
                k.setLayoutParams(new LinearLayout.LayoutParams(radSize, radSize));
299+
            }
300+
        }
301+
    }
302+
}

app/src/main/java/eu/lepiller/nani/RadicalSelectorView.java unknown status 2

1-
package eu.lepiller.nani;
2-
3-
import android.content.Context;
4-
import android.os.AsyncTask;
5-
import android.os.Build;
6-
import android.util.AttributeSet;
7-
import android.util.Log;
8-
import android.util.Pair;
9-
import android.view.LayoutInflater;
10-
import android.view.View;
11-
import android.widget.Button;
12-
import android.widget.LinearLayout;
13-
import android.widget.TextView;
14-
import android.widget.ToggleButton;
15-
16-
import com.google.android.flexbox.FlexWrap;
17-
import com.google.android.flexbox.FlexboxLayout;
18-
19-
import java.text.NumberFormat;
20-
import java.util.ArrayList;
21-
import java.util.Arrays;
22-
import java.util.Collections;
23-
import java.util.List;
24-
import java.util.Map;
25-
import java.util.Set;
26-
27-
import eu.lepiller.nani.dictionary.IncompatibleFormatException;
28-
import eu.lepiller.nani.dictionary.RadicalDict;
29-
30-
public class RadicalSelectorView extends LinearLayout implements OnTaskCompleted<Map<Integer, List<String>>>,
31-
        OnOtherTaskCompleted<Pair<Map<Integer, List<String>>, Set<String>>> {
32-
    static private final String TAG = "RSV";
33-
    private Button close_button, help_button;
34-
    private LinearLayout kanji_row1, kanji_row2;
35-
    private LinearLayout radical_table;
36-
    final List<String> selected = new ArrayList<>();
37-
    View.OnClickListener kanjiSelectionListener;
38-
    RadicalDict dictionary;
39-
    private int radSize = 122;
40-
41-
    public RadicalSelectorView(Context context) {
42-
        this(context, null, 0);
43-
    }
44-
45-
    public RadicalSelectorView(Context context, AttributeSet attrs) {
46-
        this(context, attrs, 0);
47-
    }
48-
49-
    public RadicalSelectorView(Context context, AttributeSet attrs, int defStyle) {
50-
        super(context, attrs, defStyle);
51-
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
52-
        if(inflater == null) {
53-
            Log.e(TAG, "Inflater is null!");
54-
            return;
55-
        }
56-
        inflater.inflate(R.layout.content_radicals, this);
57-
        this.setOrientation(VERTICAL);
58-
    }
59-
60-
    @Override
61-
    protected void onFinishInflate() {
62-
        super.onFinishInflate();
63-
64-
        close_button = findViewById(R.id.close_button);
65-
        help_button = findViewById(R.id.help_button);
66-
        kanji_row1 = findViewById(R.id.kanji_row1);
67-
        kanji_row2 = findViewById(R.id.kanji_row2);
68-
        radical_table = findViewById(R.id.radical_table);
69-
    }
70-
71-
    public void setDictionary(RadicalDict dict) {
72-
        dictionary = dict;
73-
        new DictionaryUpdateTask(this).execute(dict);
74-
    }
75-
76-
    public void setRadSize(int size) {
77-
        radSize = size;
78-
        resizeRadicals();
79-
    }
80-
81-
    public int getRadFontSize() {
82-
        return radSize / 8;
83-
    }
84-
85-
    @Override
86-
    public void onTaskCompleted(Map<Integer, List<String>> radicals) {
87-
        if(radicals == null)
88-
            return;
89-
90-
        ArrayList<Integer> strokes = new ArrayList<>(radicals.keySet());
91-
        Collections.sort(strokes);
92-
        for (int stroke : strokes) {
93-
            TextView strokeView = new TextView(getContext());
94-
            NumberFormat nf = NumberFormat.getInstance();
95-
            strokeView.setText(nf.format(stroke));
96-
            radical_table.addView(strokeView);
97-
98-
            FlexboxLayout box = new FlexboxLayout(getContext());
99-
            radical_table.addView(box);
100-
101-
            List<String> lst = radicals.get(stroke);
102-
            if(lst == null)
103-
                continue;
104-
105-
            for (final String radical : lst) {
106-
                ToggleButton radicalButton = new ToggleButton(getContext());
107-
                radicalButton.setTextOff(radical);
108-
                radicalButton.setTextOn(radical);
109-
                radicalButton.setText(radical);
110-
                radicalButton.setTextSize(getRadFontSize());
111-
                radicalButton.setLayoutParams(new FlexboxLayout.LayoutParams(radSize, radSize));
112-
113-
                radicalButton.setOnClickListener(v -> {
114-
                    boolean checked = ((ToggleButton) v).isChecked();
115-
                    if (checked) {
116-
                        selected.add(radical);
117-
                    } else {
118-
                        selected.remove(radical);
119-
                    }
120-
121-
                    String[] set = new String[selected.size()];
122-
                    for(int i=0; i<selected.size(); i++) {
123-
                        set[i] = selected.get(i);
124-
                    }
125-
                    new DictionarySearchTask(RadicalSelectorView.this, dictionary).execute(set);
126-
                });
127-
                box.addView(radicalButton);
128-
            }
129-
130-
            box.setFlexWrap(FlexWrap.WRAP);
131-
            box.invalidate();
132-
        }
133-
    }
134-
135-
    private static class DictionaryUpdateTask extends AsyncTask<RadicalDict, Integer, Map<Integer, List<String>>> {
136-
        OnTaskCompleted<Map<Integer, List<String>>> callback;
137-
138-
        DictionaryUpdateTask(OnTaskCompleted<Map<Integer, List<String>>> rsv) {
139-
            callback = rsv;
140-
        }
141-
142-
        @Override
143-
        protected Map<Integer, List<String>> doInBackground(RadicalDict... sInput) {
144-
            try {
145-
                return sInput[0].getAllRadicals();
146-
            } catch (IncompatibleFormatException e) {
147-
                e.printStackTrace();
148-
                return null;
149-
            }
150-
        }
151-
152-
        @Override
153-
        protected void onPostExecute(Map<Integer, List<String>> r) {
154-
            callback.onTaskCompleted(r);
155-
        }
156-
    }
157-
158-
    @Override
159-
    public void onOtherTaskCompleted(Pair<Map<Integer, List<String>>, Set<String>> result) {
160-
        if(result == null)
161-
            return;
162-
163-
        Map<Integer, List<String>> kanji = result.first;
164-
        Set<String> availableRadicals = result.second;
165-
166-
        updateSelection(kanji);
167-
        updateRadicals(availableRadicals);
168-
    }
169-
170-
    private static class DictionarySearchTask extends AsyncTask<String, Integer, Pair<Map<Integer, List<String>>, Set<String>>> {
171-
        OnOtherTaskCompleted<Pair<Map<Integer, List<String>>, Set<String>>> callback;
172-
        RadicalDict dict;
173-
174-
        DictionarySearchTask(OnOtherTaskCompleted<Pair<Map<Integer, List<String>>, Set<String>>> rsv,
175-
                             RadicalDict dictionary) {
176-
            callback = rsv;
177-
            dict = dictionary;
178-
        }
179-
180-
        @Override
181-
        protected Pair<Map<Integer, List<String>>, Set<String>> doInBackground(String... sInput) {
182-
            try {
183-
                List<String> radicals = Arrays.asList(sInput);
184-
                return new Pair<>(dict.match(radicals), dict.availableRadicals(radicals));
185-
            } catch (IncompatibleFormatException e) {
186-
                e.printStackTrace();
187-
                return null;
188-
            }
189-
        }
190-
191-
        @Override
192-
        protected void onPostExecute(Pair<Map<Integer, List<String>>, Set<String>> r) {
193-
            callback.onOtherTaskCompleted(r);
194-
        }
195-
    }
196-
197-
    public void setOnCloseEventListener(View.OnClickListener listener) {
198-
        close_button.setOnClickListener(listener);
199-
    }
200-
201-
    public void setOnHelpEventListener(View.OnClickListener listener) {
202-
        help_button.setOnClickListener(listener);
203-
    }
204-
205-
    public void setOnClickEventListener(View.OnClickListener listener) {
206-
        kanjiSelectionListener = listener;
207-
    }
208-
209-
    public void close() {
210-
        close_button.callOnClick();
211-
    }
212-
213-
    public void updateSelection(Map<Integer, List<String>> kanji) {
214-
        LinearLayout row = kanji_row1;
215-
        kanji_row1.removeAllViews();
216-
        kanji_row2.removeAllViews();
217-
218-
        if(kanji == null)
219-
            return;
220-
221-
        int total = 0;
222-
        int number = 0;
223-
        for (int stroke : kanji.keySet()) {
224-
            List<String> s = kanji.get(stroke);
225-
            if(s != null)
226-
                total += s.size();
227-
        }
228-
        for (int stroke : kanji.keySet()) {
229-
            TextView strokeView = new TextView(getContext());
230-
            NumberFormat nf = NumberFormat.getInstance();
231-
            strokeView.setText(nf.format(stroke));
232-
            strokeView.setLayoutParams(new LayoutParams(66, 66));
233-
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
234-
                strokeView.setTextColor(getContext().getColor(R.color.colorAccent));
235-
            }
236-
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
237-
                strokeView.setTextAlignment(TEXT_ALIGNMENT_CENTER);
238-
            }
239-
            row.addView(strokeView);
240-
241-
            List<String> kanjis = kanji.get(stroke);
242-
            if(kanjis == null)
243-
                continue;
244-
245-
            for (String k : kanjis) {
246-
                number++;
247-
                Button kanji_button = new Button(getContext());
248-
                kanji_button.setText(k);
249-
                kanji_button.setOnClickListener(kanjiSelectionListener);
250-
                kanji_button.setLayoutParams(new LayoutParams(radSize, radSize));
251-
                kanji_button.setTextSize(getRadFontSize());
252-
                row.addView(kanji_button);
253-
254-
                if (number > total / 2)
255-
                    row = kanji_row2;
256-
            }
257-
        }
258-
    }
259-
260-
    private void updateRadicals(Set<String> available) {
261-
        Log.v("SELECTOR", Integer.toString(radical_table.getChildCount()));
262-
        for(int row = 0; row < radical_table.getChildCount(); row++) {
263-
            View r = radical_table.getChildAt(row);
264-
            if(r instanceof FlexboxLayout) {
265-
                for (int col = 0; col < ((FlexboxLayout) r).getChildCount(); col++) {
266-
                    View child = ((FlexboxLayout) r).getChildAt(col);
267-
                    if (child instanceof ToggleButton) {
268-
                        child.setEnabled(available == null || available.contains(((ToggleButton) child).getText().toString()));
269-
                    }
270-
                }
271-
            }
272-
        }
273-
    }
274-
275-
    private void resizeRadicals() {
276-
        for(int row=0; row < radical_table.getChildCount(); row++) {
277-
            View r = radical_table.getChildAt(row);
278-
            if(r instanceof FlexboxLayout) {
279-
                for(int col = 0; col < ((FlexboxLayout) r).getChildCount(); col++) {
280-
                    View child = ((FlexboxLayout) r).getChildAt(col);
281-
                    if(child instanceof ToggleButton) {
282-
                        child.setLayoutParams(new FlexboxLayout.LayoutParams(radSize, radSize));
283-
                        ((ToggleButton)child).setTextSize(getRadFontSize());
284-
                    }
285-
                }
286-
            }
287-
        }
288-
        for(int kanji = 0; kanji < kanji_row1.getChildCount(); kanji++) {
289-
            View k = kanji_row1.getChildAt(kanji);
290-
            if(k instanceof Button) {
291-
                ((Button) k).setTextSize(getRadFontSize());
292-
                k.setLayoutParams(new LayoutParams(radSize, radSize));
293-
            }
294-
        }
295-
        for(int kanji = 0; kanji < kanji_row2.getChildCount(); kanji++) {
296-
            View k = kanji_row2.getChildAt(kanji);
297-
            if(k instanceof Button) {
298-
                ((Button) k).setTextSize(getRadFontSize());
299-
                k.setLayoutParams(new LayoutParams(radSize, radSize));
300-
            }
301-
        }
302-
    }
303-
}

app/src/main/res/layout/content_main.xml

5959
6060
        </LinearLayout>
6161
62-
        <eu.lepiller.nani.RadicalSelectorView
62+
        <androidx.fragment.app.FragmentContainerView
6363
            android:id="@+id/radical_selector"
6464
            android:layout_width="match_parent"
6565
            android:layout_height="match_parent"
66-
            android:visibility="invisible" />
66+
            android:name="eu.lepiller.nani.RadicalSelectorFragment"
67+
            android:visibility="invisible"/>
68+
6769
6870
    </FrameLayout>
6971

app/src/main/res/layout/content_radicals.xml

11
<?xml version="1.0" encoding="utf-8"?>
2-
<merge xmlns:android="http://schemas.android.com/apk/res/android"
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
33
    android:layout_width="match_parent"
44
    android:layout_height="match_parent"
55
    android:orientation="vertical">

6565
            android:layout_height="wrap_content"
6666
            android:text="@string/close" />
6767
    </LinearLayout>
68-
</merge>
68>
690>
\ No newline at end of file
68+
</LinearLayout>
68<
069<
\ No newline at end of file