Androidアプリまたは無題のプロジェクトを作成する

背景



ある晴れた日、私は英語を学び始めることを決め、勉強する直前にこの言語を教えている先生と相談しました。 私は彼がかつて得た経験を私と共有すると思った。 その結果、主に英語のサイトを訪れたときに知識を使用してから文法を取り上げるので、私は言語の言葉で勉強を始めるのが最善であると彼に同意しました。 彼は(少なくとも私にとって)非常に興味深い勉強方法を提案しました。 あるとき、言葉を覚えておくために、彼は普通の紙を取り、それを片側で等しい長方形に並べて切り取り、その長方形の片側に英語の単語を書き、もう片方の翻訳で、その後に箱を取り、結果のカードをそこに入れて、一つ一つ混ぜて取り除き、単語を見て翻訳を言いました。

この手順を毎日1〜2時間、定期的に実行し、ファイルキャビネットを補充すると、言葉がよく覚えられます。



それ以来、私は常にそうすることを決め、近い将来、自分のように英語で読み始めるようになりました! しかし、しばらくして、私はカードを切って時間を無駄にすることに飽き始めました、同時に、私は常に絶対に欠けていました、その瞬間、私は思考に打たれました、Android OS用のプログラムを作成してみませんか?このシステムで)、同様の機能を実行します!



プロジェクトが始まったのはこの瞬間からでしたが、名前は思いつきませんでした。



目的



このプロジェクトの目標は、当初、ファイルキャビネットへの単語の追加とそのさらなる活用を自動化することでしたが、後にいくつかのアイデアが訪れ、プロジェクトを開発することは非常に興味深いものでしたが、2週間後には退屈になり、以前のすべてと同様に退屈し、完全に放棄しました、私はそうしたくなかったので、この記事の著者として自分自身を試して、ネットワークプログラミングとAndroidのプログラミングの分野での経験を共有することにしました。 この記事では、可能な限り、このプログラムを作成するための手順全体をステップごとに説明しようとします。



プログラム



まず、私が作成した製品の詳細を説明し、機能を検討します。その後、興味がある人は誰でもこの奇跡の作成についてさらに読むことができます。



説明



私が最初に伝えたいことは、メニューについてです。できるだけ魅力的なものにしようとしました。私はいつも「素晴らしい」味をしていたので、これがそれから来たものです。



画像



画像でわかるように、特別なことは何もありませんが、「言葉を確認」または「言葉」ボタンをクリックすると、いわばサブメニューが表示されます。



画像



画像



上の画像からわかるように、「アルファベット順」、「逆順」、「ランダム」の各ボタンには同じプロパティがあります。 すべて特別な「+」記号でマークし、開くと記号が「-」に置き換えられます。 展開されたメニューのいずれかのアイテムをクリックすると、元の位置に折りたたまれます。



テストに合格する前、または単語を変更および削除する前に、単語を追加する必要があります。そのため、このメカニズムを検討しますが、その前にこのトピックから少し戻ってすべてが明確になるようにする必要があります。



私が言ったように、プロジェクトを作成する前に、多くのアイデアが訪れましたが、その1つは、プログラムに単語を追加することの簡素化です。 人が怠zyな生き物であり、誰もが手動でファイルキャビネットを手動で作成する必要があるわけではありません。特に、インターネットの発展と長距離でのデータ転送の時代に、3つのフィールドを入力する必要がある場合は(転写を記入する必要はありません)



画像



アイデアが思い浮かびました。プログラムのユーザーが自分のファイルキャビネットを全世界と共有してみませんか。 したがって、単語を自分の個人辞書に追加する瞬間に、ユーザーは気づかないうちに(インターネット接続がある場合)サーバーにアップロードし、データベースに保存され、他のユーザーが自分に追加するのを待機します。単語を追加するメカニズムは複雑でなく、単純であり、子供でも理解できるものです。



プログラムには、単語を変更および削除する機能もあります。 ここでは、すべてが非常に簡単です。目的のメニュー項目をクリックすると、アクティビティが私たちの前に開き、単語がアルファベット順に並べられます。 単語を削除および変更するためのウィンドウは、実際には違いはなく、単語の付いたボタン上のアイコンだけなので、1つのxmlファイルを使用してそれらを作成しました。



画像



画像



ユーザーが単語を変更すると、単語を追加するためのxmlファイルが使用され、他の機能でのみ、3つのフィールドすべてに古い値が入力されます。



画像



新しい値を入力した後、対応するボタンをクリックすると、サーバー上のデータベースに変更を加えることなく、単語が変更されてユーザーのデバイスに保存されます。 単語や単語の削除も非常に簡単です。このプロセスを複雑にする方法は想像できません。



画像



画像



画像からわかるように、すべての単語を一度に削除することも、各単語を個別に削除することもできますが、削除する前に確認ダイアログがポップアップ表示されます。



主な機能の1つ、つまり単語の追加/削除/変更について説明したので、最も重要なものを検討し、これらの単語に従ってテストに合格した後、単語を追加する別の方法を説明します。



上記の図では、アルファベット順、逆順、ランダムの3つの異なる順序でテストに合格できることがわかります。 テストオブジェクトは、英語版、ロシア語、または転写のいずれかです。



画像



図からわかるように、単語の英語版のフィールドがアクティブになっています。つまり、このオプションがテストされています。 選択したテストに応じて、常に1つの入力フィールドのみがアクティブになり、残りは変更されません。 「ステータス」行は、入力したユーザーバージョンが正しいかどうかを示します。確認するには、「確認」ボタンをクリックする必要があります。また、完了した単語の数とその数を示します。「次へ」ボタンは詳細に検討できませんが、前の単語に戻るボタンを追加できることに注意してください。 テストは、最後の単語またはメニュー項目に到達することで完了できます。



画像



テストに合格または完了したら、結果が注意を促されます。



画像



正しく入力された単語は緑色で表示され、残りは赤色で表示されます。その後、メインメニューに移動するか、再度テストを受けることができます。



次に、単語を追加する別の方法を検討します。それを使用するには、[ダウンロード]メニュー項目に移動する必要があります。ここで、上記のようにサーバーに追加された単語を表示できます。



画像



図は、このアクティビティは、ボタンの代わりにチェックボックスが存在することを除いて、実際に変更および削除のアクティブ化と同じであることを示しています。



サーバーから最後の単語が返されるまで、ユーザーが最後から2番目の単語に到達した後、さらに100個がロードされるなど、サーバーからの単語は小さな部分、つまり100個になります。 カードファイルに単語を追加するには、メニューオプションを使用します。



画像



画像でわかるように、選択した単語、または現在ロードされている単語をダウンロードできます。 保存される単語の数は、メニュー項目の左側に表示されます。



上の画像では、単語の変更/削除/読み込みのアクティブ化に編集-「検索」があることがわかります。 どこでも同じように実装されているので、ダウンロードウィンドウの例のみを検討します。



実装が簡単であるにもかかわらず、このプログラムでの単語の検索は私のお気に入りの開発です(サーバーからの単語の読み込みをカウントしないでください)。 英語とロシア語の単語を検索する「ライブ」であり、シンプルで使いやすいです。



画像



画像



画像



画像



このプログラムには、「View words」というメニュー項目もあり、すべての単語がHTMLテーブルに表示されます。



画像



最後に、すべてのアクティビティのすべての機能がメニューに複製されています。



画像



画像



画像



画像



画像



実装



推測することは難しくなかったので、プログラムは2つの部分で構成されます。これはサーバーアプリケーションとクライアントアプリケーションです。したがって、この項目は2つの部分に分割され、それぞれの実装について個別に説明します。 特にプログラムの大部分は難しくないので、私は最も必要だと思うものだけを考慮します。そうしないと、記事は非常に扱いにくくなります。



クライアント部



クライアント部分を順番に説明し始めるので、最初に考慮すべきことは、メニューの作成、より正確には、折りたたみ/展開サブメニューの実装です。 このフラグメントは非常に単純であり、説明はほとんど必要ないため、コードのロジックのみを説明します。



<Button android:id="@+id/alphabet" android:layout_width="@dimen/b_size" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/b_alphabet" android:visibility="gone" android:onClick="Alphabet"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <Button android:id="@+id/english1" android:layout_width="@dimen/b_size2" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/b_english" android:visibility="gone" android:onClick="TestingWords"/> <Button android:id="@+id/transcription1" android:layout_width="@dimen/b_size2" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/b_transcription" android:visibility="gone" android:onClick="TestingWords"/> <Button android:id="@+id/russian1" android:layout_width="@dimen/b_size2" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/b_russian" android:visibility="gone" android:onClick="TestingWords"/> </LinearLayout>
      
      





xml-fileコードスニペットからわかるように、最初はすべてのサブメニューアイテムが非表示になっていますが、対応するボタンをクリックすると、それらが表示され、アクティブだった他のアイテムが最小化されます。機能の1つを以下に示しますが、残りは事実上同じです。



 public void Alphabet(View view) { click_alphabet = !click_alphabet; if(Btn_Null()) Btn_Gone(); btn_english = (Button) findViewById(R.id.english1); btn_transcription = (Button) findViewById(R.id.transcription1); btn_russian = (Button) findViewById(R.id.russian1); if(click_alphabet) { btn_english.setVisibility(View.VISIBLE); btn_transcription.setVisibility(View.VISIBLE); btn_russian.setVisibility(View.VISIBLE); btn_alphabet.setText("   -"); } else { Btn_Gone(); btn_alphabet.setText("   +"); } }
      
      





Click_alphabet変数-ボタンが再度押されたかどうかを確認し、はいの場合、この項目が担当するサブメニューが最小化されます。



関数Btn_Null()-すべてのボタンの初期化をチェックします。

関数Btn_Gone()-すべてのメニュー項目/サブ項目を完全に折りたたみます。



次に、サーバーとスマートフォンのデータベースに単語を追加することを検討します。 ユーザーが自分に追加したすべての単語はTreeMap <String、TransRus>クラスに格納され、このクラスのキーは英語の単語であり、トランスクリプションと翻訳はTransRusクラスに格納されます。



 public class TransRus { private String transcription; private String russian; boolean error; TransRus() { transcription = new String(""); russian = new String(""); error = false; } void getTranscription(String tr) { transcription = tr; } void getRussian(String rs) { russian = rs; } String setTranscription() { return transcription; } String setRussian() { return russian; } void getError(boolean t) { error = t; } boolean setError() { return error; } }
      
      





TreeMapクラスは、CollectionWordsクラスのラッパーでラップされます。また、大文字と小文字を無視するコンパレーターも作成されています。



 class ComparatorNotRegister implements Comparator<String> { public int compare(String str1, String str2) { return str1.compareToIgnoreCase(str2); } } public class CollectionWords { static TreeMap<String, TransRus> coll_words = null; static final String file1 = "english"; static final String file2 = "transcription"; static final String file3 = "russian"; static void InitializationCollWords() { if(coll_words != null) return; coll_words = new TreeMap<String, TransRus>(new ComparatorNotRegister()); } static void PutCollWords(String english, String transcription, String russian) { TransRus tr = new TransRus(); tr.getTranscription(transcription); tr.getRussian(russian); coll_words.put(english, tr); } static void ChangedWordEng(String old_english, String new_english, String transcription, String russian) { TransRus temp = coll_words.get(old_english); coll_words.remove(old_english); PutCollWords(new_english, transcription, russian); } static void DeleteWords(String eng) { coll_words.remove(eng); } static void WriteWords(AppCompatActivity t) { try( BufferedWriter eng = new BufferedWriter(new OutputStreamWriter(t.openFileOutput(file1, t.MODE_PRIVATE))); BufferedWriter trans = new BufferedWriter(new OutputStreamWriter(t.openFileOutput(file2, t.MODE_PRIVATE))); BufferedWriter rus = new BufferedWriter(new OutputStreamWriter(t.openFileOutput(file3, t.MODE_PRIVATE)))) { for(Map.Entry<String, TransRus> me : CollectionWords.AllWords()) { eng.write(me.getKey() + "\n"); trans.write(me.getValue().setTranscription() + "\n"); rus.write(me.getValue().setRussian() + "\n"); } } catch (FileNotFoundException e) { Log.d("MyLog", "WF: " + e); } catch (IOException e) { Log.d("MyLog", "WIOE: " + e); } catch(NullPointerException e) { Log.d("MyLog", "WN: " + e); } catch (Exception e) { Log.d("MyLog", "WE: " + e); } } static void ReadWords(AppCompatActivity t) { try( BufferedReader eng = new BufferedReader(new InputStreamReader(t.openFileInput(file1))); BufferedReader trans = new BufferedReader(new InputStreamReader(t.openFileInput(file2))); BufferedReader rus = new BufferedReader(new InputStreamReader(t.openFileInput(file3)))) { String str_eng; String str_trans; String str_rus; while(((str_eng = eng.readLine()) != null) && ((str_trans = trans.readLine()) != null) && ((str_rus = rus.readLine()) != null)) { CollectionWords.PutCollWords(str_eng, str_trans, str_rus); } Log.d("MyLog", "Hyi tam"); } catch (FileNotFoundException e) { Log.d("MyLog", "RF: " + e); } catch (IOException e) { Log.d("MyLog", "RIO: " + e); } catch(NullPointerException e) { Log.d("MyLog", "RN: " + e); } } static Set<Map.Entry<String, TransRus>> AllWords() { return coll_words.entrySet(); } }
      
      





ご覧のとおり、このクラスは難しくありません。すべての単語は英語、転写、ロシア語のテキストファイルに格納されています。このため、データベースを使用する必要がありますが、あまり気にしませんでした。 すべてがそのように機能します。 WriteWords、ReadWords関数は、単語を保存するために使用されます。関数が機能するためには、それを呼び出したクラスからthisポインターを渡す必要があることに注意してください。 すべての関数が静的であるという事実はすぐに明らかになります。これは、クラスを何度も複製しないように特別に行われたものであり、他のすべては明確であり、コメントは不要です。 追加のシェルについて説明したので、add関数を説明できます。



 public void AddWord(View view) { CollectionWords.InitializationCollWords(); if(english_language.getText().length() == 0 || russian_language.getText().length() == 0) { Toast toast = Toast.makeText(getApplicationContext(), "  !", Toast.LENGTH_SHORT); toast.show(); return; } if(status != 0 && status == MainActivity.INT_CHG) { CollectionWords.ChangedWordEng(old_english, english_language.getText().toString(), transcription_language.getText().toString().length() == 0 ? "-" : transcription_language.getText().toString(), russian_language.getText().toString()); Back(null); } CollectionWords.PutCollWords(english_language.getText().toString(), (transcription_language.getText().toString().length() == 0 ? "-" : transcription_language.getText().toString()), russian_language.getText().toString()); ClientAddWords caw = new ClientAddWords(); caw.ServerAddWords("1(!!)" + english_language.getText().toString() + "(!!)" + (transcription_language.getText().toString().length() == 0 ? "-" : transcription_language.getText().toString()) + "(!!)" + russian_language.getText().toString()); english_language.setText(""); transcription_language.setText(""); russian_language.setText(""); }
      
      





コードスニペットから、ここの必須フィールドはenlish_languageとrussian_languageであることがわかります。これらが入力されていない場合、単語は追加されず、関数は終了し、メッセージがポップアップ表示されます。 前に言ったように、単語を追加および変更するために、1つのxml-fileが使用されます。したがって、クラスにも2番目のifステートメントがあり、この関数への入力が行われたかどうかの値を格納するステータス変数をチェックします。言葉の変化。

特に興味深いのは、サーバーに単語を送信するために使用されるClientAddWordsクラスです。 なぜなら 現在、Android Studioでは、ネットワークに関連するすべてが別のスレッドで発生する必要があるため、これを担当するクラスを作成することにしました。 プログラムには、サーバーから単語を返すもう1つがあります。



コードからわかるように、ClientAddWordsオブジェクトが最初に作成され、次にオブジェクトが関数を呼び出し、シンボル「(!!)」で区切られた文字列が渡されます。このシンボルは、サーバー向けのオペレーションコード(この場合は「1」)と英語の単語を分離します、トランスクリプションおよび翻訳。これは、サーバーがデータを相互に正しく分離できるようにするためです。この行はサーバーに渡されると推測されるかもしれません。



ネットワークを操作するためのクラスを作成すると、ServerAddWords関数が呼び出されたときにクライアントがサーバーに接続し、転送後にクライアントがサーバーアプリケーションから切断されるため、サーバーに追加の負荷がかからないため、非常に便利です。 以下は、ClientAddWordsクラスです。



 public class ClientAddWords extends Thread { String str_user; void ServerAddWords(String str) { str_user = str; start(); } public void run() { Log.d("MyLog", "Run Client"); InetAddress addr = null; try { addr = InetAddress.getByName("192.168.1.208"); } catch (UnknownHostException e) { Log.d("MyLog", "ServerAddWords ClientAddWords: " + e); } Client c; try { c = new Client(addr); } catch (IOException e) { Log.d("MyLog", "Socket failed: " + e); return; } c.Out(str_user); c.Close(); } }
      
      





ご覧のとおり、このコードの実装では、複雑なことはなく、追加の説明は不要です。Clientクラスのコードを以下に示します。



 public class Client extends Thread { private Socket socket; private BufferedReader in; private PrintWriter out; InetAddress addr; public String In() throws IOException { return in.readLine(); } public void Out(String str) { out.println(str); } public Client(InetAddress addr) throws IOException { this.addr = addr; Log.d("MyLog", "Making client"); try { socket = new Socket(addr, 8080); } catch (IOException e) { Log.d("MyLog", "Socket failed: " + e); throw e; } try { in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); } catch (Exception e) { Log.d("MyLog", "In/Out: " + e); try { socket.close(); } catch (IOException e2) { Log.d("MyLog", "Client: Socket not closed"); } } } public void Close() { try { socket.close(); in.close(); out.close(); } catch (IOException e) { Log.d("MyLog", "Close Client: " + e); } } }
      
      





興味深い点もありません。このコード例は、ネットワークプログラミング専用のWebサイトで見つけることができます。



今度は、単語の変更と削除を行うクラスを見ていきます。何度も言ったように、それらは1つのxmlファイルを使用し、その実装で最も興味深いのはボタンでレイアウトを埋めることです。



 <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/background_find" > <LinearLayout android:id="@+id/ll_find" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> </LinearLayout> </ScrollView>
      
      





xmlファイル自体では、このコード部分のみが対象です。レイアウトがid-ll_findに設定されていることがわかります。これはプログラムでボタンを作成するために必要です。



 class MyButton extends Button { private String str_eng; private String str_trans; private String str_rus; private int index; public MyButton(Context context) { super(context); } void setEnglish(String eng) { str_eng = eng; } void setTranscription(String trans) { str_trans = trans; } void setRussian(String rus) { str_rus = rus; } void setIndex(int id) { index = id; } String getEnglish() { return str_eng; } String getTranscription() { return str_trans; } String getRussian() { return str_rus; } int getIndex() { return index; } }
      
      





推測するのは難しくないので、このクラスはすぐに注意します。これは、カードの値、つまり英語の単語、その転写と翻訳を保存することのみを目的としています



最初に説明する関数はCreateButtonです。コードを以下に示します。



 public MyButton CreateButton(int i, String eng, String trans, String rus) { final MyButton btnNew = new MyButton(this); btnNew.setBackgroundResource(R.drawable.background_button); btnNew.setText(eng + " - " + rus); btnNew.setEnglish(eng); btnNew.setTranscription(trans); btnNew.setRussian(rus); btnNew.setIndex(i); if(status == MainActivity.INT_DEL) { btnNew.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon_delete_button, 0, 0, 0); btnNew.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AlertDialog.Builder ad; Find context; context = Find.this; String title = " "; String message = " ?"; String button1String = ""; String button2String = ""; ad = new AlertDialog.Builder((Context) context); ad.setTitle(title); ad.setMessage(message); ad.setPositiveButton(button1String, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int arg1) { CollectionWords.DeleteWords(btnNew.getEnglish()); ll_layout.removeView(btnNew); } }); ad.setNegativeButton(button2String, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int arg1) { } }); ad.show(); } }); } else { btnNew.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon_changed_button, 0, 0, 0); btnNew.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d("MyLog", "Changed Words"); ChangedWord((MyButton) v); ll_layout.removeView((MyButton) v); } }); } return btnNew; }
      
      





いくつかの興味深い点があります。つまり、ボタンの背景を変更します。次に、クラスが訪問する目的に応じて、ボタンのアイコンを作成します。単語とbtnNewが削除されるか、ChangedWord関数が呼び出され、単語を変更するアクティビティが開きます。



次に説明する機能はShowViewWordsで、その目的はボタンをレイアウトに配置することです。



 public void ShowViewWords(LinearLayout.LayoutParams lParams, String sub_str) { int i = 0; String first_chr = new String(""); for(Map.Entry<String, TransRus> me : CollectionWords.AllWords()) { if(sub_str.length() != 0 && (me.getKey().toLowerCase().indexOf(sub_str.toLowerCase()) == -1 && me.getValue().setRussian().toLowerCase().indexOf(sub_str.toLowerCase()) == -1)) continue; if(!first_chr.equals(String.valueOf(me.getKey().toUpperCase().charAt(0)))) { first_chr = String.valueOf(me.getKey().toUpperCase().charAt(0)); TextView temp = new TextView(this); temp.setText(first_chr + ":"); temp.setTextSize(25f); ll_layout.addView(temp, i, lParams); i++; } ll_layout.addView(CreateButton(i, me.getKey(), me.getValue().setTranscription(), me.getValue().setRussian()), i, lParams); i++; } if(i == 0) { LinearLayout.LayoutParams l = CreateParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER_VERTICAL); TextView not_found = new TextView(this); not_found.setText("  "); ll_layout.addView(not_found, l); } }
      
      





また、次の単語の最初の文字とは異なる、単語の最初の文字の値を格納するTextViewを作成して追加します。 できる限り説明しようとしましたが、念のため、例として例を示します。



画像



このコード部分がこれを担当します。



 if(!first_chr.equals(String.valueOf(me.getKey().toUpperCase().charAt(0)))) { first_chr = String.valueOf(me.getKey().toUpperCase().charAt(0)); TextView temp = new TextView(this); temp.setText(first_chr + ":"); temp.setTextSize(25f); ll_layout.addView(temp, i, lParams); i++; }
      
      





最初に、変数first_chrには空の文字列が割り当てられます。そのため、サイクルが初めて通過すると、値が入力されます。



この行はループ状態の原因です。



 for(Map.Entry<String, TransRus> me : CollectionWords.AllWords())
      
      





これは検索に関連するため、最初のifステートメントの目的については後で説明し、検索については最後に説明します。



  ll_layout.addView(CreateButton(i, me.getKey(), me.getValue().setTranscription(), me.getValue().setRussian()), i, lParams);
      
      





そして、この構造はll_layoutへの追加を担当し、ここでCreateButton関数が呼び出されます。これは上記と見なされ、MyButton値を返し、このボタンのインデックスとパラメーターが追加されます。



ShowViewWords関数はCreatesButton関数から呼び出され、CreatesButton関数はonCreateから呼び出されます。 CreatesButtonコードは次のとおりです。



 public void CreatesButton(String str_find) { ll_layout.removeAllViews(); LinearLayout.LayoutParams lParams = CreateParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, Gravity.LEFT); lParams.topMargin = 1; ShowViewWords(lParams, str_find); }
      
      





CreateParams関数コード:



 public LinearLayout.LayoutParams CreateParams(int width, int height, int gravity) { LinearLayout.LayoutParams lParams = new LinearLayout.LayoutParams(width, height); lParams.gravity = gravity; return lParams; }
      
      





プログラム記述のこの段階で、単語のテストを担当するTestWordsクラスの実装に取り​​組みました。 いつものように、複雑なことは何もありませんが、考慮すべき点がいくつかあります。 最初の1つは、ユーザーがテストを選択することです。推測がどれほど困難であっても、9つのテストオプション、つまり指定された語順(アルファベット順、逆順、ランダム)およびテストオブジェクト(英語、転写、ロシア語)があります。 そのため、StatusTest関数を最初に呼び出します。 どの編集をブロックするかをコードによって決定し、単語が存在するインデックスで変数を初期化します。



 public void StatusTest() { switch (status) { case MainActivity.INT_ALPH_ENG: edit_transcription.setRawInputType(0x00000000); edit_russian.setRawInputType(0x00000000); next_words = 0; break; case MainActivity.INT_ALPH_TRANS: edit_english.setRawInputType(0x00000000); edit_russian.setRawInputType(0x00000000); next_words = 0; break; case MainActivity.INT_ALPH_RUS: edit_english.setRawInputType(0x00000000); edit_transcription.setRawInputType(0x00000000); next_words = 0; break; case MainActivity.INT_REVS_ENG: edit_transcription.setRawInputType(0x00000000); edit_russian.setRawInputType(0x00000000); next_words = CollectionWords.coll_words.size() - 1; break; case MainActivity.INT_REVS_TRANS: edit_english.setRawInputType(0x00000000); edit_russian.setRawInputType(0x00000000); next_words = CollectionWords.coll_words.size() - 1; break; case MainActivity.INT_REVS_RUS: edit_english.setRawInputType(0x00000000); edit_transcription.setRawInputType(0x00000000); next_words = CollectionWords.coll_words.size() - 1; break; case MainActivity.INT_RAND_ENG: rand_next_words = new Random(); next_words = MethodRandomWords(); edit_transcription.setRawInputType(0x00000000); edit_russian.setRawInputType(0x00000000); break; case MainActivity.INT_RAND_TRANS: rand_next_words = new Random(); next_words = MethodRandomWords(); edit_english.setRawInputType(0x00000000); edit_russian.setRawInputType(0x00000000); break; case MainActivity.INT_RAND_RUS: rand_next_words = new Random(); next_words = MethodRandomWords(); edit_english.setRawInputType(0x00000000); edit_transcription.setRawInputType(0x00000000); break; } }
      
      





アルファベット順の場合、next_words変数には0が割り当てられます。逆順は、TreeMapクラスのサイズから1を引いたものと、next_wordsでランダムな値を返す特別な関数であるランダムな順序です。



MethodRandomWords関数は、同じランダム値を数回返さないようにします。



すべての編集を初期化し、StatusTest関数を呼び出した後、ReadWordメソッドが実行されます。



 public void ReadWord() { last_words++; amount_words.setText(last_words + "/" + CollectionWords.coll_words.size()); switch (status) { case MainActivity.INT_ALPH_ENG: nw = VecNextWord(next_words); edit_english.setText(""); edit_transcription.setText(nw.getValue().setTranscription()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_ALPH_TRANS: nw = VecNextWord(next_words); edit_transcription.setText(""); edit_english.setText(nw.getKey()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_ALPH_RUS: nw = VecNextWord(next_words); edit_russian.setText(""); edit_english.setText(nw.getKey()); edit_transcription.setText(nw.getValue().setTranscription()); break; case MainActivity.INT_REVS_ENG: nw = VecNextWord(next_words); edit_english.setText(""); edit_transcription.setText(nw.getValue().setTranscription()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_REVS_TRANS: nw = VecNextWord(next_words); edit_transcription.setText(""); edit_english.setText(nw.getKey()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_REVS_RUS: nw = VecNextWord(next_words); edit_russian.setText(""); edit_english.setText(nw.getKey()); edit_transcription.setText(nw.getValue().setTranscription()); break; case MainActivity.INT_RAND_ENG: nw = VecNextWord(next_words); edit_english.setText(""); edit_transcription.setText(nw.getValue().setTranscription()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_RAND_TRANS: nw = VecNextWord(next_words); edit_transcription.setText(""); edit_english.setText(nw.getKey()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_RAND_RUS: nw = VecNextWord(next_words); edit_russian.setText(""); edit_english.setText(nw.getKey()); edit_transcription.setText(nw.getValue().setTranscription()); break; } status_true_word.setText(":-"); }
      
      





このメソッドの目的は、最初のワードをロードすることです。VecNextWord関数がこれを担当します。そのパラメーターはインデックスであり、戻り値はMap.Entry <String、TransRus>です。また、ワード数を示し、ステータスをリセットします。



次の役割は2つの機能のみが果たします。チェック-入力された単語の正確性をチェックし、必要に応じてステータス、NextWordを変更します-選択した順序に応じて、リスト内の次の単語を返します。 機能コードを以下に示します。



 public void Check(View view) { check_bool = true; Log.d("MyLog", "Status: " + status); switch (status) { case MainActivity.INT_ALPH_ENG: Log.d("MyLog", "Check()"); if(edit_english.getText().toString().equals(nw.getKey())) { Log.d("MyLog", "True"); status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { Log.d("MyLog", "False"); status_true_word.setText(":  "); } break; case MainActivity.INT_ALPH_TRANS: Log.d("MyLog", "Check()"); if(edit_transcription.getText().toString().equals(nw.getValue().setTranscription())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; case MainActivity.INT_ALPH_RUS: Log.d("MyLog", "Check()"); if(edit_russian.getText().toString().equals(nw.getValue().setRussian())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; case MainActivity.INT_REVS_ENG: Log.d("MyLog", "Check()"); if(edit_english.getText().toString().equals(nw.getKey())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; case MainActivity.INT_REVS_TRANS: Log.d("MyLog", "Check()"); if(edit_transcription.getText().toString().equals(nw.getValue().setTranscription())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; case MainActivity.INT_REVS_RUS: Log.d("MyLog", "Check()"); if(edit_russian.getText().toString().equals(nw.getValue().setRussian())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; case MainActivity.INT_RAND_ENG: Log.d("MyLog", "Check()"); if(edit_english.getText().toString().equals(nw.getKey())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; case MainActivity.INT_RAND_TRANS: Log.d("MyLog", "Check()"); if(edit_transcription.getText().toString().equals(nw.getValue().setTranscription())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; case MainActivity.INT_RAND_RUS: Log.d("MyLog", "Check()"); if(edit_russian.getText().toString().equals(nw.getValue().setRussian())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; } } public void NextWord(View view) throws InterruptedException { if(last_words >= CollectionWords.coll_words.size()) { ResultTestGo(); return; } if(!check_bool && last_words != 0) Check(view); AddWordInTable(nw.getValue().setError()); last_words++; amount_words.setText(last_words + "/" + CollectionWords.coll_words.size()); switch (status) { case MainActivity.INT_ALPH_ENG: next_words++; nw = VecNextWord(next_words); edit_english.setText(""); edit_transcription.setText(nw.getValue().setTranscription()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_ALPH_TRANS: next_words++; nw = VecNextWord(next_words); edit_transcription.setText(""); edit_english.setText(nw.getKey()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_ALPH_RUS: next_words++; nw = VecNextWord(next_words); edit_russian.setText(""); edit_english.setText(nw.getKey()); edit_transcription.setText(nw.getValue().setTranscription()); break; case MainActivity.INT_REVS_ENG: next_words--; nw = VecNextWord(next_words); edit_english.setText(""); edit_transcription.setText(nw.getValue().setTranscription()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_REVS_TRANS: next_words--; nw = VecNextWord(next_words); edit_transcription.setText(""); edit_english.setText(nw.getKey()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_REVS_RUS: next_words--; nw = VecNextWord(next_words); edit_russian.setText(""); edit_english.setText(nw.getKey()); edit_transcription.setText(nw.getValue().setTranscription()); break; case MainActivity.INT_RAND_ENG: next_words = MethodRandomWords(); nw = VecNextWord(next_words); edit_english.setText(""); edit_transcription.setText(nw.getValue().setTranscription()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_RAND_TRANS: next_words = MethodRandomWords(); nw = VecNextWord(next_words); edit_transcription.setText(""); edit_english.setText(nw.getKey()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_RAND_RUS: next_words = MethodRandomWords(); nw = VecNextWord(next_words); edit_russian.setText(""); edit_english.setText(nw.getKey()); edit_transcription.setText(nw.getValue().setTranscription()); break; } status_true_word.setText(":-"); check_bool = false; }
      
      





, - , . , , Html-, . , , , AddWordInTable(nw.getValue().setError()), .



 public void AddWordInTable(boolean temp) { table_result += "<tr><td " + (temp ? "bgcolor=\"#008000\"" : "bgcolor=\"#FF0000\"") + ">" + nw.getKey() + "</td><td " + (temp ? "bgcolor=\"#008000\"" : "bgcolor=\"#FF0000\"") + ">" + nw.getValue().setTranscription() + "</td><td " + (temp ? "bgcolor=\"#008000\"" : "bgcolor=\"#FF0000\"") + ">" + nw.getValue().setRussian() + "</td><td " + (temp ? "bgcolor=\"#008000\"" : "bgcolor=\"#FF0000\"") + ">" + (temp ? "" : " ") + "</td></tr>\n"; }
      
      





onCreat, ResultTest, .

, , , ResultTest, , , , Html- loadDataWithBaseURL(null, TestWords.table_result, «text/html», «UTF-8», null), WebView.



, . Load, 18 , .. RecyclerView, - , , . , , Load, .



, , , . xml- CheckBox' TextView', . TextView , . , , , , .



, RecyclerView, , .. , .



, onCreateViewHolder, onBindViewHolder, getItemCount, ViewHolder. GetItemCount , .. . ViewHolder.



 public static class ViewHolder extends RecyclerView.ViewHolder { public CheckBox chkbox; public TextView tv_alph; public ViewHolder(View v) { super(v); chkbox = (CheckBox) v.findViewById(R.id.rv_chkbox); tv_alph = (TextView) v.findViewById(R.id.tv_alph); } }
      
      





. onCreateViewHolder, ViewHolder.



 public RecyclerLoad.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.content_checkbox, parent, false); ViewHolder vh = new ViewHolder(v); return vh; }
      
      





onBindViewHolder.



 public void onBindViewHolder(final ViewHolder holder, final int position) { if(index_alph[position]) { holder.tv_alph.setText(Alph[position]); holder.tv_alph.setVisibility(View.VISIBLE); } else holder.tv_alph.setVisibility(View.GONE); holder.chkbox.setText(Eng_Array[position] + " - [" + Trans_Array[position] + "] - " + Rus_Array[position]); if(this_load.menu_load_1 != null) this_load.menu_load_1.setTitle("   (" + Integer.toString(amount) + ")"); holder.chkbox.setOnCheckedChangeListener(null); holder.chkbox.setChecked(checked_box[position]); holder.chkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if(isChecked) checked_words_load++; else checked_words_load--; checked_box[position] = isChecked; if(this_load.menu_load_2 != null) this_load.menu_load_2.setTitle(".   (" + Integer.toString(checked_words_load) + ")"); } }); if (position >= amount - 1) { Log.d("MyLog", "!!!"); LoadWords(sub_str); onBind = true; } }
      
      





, — holder , — CheckBox' setOnCheckedChangeListener setChecked, CheckBox' onCheckedChanged, «» — if , LoadWords.



sub_str, . String, Edit' «: ». なぜなら , Edit'e, .



 find_words.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable s) { } public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { FindWord(null); } }); public void FindWord(View view) { mAdapter.Find(find_words.getText().toString()); mAdapter.notifyDataSetChanged(); }
      
      





, FindWord, Find, RecyclerLoad, , , .



 public void Find(String sub_str) { this.sub_str = sub_str; amount = 0; Eng_Array = null; Trans_Array = null; Rus_Array = null; checked_box = null; index_alph = null; Alph = null; LoadWords(sub_str); }
      
      





LoadWords, RecyclerLoad , .. .



 public void LoadWords(String sub_str) { ClientLoadWords clw = new ClientLoadWords(); clw.LoadWords("2(!!)" + (sub_str.length() != 0 ? sub_str : "(--)"), amount); try { clw.join(); } catch (InterruptedException e) { Log.d("MyLog", "ShowViewWords: " + e); } if(clw.int_error == -1) { Toast toast = Toast.makeText(this_load.getApplicationContext(), "   !", Toast.LENGTH_SHORT); toast.show(); } amount += clw.amount; Log.d("MyLog", "amount = " + amount); String [] temp_Eng_Array = new String[amount]; String [] temp_Trans_Array = new String[amount]; String [] temp_Rus_Array = new String[amount]; String [] temp_Alph = new String[amount]; boolean [] temp_checked_box = new boolean[amount]; boolean [] temp_index_alph = new boolean[amount]; int temp_amount = Eng_Array != null ? Eng_Array.length : 0; if(Eng_Array != null) for(int i = 0; i < Eng_Array.length; i++) { temp_Eng_Array[i] = Eng_Array[i]; temp_Trans_Array[i] = Trans_Array[i]; temp_Rus_Array[i] = Rus_Array[i]; temp_Alph[i] = Alph[i]; temp_checked_box[i] = checked_box[i]; temp_index_alph[i] = index_alph[i]; } for(int i = 0; i < clw.amount; i++) { temp_Eng_Array[i + temp_amount] = clw.Eng_Array[i]; temp_Trans_Array[i + temp_amount] = clw.Trans_Array[i]; temp_Rus_Array[i + temp_amount] = clw.Rus_Array[i]; temp_checked_box[i + temp_amount] = false; temp_index_alph[i + temp_amount] = false; temp_Alph[i + temp_amount] = ""; if(!first_chr.equals(String.valueOf(clw.Eng_Array[i].toUpperCase().charAt(0)))) { Log.d("MyLog", "First Chr: " + first_chr + ", me.getKey(): " + clw.Eng_Array[i].toUpperCase().charAt(0) + " boolean: " + first_chr.equals(String.valueOf(clw.Eng_Array[i].toUpperCase().charAt(0)))); first_chr = String.valueOf(clw.Eng_Array[i].toUpperCase().charAt(0)); temp_Alph[i + temp_amount] = first_chr + ":"; temp_index_alph[i + temp_amount] = true; } } for(int i = 0; i < temp_Eng_Array.length; i++) { Log.d("MyLog", "temp_Alph: " + temp_Alph[i] + ", temp_index_alph = " + temp_index_alph[i] + ", i = " + i); } Eng_Array = temp_Eng_Array; Trans_Array = temp_Trans_Array; Rus_Array = temp_Rus_Array; checked_box = temp_checked_box; index_alph = temp_index_alph; Alph = temp_Alph; }
      
      





LoadWords , . - ClientLoadWords — ClientAddWords, , . . LoadWords, , , . LoadWords .



 public void run() { InetAddress addr = null; try { addr = InetAddress.getByName("192.168.1.137"); } catch (UnknownHostException e) { Log.d("MyLog", "ClientLoadWords LoadWords 1: " + e); } Client c; try { c = new Client(addr); } catch (IOException e) { Log.d("MyLog", "Socket failed: " + e); int_error = -1; return; } c.Out(str_user); c.Out(Integer.toString(begin)); amount = 0; try { amount = Integer.parseInt(c.In()); } catch (IOException e) { Log.d("MyLog", "LoadWords ClientLoadWords 3: " + e); } Log.d("MyLog", "Amount: " + amount); Id_Array = new int[amount]; Eng_Array = new String[amount]; Trans_Array = new String[amount]; Rus_Array = new String[amount]; try { for (int i = 0; i < amount; i++) { Id_Array[i] = Integer.parseInt(c.In()); Eng_Array[i] = c.In(); Trans_Array[i] = c.In(); Rus_Array[i] = c.In(); } } catch (IOException e) { Log.d("MyLog", "LoadWords ClientLoadWords 4: " + e); } Sort(); }
      
      





, . , , for, , , .



LoadWords. clw.join() ClientLoadWords, . clw -1, . , , , TextView' index_alph, TextView .



, , .. , , , , . ., , « », , , Html-, , .





, , MySQL TCP, , . / ServerOneJabber. Thread. , .. .



 public ServerOneJabber(Socket s) throws IOException, SQLException { socket = s; in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); sqldb = new SqlDB(); start(); }
      
      





, sqldb, , , . in out In Out, .



 public void run() { String message_user = new String(""); try { message_user = Out(); } catch(IOException e) { System.out.println(e); } System.out.println("message_user: " + message_user); try { switch(message_user.charAt(0)) { case '1': AddWord(message_user); break; case '2': TransferWord(message_user); break; } } catch(SQLException e) { System.out.println(e); } catch(IOException e) { System.out.println(e); } }
      
      





run . .



 public void AddWord(String str) throws SQLException { String[] str_user = Split(str, "(!!)"); for(int i = 0; i < str_user.length; i++) System.out.println("str_user: " + str_user[i]); sqldb.AddWord(str_user[1], str_user[2], str_user[3]); }
      
      





AddWord . sqldb AddWord. Split , , split String , .



 public void TransferWord(String str) throws SQLException, IOException { String [] user_str = Split(str, "(!!)"); for(int i = 0; i < user_str.length; i++) { System.out.println("user_str: " + user_str[i]); } if(sqldb.CountSQL() == 0) { In("0"); return; } int begin = new Integer(Out()); System.out.println("Loading Words..."); String [] data; if(user_str[1].equals("(--)")) data = sqldb.AllWords(); else data = sqldb.Find(user_str[1]); read_amount_words = (data.length - begin > 100 ? 100 : data.length - begin); In(Integer.toString(read_amount_words)); for(int i = begin; i < begin + ((data.length - begin) > 100 ? 100 : data.length); i++) { System.out.println("i = " + i + ", data.length = " + data.length); if(i == data.length) break; String [] str_data = Split(data[i], "(!!)"); for(int j = 0; j < str_data.length; j++) System.out.println("str_data: " + str_data[j]); In(str_data[0]); In(str_data[1]); In(str_data[2]); In(str_data[3]); } }
      
      





TransferWord . , , , , , , . , 100 , 100 , , .



 public class Server { static final int PORT = 8080; static public void main(String[] args) throws IOException { ServerSocket s = new ServerSocket(PORT); System.out.println("Server Started"); try { while(true) { Socket socket = s.accept(); try { System.out.println("Client Connection"); new ServerOneJabber(socket); } catch(IOException e) { socket.close(); } } } catch(SQLException e) { System.out.println(e); } finally { s.close(); } } }
      
      





Server main, , ServerOneJabber .



おわりに



. , , , , - . - , , . .



All Articles