KDP(電子出版)のメモ 急急如律令

Amazon Kindleダイレクト・パブリッシングでの電子出版や電子書籍の作成販売について、文章やイラストの作成や編集方法について書いています。

Android設定画面の作成

設定画面を作っていて多すぎじゃないか、作るのに時間がめっちゃかかる。基本的の設定画面を作ってあとは気が向いたら作ることにしようかな。 最低限、表題、縦書き、横書きぐらいでいいか。

あなた:

androidのpreferenceに書き換えて

    jComboTitle = new JComboBox<String>(BookInfo.TitleType.titleTypeNames);
    jComboTitle.setFocusable(false);
    jComboTitle.setMaximumSize(new Dimension(200, 22));
    jComboTitle.setBorder(padding0);
    ((JLabel)jComboTitle.getRenderer()).setBorder(padding2H);
    panel.add(jComboTitle);

/ タイトル著作者等のメタ情報を格納 */ public class BookInfo { / タイトル記載種別 */ public enum TitleType { TITLE_AUTHOR, AUTHOR_TITLE, SUBTITLE_AUTHOR, TITLE_ONLY, TITLE_AUTHOR_ONLY, NONE; final static public String[] titleTypeNames = {"表題 → 著者名", "著者名 → 表題", "表題 → 著者名(副題優先)", "表題のみ(1行)", "表題+著者のみ(2行)", "なし"}; static public TitleType indexOf(int idx) { return values()[idx]; } boolean hasTitleAuthor() { switch (this) { case TITLE_ONLY: case NONE: return false; default: return true; } } boolean hasTitle() { switch (this) { case NONE: return false; default: return true; } } boolean hasAuthor() { switch (this) { case TITLE_ONLY: case NONE: return false; default: return true; } } boolean titleFirst() { switch (this) { case TITLE_AUTHOR: case SUBTITLE_AUTHOR: case TITLE_ONLY: case TITLE_AUTHOR_ONLY: return true; default: return false; } } } }

ChatGPT:

AndroidのSharedPreferencesを使って、PreferenceScreenにListPreferenceを追加する形で変換してみました。

<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">

    <ListPreference
        app:key="title_type"
        app:title="タイトル記載種別"
        app:dialogTitle="選択してください"
        app:entries="@array/title_type_names"
        app:entryValues="@array/title_type_values"
        app:defaultValue="TITLE_AUTHOR" />

</PreferenceScreen>
<resources>
    <string-array name="title_type_names">
        <item>表題 → 著者名</item>
        <item>著者名 → 表題</item>
        <item>表題 → 著者名(副題優先)</item>
        <item>表題のみ(1行)</item>
        <item>表題+著者のみ(2行)</item>
        <item>なし</item>
    </string-array>

    <string-array name="title_type_values">
        <item>TITLE_AUTHOR</item>
        <item>AUTHOR_TITLE</item>
        <item>SUBTITLE_AUTHOR</item>
        <item>TITLE_ONLY</item>
        <item>TITLE_AUTHOR_ONLY</item>
        <item>NONE</item>
    </string-array>
</resources>
import android.content.SharedPreferences;
import android.os.Bundle;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;

public class SettingsFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.preferences, rootKey);

        ListPreference titlePreference = findPreference("title_type");
        if (titlePreference != null) {
            titlePreference.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
        }
    }

    public static String getSelectedTitleType(SharedPreferences prefs) {
        return prefs.getString("title_type", "TITLE_AUTHOR"); // デフォルトは"表題 → 著者名"
    }
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String selectedTitleType = SettingsFragment.getSelectedTitleType(prefs);
  1. ListPreferenceを使用 → JComboBox の代わりに、ユーザーが選択できるリストを提供。
  2. entries と entryValues を res/values/arrays.xml に定義 → JComboBox で定義されていた titleTypeNames をXMLに移動。
  3. 選択された値を SharedPreferences で管理 → アプリの設定として保存できるようにする。
  4. サマリーの自動更新 (setSummaryProvider) → ユーザーが選択したオプションがそのまま設定画面に表示されるようにする。

ListPreferenceを使用 → JComboBox の代わりに、ユーザーが選択できるリストを提供。

entries と entryValues を res/values/arrays.xml に定義 → JComboBox<String> で定義されていた titleTypeNames をXMLに移動。

選択された値を SharedPreferences で管理 → アプリの設定として保存できるようにする。

サマリーの自動更新 (setSummaryProvider) → ユーザーが選択したオプションがそのまま設定画面に表示されるようにする。

これで、Androidの設定画面でタイトル種別を選択し、アプリ全体でその設定を使用できるようになります!

あなた:

次のpreferenceから配列番号の取得

<ListPreference
    app:key="TitleType"
    app:title="表題:本文内"
    app:dialogTitle="タイトルタイプを選択"
    app:entries="@array/title_type_names"
    app:entryValues="@array/title_type_values"
    app:defaultValue="0" />

ChatGPT:

AndroidのListPreferenceで、選択された配列のインデックスを取得する方法を解説します。

  1. SharedPreferences から entryValues の値を取得
  2. entryValues 配列内で選択された値のインデックスを検索

SharedPreferences から entryValues の値を取得

entryValues 配列内で選択された値のインデックスを検索

<ListPreference
    app:key="TitleType"
    app:title="表題:本文内"
    app:dialogTitle="タイトルタイプを選択"
    app:entries="@array/title_type_names"
    app:entryValues="@array/title_type_values"
    app:defaultValue="0" />
<resources>
    <string-array name="title_type_names">
        <item>表題 → 著者名</item>
        <item>著者名 → 表題</item>
        <item>表題 → 著者名(副題優先)</item>
        <item>表題のみ(1行)</item>
        <item>表題+著者のみ(2行)</item>
        <item>なし</item>
    </string-array>

    <string-array name="title_type_values">
        <item>0</item>
        <item>1</item>
        <item>2</item>
        <item>3</item>
        <item>4</item>
        <item>5</item>
    </string-array>
</resources>
import android.content.Context;
import android.content.SharedPreferences;
import androidx.preference.PreferenceManager;

public class PreferenceHelper {

    public static int getTitleTypeIndex(Context context) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        String selectedValue = prefs.getString("TitleType", "0"); // デフォルト値は"0"

        String[] entryValues = context.getResources().getStringArray(R.array.title_type_values);

        // entryValues の中で選択された値のインデックスを取得
        for (int i = 0; i < entryValues.length; i++) {
            if (entryValues[i].equals(selectedValue)) {
                return i;
            }
        }

        return 0; // デフォルトは 0 (エラー時)
    }
}
int selectedIndex = PreferenceHelper.getTitleTypeIndex(context);
  • SharedPreferences から "TitleType" の値を取得
  • res/values/arrays.xml の title_type_values 配列と照らし合わせてインデックスを取得
  • 選択されていない場合はデフォルト値 (0) を返す

SharedPreferences から "TitleType" の値を取得

res/values/arrays.xml の title_type_values 配列と照らし合わせてインデックスを取得

選択されていない場合はデフォルト値 (0) を返す

選択項目 entryValues getTitleTypeIndex の返り値
表題 → 著者名 "0" 0
著者名 → 表題 "1" 1
なし "5" 5

これで、選択されたListPreferenceのインデックスが簡単に取得できます!

あなた:

preferenceの更新をlistenerで更新

ChatGPT:

ListPreferenceの値が変更された際に、リスナーを使って自動的に更新する方法を紹介します。

  1. Preference.OnPreferenceChangeListener を使う
  2. リスナーを ListPreference に設定
  3. 選択値の変更を検知して処理を行う

Preference.OnPreferenceChangeListener を使う

リスナーを ListPreference に設定

選択値の変更を検知して処理を行う

import android.content.SharedPreferences;
import android.os.Bundle;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;

public class SettingsFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.preferences, rootKey);

        // ListPreference のリスナー設定
        ListPreference titlePreference = findPreference("TitleType");
        if (titlePreference != null) {
            titlePreference.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());

            // 値変更時のリスナー
            titlePreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
                @Override
                public boolean onPreferenceChange(Preference preference, Object newValue) {
                    updatePreferenceSummary(preference, newValue);
                    return true; // trueを返すと値が保存される
                }
            });
        }
    }

    private void updatePreferenceSummary(Preference preference, Object newValue) {
        if (preference instanceof ListPreference) {
            ListPreference listPreference = (ListPreference) preference;
            int index = listPreference.findIndexOfValue(newValue.toString());
            if (index >= 0) {
                preference.setSummary(listPreference.getEntries()[index]); // 選択された項目の表示名を設定
            }
        }
    }
}
<ListPreference
    app:key="TitleType"
    app:title="表題:本文内"
    app:dialogTitle="タイトルタイプを選択"
    app:entries="@array/title_type_names"
    app:entryValues="@array/title_type_values"
    app:defaultValue="0" />

設定の変更をリアルタイムで監視する場合

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener() {
    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if ("TitleType".equals(key)) {
            int selectedIndex = PreferenceHelper.getTitleTypeIndex(context);
            // 変更後のインデックスを使用して処理を行う
        }
    }
});
  1. setOnPreferenceChangeListener を設定

ListPreference の選択が変更されたときにリスナーを実行。

newValue を ListPreference の entries と照合してタイトルを更新。 2. ListPreference の選択が変更されたときにリスナーを実行。 3. newValue を ListPreference の entries と照合してタイトルを更新。 4. registerOnSharedPreferenceChangeListener で監視

設定の変更をリアルタイムで取得できる。

他のクラスから SharedPreferences の変更を監視する場合に便利。 5. 設定の変更をリアルタイムで取得できる。 6. 他のクラスから SharedPreferences の変更を監視する場合に便利。

setOnPreferenceChangeListener を設定

  • ListPreference の選択が変更されたときにリスナーを実行。
  • newValue を ListPreference の entries と照合してタイトルを更新。

ListPreference の選択が変更されたときにリスナーを実行。

newValue を ListPreference の entries と照合してタイトルを更新。

registerOnSharedPreferenceChangeListener で監視

  • 設定の変更をリアルタイムで取得できる。
  • 他のクラスから SharedPreferences の変更を監視する場合に便利。

設定の変更をリアルタイムで取得できる。

他のクラスから SharedPreferences の変更を監視する場合に便利。

  1. 設定画面で ListPreference を選択する
  2. タイトルが即座に更新
  3. 他のクラスでも SharedPreferences の変更を監視できる

設定画面で ListPreference を選択する

タイトルが即座に更新

他のクラスでも SharedPreferences の変更を監視できる

これで、設定の変更をリアルタイムで反映するリスナーが完成です! 🚀

あなた:

androidのpreferenceに書き換えて

    //入力ファイル名優先
    jCheckPubFirst = new JCheckBox("先頭が発行者");
    jCheckPubFirst.setFocusPainted(false);
    panel.add(jCheckPubFirst);
    //入力ファイル名優先
    panel.add(new JLabel("  "));
    jCheckUseFileName = new JCheckBox("ファイル名優先 ");
    jCheckUseFileName.setFocusPainted(false);
    panel.add(jCheckUseFileName);

ChatGPT:

JCheckBox を Android の CheckBoxPreference に置き換える方法 を紹介します。

<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- 先頭が発行者 -->
    <CheckBoxPreference
        app:key="pref_pub_first"
        app:title="先頭が発行者"
        app:defaultValue="false" />

    <!-- 空白 (JLabel 相当) -->
    <Preference
        app:title=" " 
        app:selectable="false" />

    <!-- ファイル名優先 -->
    <CheckBoxPreference
        app:key="pref_use_filename"
        app:title="ファイル名優先"
        app:defaultValue="false" />

</PreferenceScreen>
import android.content.SharedPreferences;
import android.os.Bundle;
import androidx.preference.CheckBoxPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;

public class SettingsFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.preferences, rootKey);

        // "先頭が発行者" の設定
        CheckBoxPreference pubFirstPref = findPreference("pref_pub_first");
        if (pubFirstPref != null) {
            pubFirstPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
                @Override
                public boolean onPreferenceChange(Preference preference, Object newValue) {
                    boolean isChecked = (boolean) newValue;
                    // ここで変更時の処理を実装可能
                    return true; // 値を保存する
                }
            });
        }

        // "ファイル名優先" の設定
        CheckBoxPreference useFilenamePref = findPreference("pref_use_filename");
        if (useFilenamePref != null) {
            useFilenamePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
                @Override
                public boolean onPreferenceChange(Preference preference, Object newValue) {
                    boolean isChecked = (boolean) newValue;
                    // ここで変更時の処理を実装可能
                    return true; // 値を保存する
                }
            });
        }
    }
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean isPubFirst = prefs.getBoolean("pref_pub_first", false);
boolean isUseFileName = prefs.getBoolean("pref_use_filename", false);
  1. JCheckBox → CheckBoxPreference

CheckBoxPreference を PreferenceScreen に追加

値は SharedPreferences に自動保存 される

setOnPreferenceChangeListener で変更を監視可能 2. CheckBoxPreference を PreferenceScreen に追加 3. 値は SharedPreferences に自動保存 される 4. setOnPreferenceChangeListener で変更を監視可能 5. JLabel の代わりに Preference を追加

ラベルの役割のため Preference を selectable="false" にして追加

ユーザー操作不可のスペースとして利用 6. ラベルの役割のため Preference を selectable="false" にして追加 7. ユーザー操作不可のスペースとして利用 8. SharedPreferences から値を取得

PreferenceManager.getDefaultSharedPreferences(context) で取得

getBoolean("キー", デフォルト値) で取得可能 9. PreferenceManager.getDefaultSharedPreferences(context) で取得 10. getBoolean("キー", デフォルト値) で取得可能

JCheckBox → CheckBoxPreference

  • CheckBoxPreference を PreferenceScreen に追加
  • 値は SharedPreferences に自動保存 される
  • setOnPreferenceChangeListener で変更を監視可能

CheckBoxPreference を PreferenceScreen に追加

値は SharedPreferences に自動保存 される

setOnPreferenceChangeListener で変更を監視可能

JLabel の代わりに Preference を追加

  • ラベルの役割のため Preference を selectable="false" にして追加
  • ユーザー操作不可のスペースとして利用

ラベルの役割のため Preference を selectable="false" にして追加

ユーザー操作不可のスペースとして利用

SharedPreferences から値を取得

  • PreferenceManager.getDefaultSharedPreferences(context) で取得
  • getBoolean("キー", デフォルト値) で取得可能

PreferenceManager.getDefaultSharedPreferences(context) で取得

getBoolean("キー", デフォルト値) で取得可能

✔️ チェックボックスの設定画面 ✅ 「先頭が発行者」 ✅ 「ファイル名優先」 (どちらもON/OFF可能)

これで、JCheckBox を Android の CheckBoxPreference にスムーズに変換できました! 🚀