はじめに
良い一日。 この記事では、Androidアプリケーションの開発時に発生する可能性のある問題について学びます。 前回の記事からのコメントは、この記事を書くように促しました。ところで、ここにあります: 最初の記事 ヒントをありがとう! さあ、始めましょう...
問題1
アプリケーションを開発するとき、できるだけ便利で美しいものにしたかったのです。 これは、標準のダイアログボックスによって防止されました。 ダイアログの背景をアプリケーションのメインの背景と一致させたいと思いました。
解決策
独自のテーマを選択する必要があるマニフェストでは、属性がこれを担当します。
android:theme="@style/AppTheme">
値/ styles.xmlに移動します。
このファイルにはアプリケーションテーマが含まれています。 まず、テーマを継承してアプリケーションをフルスクリーンにしました-android:Theme.Black.NoTitleBar.Fullscreen、次にダイアログボックスのスタイルを次のように変更しました。
<item name="android:alertDialogStyle">@style/alertStyle</item>
しかし、このオプションは機能しません...このような属性は、ダイアログボックスのスタイルを担当します。
<item name="android:alertDialogTheme">@style/alertStyle</item>
これで、同じファイルでスタイル自体を定義できます。
<style name="alertStyle" parent="android:Theme.Dialog"> <item name="android:layout_gravity">center</item> <item name="android:background">#64abcdf5</item> </style>
ファイル全体
<resources> <style name="AppTheme" parent="android:Theme.Black.NoTitleBar.Fullscreen"> <item name="android:alertDialogTheme">@style/alertStyle</item> </style> <style name="alertStyle" parent="android:Theme.Dialog"> <item name="android:layout_gravity">center</item> <item name="android:background">#64abcdf5</item> </style> </resources>
その結果、以下が得られます。
美しいダイアログボックス

問題2
この問題は、データストレージに関連しています。 最初はデータベースの作成に関連する解決策を見つけましたが、私にとっては恐ろしいことでした。 もっと簡単なオプションを探していました。 最後に、SharedPreferencesクラスの公式ドキュメントに出会いました。 データを保存するのは非常に簡単です。 例として時間を節約することを検討してください。
SaveObjectRating
public final class SaveObjectRating { private Date[] convertedTime; private SharedPreferences sharedPref; private long[] time; SaveObjectRating(Context context) { time = new long[10]; convertedTime = new Date[10]; sharedPref = context.getSharedPreferences("RatFile", MODE_PRIVATE); load(); } public Date[] getConvertedTime() { return convertedTime; } public void setNewTimeOnIndex(long a, int index) { if (a < time[index] && a != 0) { time[index] = a; } } // public void save() { SharedPreferences.Editor editor = sharedPref.edit(); for (int i = 0; i < 10; i++) { editor.putLong("key" + i, time[i]); } editor.apply(); } // private void load() { for (int i = 0; i < 10; i++) { time[i] = sharedPref.getLong("key" + i, 3599); } } // void createConvertedTime() { for (int i = 0; i < 10; i++) { convertedTime[i] = new Date(); long min = time[i] / 60; long sec = time[i] % 60; convertedTime[i].setMinutes((int) min); convertedTime[i].setSeconds((int) sec); } } }
このクラスは、プレイヤーがレベルを渡すのに費やす時間を節約するために使用されます。 このクラスのオブジェクトを作成する場合、load()メソッドがクラスコンストラクターで呼び出されるため、データは既にロードされています。
新しい時間は次の方法で設定できます。
setNewTimeOnIndex(long a, int index)
ユーザーが通過に費やした時間が少ない場合にのみデータを変更します。データを保存するには、save()メソッドを呼び出す必要があります。
また、データベースを作成せずにデータストレージの問題を解決します。
問題3
すべてはマルチスクリーンアプリケーションから始まりました。 画面を変更する必要がありますが、その方法は変わります。 私が長い間使用してきた最初の解決策は、各画面に独自のアクティビティを作成することです。 私の友人のような強力な電話があれば、このソリューションのマイナス面さえ気づかないでしょうが、そうではありません。 別の画面に切り替えると、別のアクティビティが作成され、弱い電話で視覚的に非常に目立ちます。 理解した後、私は、アクティビティがアプリケーション画面間の遷移に最適なオプションではないことに最終的に気付きました。 フラグメントを使用する必要がありました。 これにより、通常の視覚効果が得られます-画面に目立った変化はありません。
問題4
おそらく、最も難しい問題は、これまでのところどのソリューションを使用しても、松葉杖をどこかに置く必要があるため、現在のフラグメントの定義を実装することです。 私が最初に思いついたのは、静的変数を使用することでした。 オプションとしては実行できますが、フラグメントが多数ある場合は、静的変数の巨大なサンプルが作成され、どの値がどのフラグメントに関与するのか混乱し始めます。 次のオプションは、現在どのフラグメントでそのタイプを使用しているかを判断することです(Javaプログラミング言語のキーワード-instanceofを使用)。 一見動作するはずですが、動作しません。 どうしてこれがうまくいかないのか、まだ理解できませんでした。 (動作しますが、エラーが発生します...)
そこで、別のオプションを試してみました-画面に表示されているフラグメントを確認してください。 静的変数と一緒に使用すると、正常に機能します。
MainActivity.class
@Override public void onBackPressed() { System.out.println("MainActivity:onBackPressed()"); if (idTheCurrentFragment == 4) { finish(); } if (start.isVisible()) { System.out.println(" "); idTheCurrentFragment = -1; finish(); } else if (game1vs1.isVisible() || gameCompany.isVisible()) { confirmation(); // . } else if (idTheCurrentFragment == -1) { System.out.println(" "); super.onBackPressed(); } }
タスクは、システムボタンが押し戻されたときに、プレイヤーがゲームを終了することを確信しているかどうかを尋ねられることでした。 プレーヤーが同意すると、FragmentManager popBackStack( "...")クラスのインスタンスメソッドが呼び出され、静的変数が4に設定されます。この場合、ボタンが再度クリックされるとアプリケーションが終了します。 このような解決策は私に適していましたが、これをさらに改善する方法は興味深いでしょう。
問題5
フラグメントの動的な変更の問題。 たとえば、フラグメントAがあり、このフラグメントのラベルにあるボタンをクリックすると、次の画面、つまりフラグメントBが開きます。オプションを試しました-アクティビティクラスで、アプリケーションのすべてのボタンをクリックするためのイベントハンドラーを作成しました。 すべてのマークアップで、属性androidのすべてのボタンに対して、onClick = "..."アクティビティで作成されたイベントハンドラーを示しました。 ボタンの場合、ハンドラーがどのボタンを扱っているかを理解できるように、IDを指定する必要があります。
ハンドラーコード
public void onClick(View v) { int id = v.getId(); switch (id) { case R.id.exit: { onBackPressed(); break; } case R.id.info: { fm.beginTransaction().replace(R.id.fragment_container, infoFragment).addToBackStack(null).commit(); break; } case R.id.about_game: { fm.beginTransaction().replace(R.id.fragment_container, aboutGameFragment).addToBackStack(null).commit(); break; } case R.id.about_authors: { fm.beginTransaction().replace(R.id.fragment_container, aboutAuthorsFragment).addToBackStack(null).commit(); break; } }
ボタン自体はJavaコードでは作成されず、xmlでのみ作成されます。 はい、はい、動作します。 トランザクションを完了する、つまり現在のフラグメントを変更するアクティビティには、FragmentManagerクラスのインスタンスがあります。
これはすべて良いことですが、これが正しいと考えられるかどうかはわかりません。そのため、このオプションをすぐに拒否し、サンプルが完全に空になるまでいくつかの値を徐々に削除しました。 Googleドキュメントが提供するもう1つのオプションは、インターフェイスオブジェクトを使用することです。つまり、フラグメントはボタンのクリックを処理し、クリックされると、この方法でアクティビティを実装するインターフェイスオブジェクトが作成されます。
SendingActivity message = (SendingActivity) getActivity(); message.send('' '');
実装では、このインターフェースのアクティビティを切り替え可能にすることができます。この場合、次に開くフラグメントをすでに決定しています。
@Override public void send(int a) { switch (a) { case 0: { // break; } case 1: { // break; } case 2: { // break; } case 3: { // break; } case 4: { // ( ) finish(); break; } }
問題6
この問題は未解決のままです。 コメントで経験を共有できる経験豊富な開発者がいることを願っています。 実際には、svg形式の画像を開発環境にインポートする必要があることが多いのですが、訓練を受けていても1枚の写真を長時間撮る必要があります...ストーリーはこのようなもので、80枚の画像を開発環境に挿入することで苦しみました。やり直し...
おわりに
最後まで読んだ人、よくやった。 だから、私はこれらの問題を回避する長い道のりを歩んできたので、他の人は私の間違いから学び、経験を初心者のAndroid開発者と共有します。 例として、私が書いたアプリケーションを使用しました。 それらへのリンクは次のとおりです。
play.google.com/store/apps/details?id=com.thekingames.memorize
play.google.com/store/apps/details?id=com.thekingames.warrior
私の記事がお役に立てば幸いです。 皆さんに幸運を!