Add pitch layout preference

Julien LepillerSat Jun 25 19:27:57+0200 2022

057291d

Add pitch layout preference

.idea/misc.xml

44
    <option name="filePathToZoomLevelMap">
55
      <map>
66
        <entry key="../../../../../../layout/custom_preview.xml" value="0.23385416666666667" />
7+
        <entry key="app/src/main/res/drawable/ic_pitch.xml" value="0.1535" />
8+
        <entry key="app/src/main/res/drawable/ic_rad.xml" value="0.1535" />
9+
        <entry key="app/src/main/res/drawable/ic_reading.xml" value="0.1535" />
10+
        <entry key="app/src/main/res/layout/fragment_results.xml" value="0.2078125" />
11+
        <entry key="app/src/main/res/layout/layout_result.xml" value="0.2078125" />
12+
        <entry key="app/src/main/res/xml/preferences.xml" value="0.2078125" />
713
      </map>
814
    </option>
915
  </component>

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

4444
    private SearchView search_form;
4545
    private RadicalSelectorView radical_selector;
4646
    private String readingStyle = "furigana";
47+
    private String pitchStyle = "box";
4748
    private String intentSearch = null;
4849
    ViewPager2 viewPager2;
4950
    ResultPagerAdapter pagerAdapter;

7374
                PreferenceManager.getDefaultSharedPreferences(this);
7475
        sharedPref.registerOnSharedPreferenceChangeListener(this);
7576
        int radSizePref = getRadSizePref(sharedPref);
76-
        readingStyle = getReadingSizePref(sharedPref);
77+
        readingStyle = getReadingStylePref(sharedPref);
78+
        pitchStyle = getPitchStylePref(sharedPref);
7779
7880
        Button radical_button = findViewById(R.id.radical_button);
7981
8082
        pagerAdapter = new ResultPagerAdapter(this);
8183
        pagerAdapter.setReadingStyle(readingStyle);
84+
        pagerAdapter.setPitchStyle(pitchStyle);
8285
        pagerAdapter.notifyDataSetChanged();
8386
        viewPager2.setAdapter(pagerAdapter);
8487

137140
        if(key.compareTo(SettingsActivity.KEY_PREF_RAD_SIZE) == 0) {
138141
            radical_selector.setRadSize(getRadSizePref(sharedPreferences));
139142
        } else if(key.compareTo(SettingsActivity.KEY_PREF_READING_STYLE) == 0) {
140-
            readingStyle = getReadingSizePref(sharedPreferences);
143+
            readingStyle = getReadingStylePref(sharedPreferences);
141144
            pagerAdapter.setReadingStyle(readingStyle);
142145
            pagerAdapter.notifyItemChanged(0);
146+
        } else if(key.compareTo(SettingsActivity.KEY_PREF_PITCH_STYLE) == 0) {
147+
            pitchStyle = getPitchStylePref(sharedPreferences);
148+
            pagerAdapter.setPitchStyle(pitchStyle);
149+
            pagerAdapter.notifyItemChanged(0);
143150
        }
144151
    }
145152

148155
        return Integer.parseInt(prefRadSize);
149156
    }
150157
151-
    private String getReadingSizePref(SharedPreferences sharedPreferences) {
158+
    private String getReadingStylePref(SharedPreferences sharedPreferences) {
152159
        return sharedPreferences.getString(SettingsActivity.KEY_PREF_READING_STYLE, "furigana");
153160
    }
154161
162+
    private String getPitchStylePref(SharedPreferences sharedPreferences) {
163+
        return sharedPreferences.getString(SettingsActivity.KEY_PREF_PITCH_STYLE, "box");
164+
    }
165+
155166
    private class SearchThread extends Thread {
156167
        String text;
157168

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

1+
package eu.lepiller.nani;
2+
3+
import android.content.Context;
4+
import android.graphics.Canvas;
5+
import android.graphics.Paint;
6+
import android.util.AttributeSet;
7+
import android.util.Pair;
8+
9+
import androidx.annotation.Nullable;
10+
11+
public class PitchContourView extends PitchView {
12+
    private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
13+
    private final static int spacing = 4;
14+
15+
    public PitchContourView(Context context) {
16+
        super(context);
17+
    }
18+
19+
    public PitchContourView(Context context, @Nullable AttributeSet attrs) {
20+
        super(context, attrs);
21+
    }
22+
23+
    public PitchContourView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
24+
        super(context, attrs, defStyleAttr);
25+
    }
26+
27+
    @Override
28+
    protected void onDraw(Canvas canvas) {
29+
        super.onDraw(canvas);
30+
        if(pitchedMora == null || pitchedMora.size() == 0)
31+
            return;
32+
33+
        paint.setColor(textColor);
34+
        paint.setTextSize(textSize);
35+
        paint.setStrokeWidth(2);
36+
37+
        int x = 0;
38+
        for(int i = 0; i< pitchedMora.size(); i++) {
39+
            Pair<String, Boolean> mora = pitchedMora.get(i);
40+
            float posX = getX(x, textSize);
41+
            String text = mora.first == null? "???": mora.first;
42+
            x += text.length();
43+
            float width = paint.measureText(text);
44+
45+
            paint.setStyle(Paint.Style.FILL);
46+
            paint.setTextSize((float)textSize);
47+
            paint.setStrokeWidth(textSize);
48+
            canvas.drawText(text, posX+spacing, textSize + textSize / 4, paint);
49+
50+
            paint.setStrokeWidth(2);
51+
            paint.setStyle(Paint.Style.STROKE);
52+
            if(mora.second) {
53+
                canvas.drawLine(posX, 0, posX+width+2*spacing, 0, paint);
54+
            } else {
55+
                canvas.drawLine(posX, textSize + textSize/2, posX+width+2*spacing, textSize + textSize/2, paint);
56+
            }
57+
58+
            if(i+1<pitchedMora.size()) {
59+
                Pair<String, Boolean> mora2 = pitchedMora.get(i+1);
60+
                if(mora2.second != mora.second) {
61+
                    canvas.drawLine(posX+width+2*spacing, 0, posX+width+2*spacing, textSize + textSize/2, paint);
62+
                }
63+
            }
64+
        }
65+
66+
    }
67+
68+
    private static float getX(int i, float textSize) {
69+
        return i*textSize + i*2*spacing + textSize/2;
70+
    }
71+
72+
    private int totalSize() {
73+
        int total = 0;
74+
        for(int i = 0; i< pitchedMora.size(); i++) {
75+
            Pair<String, Boolean> mora = pitchedMora.get(i);
76+
            if(mora.first != null)
77+
                total += mora.first.length();
78+
        }
79+
        return total+1;
80+
    }
81+
82+
    @Override
83+
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
84+
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
85+
86+
        if(pitchedMora != null)
87+
            setMeasuredDimension((int)getX(totalSize(), textSize), (int)(textSize + textSize/2));
88+
        else
89+
            setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
90+
    }
91+
}

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

11
package eu.lepiller.nani;
22
33
import android.content.Context;
4-
import android.content.res.Configuration;
5-
import android.content.res.TypedArray;
64
import android.graphics.Canvas;
7-
import android.graphics.Color;
85
import android.graphics.Paint;
96
import android.util.AttributeSet;
107
import android.util.Pair;
11-
import android.view.View;
12-
import android.widget.TextView;
138
149
import androidx.annotation.Nullable;
1510
16-
import java.util.ArrayList;
17-
18-
public class PitchDiagramView extends View {
11+
public class PitchDiagramView extends PitchView {
1912
    private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
20-
    private int textColor = Color.BLACK;
21-
    private int pitchColor = Color.BLACK;
22-
    private ArrayList<Pair<String, Boolean>> pitchedMora = new ArrayList<>();
23-
    private int accent;
24-
    private String text;
25-
26-
    private float textSize = 32;
2713
2814
    public PitchDiagramView(Context context) {
2915
        super(context);
30-
        setDefaults();
3116
    }
3217
3318
    public PitchDiagramView(Context context, @Nullable AttributeSet attrs) {
3419
        super(context, attrs);
35-
        setDefaults();
36-
        setupAttributes(attrs, 0);
3720
    }
3821
3922
    public PitchDiagramView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4023
        super(context, attrs, defStyleAttr);
41-
        setDefaults();
42-
        setupAttributes(attrs, defStyleAttr);
43-
    }
44-
45-
    private void setDefaults() {
46-
        textColor = getContext().getResources().getColor(android.R.color.tab_indicator_text);
47-
        int mode = getContext().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
48-
        if(mode == Configuration.UI_MODE_NIGHT_NO) {
49-
            pitchColor = getContext().getResources().getColor(android.R.color.background_dark);
50-
        } else if(mode == Configuration.UI_MODE_NIGHT_YES) {
51-
            pitchColor = getContext().getResources().getColor(android.R.color.background_light);
52-
        }
53-
        textSize = new TextView(getContext()).getTextSize();
54-
    }
55-
56-
    private void setupAttributes(AttributeSet attrs, int defStyleAttr) {
57-
        TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.PitchDiagramView, defStyleAttr, 0);
58-
        textColor = typedArray.getColor(R.styleable.PitchDiagramView_textColor, textColor);
59-
        pitchColor = typedArray.getColor(R.styleable.PitchDiagramView_pitchColor, pitchColor);
60-
        textSize = typedArray.getDimension(R.styleable.PitchDiagramView_textSize, textSize);
61-
        text = typedArray.getString(R.styleable.PitchDiagramView_text);
62-
        accent = typedArray.getInt(R.styleable.PitchDiagramView_pitch, -1);
63-
        updatePitchedMora();
64-
    }
65-
66-
    private static boolean is_mora(char c) {
67-
        ArrayList<Character> not_mora = new ArrayList<>();
68-
        not_mora.add("???".charAt(0));
69-
        not_mora.add("???".charAt(0));
70-
        not_mora.add("???".charAt(0));
71-
        not_mora.add("???".charAt(0));
72-
        not_mora.add("???".charAt(0));
73-
        not_mora.add("???".charAt(0));
74-
        return !not_mora.contains(c);
75-
    }
76-
77-
    public void setText(String text) {
78-
        this.text = text;
79-
        updatePitchedMora();
80-
        notify();
81-
    }
82-
83-
    public void setPitch(int pitch) {
84-
        this.accent = pitch;
85-
        updatePitchedMora();
86-
        notify();
87-
    }
88-
89-
    public String getText() {
90-
        return text;
91-
    }
92-
93-
    public int getPitch() {
94-
        return accent;
95-
    }
96-
97-
    private void updatePitchedMora() {
98-
        ArrayList<String> moras = new ArrayList<>();
99-
100-
        if(accent < 0 || text == null)
101-
            return;
102-
103-
        for(int i=0; i<text.length(); i++) {
104-
            char here = text.charAt(i);
105-
            if(is_mora(here) && (i == text.length()-1 || is_mora(text.charAt(i+1))))
106-
                moras.add(text.substring(i,i+1));
107-
            else if(is_mora(here))
108-
                moras.add(text.substring(i,i+2));
109-
        }
110-
        moras.add(null);
111-
        pitchedMora = new ArrayList<>();
112-
        if(accent == 0)
113-
            setHeiban(pitchedMora, moras);
114-
        else if(accent == 1)
115-
            setAtamadaka(pitchedMora, moras);
116-
        else
117-
            setOtherAccent(pitchedMora, moras, accent);
118-
    }
119-
120-
    public void setTextColor(int textColor) {
121-
        this.textColor = textColor;
122-
    }
123-
124-
    public void setPitchColor(int pitchColor) {
125-
        this.pitchColor = pitchColor;
126-
    }
127-
128-
    public void setTextSize(float textSize) {
129-
        this.textSize = textSize;
130-
        notify();
13124
    }
13225
13326
    private static float getCharWidth(float textSize) {

15851
        return (float)3.5 * textSize + getParticleRadius(textSize);
15952
    }
16053
161-
    private static void setHeiban(ArrayList<Pair<String, Boolean>> text, ArrayList<String> moras) {
162-
        text.add(new Pair<>(moras.get(0), false));
163-
        for(int i=1; i<moras.size(); i++) {
164-
            text.add(new Pair<>(moras.get(i), true));
165-
        }
166-
    }
167-
168-
    private static void setAtamadaka(ArrayList<Pair<String, Boolean>> text, ArrayList<String> moras) {
169-
        text.add(new Pair<>(moras.get(0), true));
170-
        for(int i=1; i<moras.size(); i++) {
171-
            text.add(new Pair<>(moras.get(i), false));
172-
        }
173-
    }
174-
175-
    private static void setOtherAccent(ArrayList<Pair<String, Boolean>> text, ArrayList<String> moras, int accent) {
176-
        text.add(new Pair<>(moras.get(0), false));
177-
        int i;
178-
        for(i=1; i<moras.size() && i < accent; i++) {
179-
            text.add(new Pair<>(moras.get(i), true));
180-
        }
181-
        for(; i<moras.size(); i++) {
182-
            text.add(new Pair<>(moras.get(i), false));
183-
        }
184-
    }
185-
18654
    @Override
18755
    protected void onDraw(Canvas canvas) {
18856
        super.onDraw(canvas);

254122
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
255123
256124
        if(pitchedMora != null)
257-
           setMeasuredDimension((int)getX(pitchedMora.size(), textSize), (int)(getMoraPosition(textSize) + textSize/2));
125+
            setMeasuredDimension((int)getX(pitchedMora.size(), textSize), (int)(getMoraPosition(textSize) + textSize/2));
258126
        else
259127
            setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
260128
    }

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

1+
package eu.lepiller.nani;
2+
3+
import android.content.Context;
4+
import android.content.res.Configuration;
5+
import android.content.res.TypedArray;
6+
import android.graphics.Color;
7+
import android.graphics.Paint;
8+
import android.util.AttributeSet;
9+
import android.util.Pair;
10+
import android.view.View;
11+
import android.widget.TextView;
12+
13+
import androidx.annotation.Nullable;
14+
15+
import java.util.ArrayList;
16+
17+
public abstract class PitchView extends View {
18+
    private int accent;
19+
    private String text;
20+
21+
    protected int textColor = Color.BLACK;
22+
    protected int pitchColor = Color.BLACK;
23+
    protected ArrayList<Pair<String, Boolean>> pitchedMora = new ArrayList<>();
24+
    protected float textSize = 32;
25+
26+
    public PitchView(Context context) {
27+
        super(context);
28+
        setDefaults();
29+
    }
30+
31+
    public PitchView(Context context, @Nullable AttributeSet attrs) {
32+
        super(context, attrs);
33+
        setDefaults();
34+
        setupAttributes(attrs, 0);
35+
    }
36+
37+
    public PitchView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
38+
        super(context, attrs, defStyleAttr);
39+
        setDefaults();
40+
        setupAttributes(attrs, defStyleAttr);
41+
    }
42+
43+
    private void setDefaults() {
44+
        textColor = getContext().getResources().getColor(android.R.color.tab_indicator_text);
45+
        int mode = getContext().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
46+
        if(mode == Configuration.UI_MODE_NIGHT_NO) {
47+
            pitchColor = getContext().getResources().getColor(android.R.color.background_dark);
48+
        } else if(mode == Configuration.UI_MODE_NIGHT_YES) {
49+
            pitchColor = getContext().getResources().getColor(android.R.color.background_light);
50+
        }
51+
        textSize = new TextView(getContext()).getTextSize();
52+
    }
53+
54+
    private void setupAttributes(AttributeSet attrs, int defStyleAttr) {
55+
        TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.PitchDiagramView, defStyleAttr, 0);
56+
        textColor = typedArray.getColor(R.styleable.PitchDiagramView_textColor, textColor);
57+
        pitchColor = typedArray.getColor(R.styleable.PitchDiagramView_pitchColor, pitchColor);
58+
        textSize = typedArray.getDimension(R.styleable.PitchDiagramView_textSize, textSize);
59+
        text = typedArray.getString(R.styleable.PitchDiagramView_text);
60+
        accent = typedArray.getInt(R.styleable.PitchDiagramView_pitch, -1);
61+
        updatePitchedMora();
62+
    }
63+
64+
    protected static boolean is_mora(char c) {
65+
        ArrayList<Character> not_mora = new ArrayList<>();
66+
        not_mora.add("???".charAt(0));
67+
        not_mora.add("???".charAt(0));
68+
        not_mora.add("???".charAt(0));
69+
        not_mora.add("???".charAt(0));
70+
        not_mora.add("???".charAt(0));
71+
        not_mora.add("???".charAt(0));
72+
        return !not_mora.contains(c);
73+
    }
74+
75+
    public void setText(String text) {
76+
        this.text = text;
77+
        updatePitchedMora();
78+
    }
79+
80+
    public void setPitch(int pitch) {
81+
        this.accent = pitch;
82+
        updatePitchedMora();
83+
    }
84+
85+
    public String getText() {
86+
        return text;
87+
    }
88+
89+
    public int getPitch() {
90+
        return accent;
91+
    }
92+
93+
    private void updatePitchedMora() {
94+
        ArrayList<String> moras = new ArrayList<>();
95+
96+
        if(accent < 0 || text == null)
97+
            return;
98+
99+
        for(int i=0; i<text.length(); i++) {
100+
            char here = text.charAt(i);
101+
            if(is_mora(here) && (i == text.length()-1 || is_mora(text.charAt(i+1))))
102+
                moras.add(text.substring(i,i+1));
103+
            else if(is_mora(here))
104+
                moras.add(text.substring(i,i+2));
105+
        }
106+
        moras.add(null);
107+
        pitchedMora = new ArrayList<>();
108+
        if(accent == 0)
109+
            setHeiban(pitchedMora, moras);
110+
        else if(accent == 1)
111+
            setAtamadaka(pitchedMora, moras);
112+
        else
113+
            setOtherAccent(pitchedMora, moras, accent);
114+
    }
115+
116+
    public void setTextColor(int textColor) {
117+
        this.textColor = textColor;
118+
    }
119+
120+
    public void setPitchColor(int pitchColor) {
121+
        this.pitchColor = pitchColor;
122+
    }
123+
124+
    public void setTextSize(float textSize) {
125+
        this.textSize = textSize;
126+
    }
127+
128+
    private static void setHeiban(ArrayList<Pair<String, Boolean>> text, ArrayList<String> moras) {
129+
        text.add(new Pair<>(moras.get(0), false));
130+
        for(int i=1; i<moras.size(); i++) {
131+
            text.add(new Pair<>(moras.get(i), true));
132+
        }
133+
    }
134+
135+
    private static void setAtamadaka(ArrayList<Pair<String, Boolean>> text, ArrayList<String> moras) {
136+
        text.add(new Pair<>(moras.get(0), true));
137+
        for(int i=1; i<moras.size(); i++) {
138+
            text.add(new Pair<>(moras.get(i), false));
139+
        }
140+
    }
141+
142+
    private static void setOtherAccent(ArrayList<Pair<String, Boolean>> text, ArrayList<String> moras, int accent) {
143+
        text.add(new Pair<>(moras.get(0), false));
144+
        int i;
145+
        for(i=1; i<moras.size() && i < accent; i++) {
146+
            text.add(new Pair<>(moras.get(i), true));
147+
        }
148+
        for(; i<moras.size(); i++) {
149+
            text.add(new Pair<>(moras.get(i), false));
150+
        }
151+
    }
152+
}

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

11
package eu.lepiller.nani;
22
33
import android.annotation.SuppressLint;
4+
import android.app.NotificationManager;
45
import android.content.Context;
56
import android.content.Intent;
67
import android.text.Html;

2728
    static List<Result> results = new ArrayList<>();
2829
    static List<KanjiResult> kanjiResults = new ArrayList<>();
2930
    private static String readingStyle = "furigana";
31+
    private static String pitchStyle = "box";
3032
    private final Context context;
3133
3234
    static final String TAG = "RESULTS_PAGER";

138140
                LinearLayout senses_view = child_result.findViewById(R.id.sense_view);
139141
                TextView additional_info = child_result.findViewById(R.id.additional_info_view);
140142
                TextView pitch_view = child_result.findViewById(R.id.pitch_view);
143+
                PitchDiagramView pitch_diagram = child_result.findViewById(R.id.pitch_diagram_view);
144+
                PitchContourView pitch_contour = child_result.findViewById(R.id.pitch_contour_view);
141145
142146
                // Populate the data into the template view using the data object
143147
                if(readingStyle.compareTo("furigana") == 0) {
144148
                    kanji_view.setCombinedText(result.getKanjiFurigana());
149+
                    reading_view.setVisibility(View.GONE);
145150
                } else {
146151
                    kanji_view.setCombinedText(result.getKanji());
147152
                    reading_view.setVisibility(View.VISIBLE);

151156
                // If pitch information is available, make it visible
152157
                String pitch = result.getPitch();
153158
                if(pitch != null) {
154-
                    pitch_view.setVisibility(View.VISIBLE);
159+
                    if(pitchStyle.compareTo("box") == 0) {
160+
                        pitch_view.setVisibility(View.VISIBLE);
161+
                        pitch_diagram.setVisibility(View.GONE);
162+
                        pitch_contour.setVisibility(View.GONE);
163+
                    } else if(pitchStyle.compareTo("diagram") == 0) {
164+
                        if(readingStyle.compareTo("kana") == 0) {
165+
                            reading_view.setVisibility(View.GONE);
166+
                        }
167+
                        pitch_diagram.setVisibility(View.VISIBLE);
168+
                        pitch_contour.setVisibility(View.GONE);
169+
                        pitch_view.setVisibility(View.GONE);
170+
                        pitch_diagram.setText(result.getReading());
171+
                        pitch_diagram.setPitch(Integer.parseInt(pitch));
172+
                    } else if(pitchStyle.compareTo("contour") == 0) {
173+
                        if(readingStyle.compareTo("kana") == 0) {
174+
                            reading_view.setVisibility(View.GONE);
175+
                        }
176+
                        pitch_contour.setVisibility(View.VISIBLE);
177+
                        pitch_diagram.setVisibility(View.GONE);
178+
                        pitch_view.setVisibility(View.GONE);
179+
                        pitch_contour.setText(result.getReading());
180+
                        pitch_contour.setPitch(Integer.parseInt(pitch));
181+
                    }
182+
155183
                    pitch_view.setText(pitch);
156184
                    pitch_view.setOnClickListener(v -> {
157185
                        Intent intent = new Intent(context, HelpPitchActivity.class);

229257
    }
230258
231259
    @SuppressLint("NotifyDataSetChanged")
260+
    public void setPitchStyle(String pitchStyle) {
261+
        ResultPagerAdapter.pitchStyle = pitchStyle;
262+
        Log.d(TAG, "pitch style updated to " + pitchStyle);
263+
        notifyDataSetChanged();
264+
    }
265+
266+
    @SuppressLint("NotifyDataSetChanged")
232267
    public void setKanjiResults(List<KanjiResult> kanjiResults) {
233268
        if(kanjiResults == null)
234269
            return;

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

77
public class SettingsActivity extends AppCompatActivity {
88
    public static final String KEY_PREF_RAD_SIZE = "rad_size";
99
    public static final String KEY_PREF_READING_STYLE = "reading_style";
10+
    public static final String KEY_PREF_PITCH_STYLE = "pitch_style";
1011
1112
    @Override
1213
    protected void onCreate(Bundle savedInstanceState) {

app/src/main/res/drawable/ic_pitch.xml unknown status 1

1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
    android:width="32dp"
3+
    android:height="32dp"
4+
    android:viewportWidth="128"
5+
    android:viewportHeight="128">
6+
  <path
7+
      android:pathData="M64,64m-64,0a64,64 0,1 1,128 0a64,64 0,1 1,-128 0"
8+
      android:strokeWidth="0.264583"
9+
      android:fillColor="#e6e6e6"
10+
      android:fillType="evenOdd"/>
11+
  <path
12+
      android:pathData="M28,84m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0"
13+
      android:strokeWidth="0.264583"
14+
      android:fillColor="#1a1a1a"/>
15+
  <path
16+
      android:pathData="M100,84m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0"
17+
      android:strokeWidth="0.264583"
18+
      android:fillColor="#1a1a1a"/>
19+
  <path
20+
      android:pathData="M64,40m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0"
21+
      android:strokeWidth="0.264583"
22+
      android:fillColor="#1a1a1a"/>
23+
  <path
24+
      android:pathData="M28,84 L64,40 100,84"
25+
      android:strokeLineJoin="miter"
26+
      android:strokeWidth="5"
27+
      android:fillColor="#00000000"
28+
      android:strokeColor="#1a1a1a"
29+
      android:strokeLineCap="butt"/>
30+
</vector>

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

3737
3838
            <TextView
3939
                android:id="@+id/reading_view"
40-
                android:layout_width="match_parent"
40+
                android:layout_width="wrap_content"
41+
                android:layout_height="wrap_content"
42+
                android:layout_marginTop="8dp"
43+
                android:layout_marginLeft="8dp"
44+
                android:layout_marginStart="8dp"
45+
                android:layout_marginRight="8dp"
46+
                android:layout_marginEnd="8dp"
47+
                android:textSize="@dimen/normal_size"
48+
                android:textAlignment="center"
49+
                android:contentDescription="@string/kanji_description"
50+
                android:textIsSelectable="true"
51+
                android:gravity="center_horizontal"
52+
                android:minWidth="@dimen/title_size"
53+
                android:visibility="gone" />
54+
55+
            <eu.lepiller.nani.PitchContourView
56+
                android:id="@+id/pitch_contour_view"
57+
                android:layout_width="wrap_content"
58+
                android:layout_height="wrap_content"
59+
                android:layout_marginTop="8dp"
60+
                android:layout_marginLeft="8dp"
61+
                android:layout_marginStart="8dp"
62+
                android:layout_marginRight="8dp"
63+
                android:layout_marginEnd="8dp"
64+
                android:textSize="@dimen/normal_size"
65+
                android:textAlignment="center"
66+
                android:contentDescription="@string/kanji_description"
67+
                android:textIsSelectable="true"
68+
                android:gravity="center_horizontal"
69+
                android:minWidth="@dimen/title_size"
70+
                android:visibility="gone" />
71+
72+
            <eu.lepiller.nani.PitchDiagramView
73+
                android:id="@+id/pitch_diagram_view"
74+
                android:layout_width="wrap_content"
4175
                android:layout_height="wrap_content"
4276
                android:layout_marginTop="8dp"
4377
                android:layout_marginLeft="8dp"
4478
                android:layout_marginStart="8dp"
4579
                android:layout_marginRight="8dp"
4680
                android:layout_marginEnd="8dp"
81+
                android:textSize="@dimen/normal_size"
4782
                android:textAlignment="center"
4883
                android:contentDescription="@string/kanji_description"
4984
                android:textIsSelectable="true"

app/src/main/res/values/strings.xml

6363
        <item>kana</item>
6464
        <item>romaji</item>
6565
    </string-array>
66+
    <string name="pref_pitch_style">Display style for pitch accent information</string>
67+
    <string-array name="pref_pitch_style_choice">
68+
        <item>Box</item>
69+
        <item>Diagram</item>
70+
        <item>Contour</item>
71+
    </string-array>
72+
    <string-array name="pref_pitch_style_values">
73+
        <item>box</item>
74+
        <item>diagram</item>
75+
        <item>contour</item>
76+
    </string-array>
6677
6778
    <!-- Dictionnary descriptions -->
6879
    <string name="error_dico_url">Error fetching dictionary list: malformed URL.</string>

app/src/main/res/xml/preferences.xml

1414
        android:title="@string/pref_reading_style"
1515
        android:defaultValue="furigana"
1616
        android:icon="@drawable/ic_reading"/>
17+
    <ListPreference
18+
        android:entries="@array/pref_pitch_style_choice"
19+
        android:entryValues="@array/pref_pitch_style_values"
20+
        android:key="pitch_style"
21+
        android:title="@string/pref_pitch_style"
22+
        android:defaultValue="box"
23+
        android:icon="@drawable/ic_pitch"/>
1724
</PreferenceScreen>
1724=
1825=
\ No newline at end of file