前回は、データ取得に特に問題ないことを確認。何度もOpenWeatherMapのデータを利用しているが、ちょっとした勘違いなどによりデータの確認がなかなかできないこともある。
今回は、この取得データの一部(年月日、曜日、天候、天候のアイコン)をListViewを利用してリスト形式で表示。
他に取得できるデータとしては、当該都市の緯度・経度、国コード、人口、日の出・日の入時刻、最高気温、最低気温、体感温度(日中、夜、夕方、朝)、気圧、湿度、降水量、風速等々。今までに作成したアプリで使用したものもあり。ブロック・コード的には、今回表示するデータとほぼ同じようなブロック・コードを作成していくことになる。
今回のアプリ Weather App New では、主に日本語と英語の2か国語による表示をいろいろ試すのが目的の一つ。以前にも紹介したことがあるが、OpenWeatherMapのサイトによれば、49ヶ国語に対応しているとのこと。要するに、晴れ、曇り、雨等のお天気情報が49か国語で取得できるということ。ある日の東京のお天気を、日本語、アラビア語、ロシア語、ズールー語(南アフリカ)で検索すると以下の通り。(何の意味もないが。。。)
"weather": [{"id": 804,"main": "Clouds","description": "厚い雲","icon": "04d"}],
"weather": [{"id": 804,"main": "Clouds","description": "غيوم قاتمة","icon": "04d"}],
"weather": [{"id": 804,"main": "Clouds","description": "пасмурно","icon": "04d"}],
"weather": [{"id": 804,"main": "Clouds","description": "liguqubele","icon": "04d"}],
アプリ実行のビデオ:
スクリーン・デザイン:
左図:初期画面で、都市別ボタンをタップしデータを取得
右図:都市名を入力してデータを取得(左上端の拡大鏡アイコンの代わりに アイコンが表示される。)
ブロック・コード:
重複もあり少し長くなるが、前回までの復習も兼ねて。。。
1. 言語の切り替え(英語と日本語)
選択された言語を格納する変数langの設定:
言語を切り替えるタイミングとしては、第一にアプリを立ち上げた時と第二に言語切り替えボタンをタップした時がある。
アプリを立ち上げた時:
切り替えボタンchnageLangButton「English <= => 日本語」をタップした時:
いずれも関数selectLangが実行される。ダイアログ・ボックスが表示され、「日本語」または「英語」のいずれかの選択を促す。
日本語のボタンがタップされれば、変数langに "ja" がセットされ、リスト「titleLabel」のindex 2、
すなわち「新お天気アプリ」がタイトルにセットされる。また、「English」が選択されたら、同index 1
である「Weather App New」がタイトルにセットされる。
同様に、対象都市名が表示されるLabelの見出しも、リスト「cityNameLabel」よりindexに応じラベルが選択、表示される。
2. 検索対象都市をボタンで選択、あるいは都市名を入力し指定する
対象都市名を格納する変数 targetCity を設定。
都市名を表示したボタンで対象都市を選択する。
(赤白点線部分)
タップされたボタンに表示されている都市名が、リスト cityNameListEN(選択言語が英語の場合)あるいは
リスト cityNameListJP(選択言語が日本語の場合)の中のどのindex番号にあたるのかを取得。
再度、cityNameListENの中で同index番号の英語の都市名を変数targetCityにセットする。
こんなまわりくどいやり方をするのは、APIに対しGETリクエストをする際、検索対象都市名は英語である必要があるため。
そして、関数fetchDataを実行。
関数fetchDataはAPI指定のURLに対しGETリクエストを行う。
レスポンス・コードとして200が返されたら、リクエストが成功。デコードして変数JSONDataに格納。
そして、取得したデータからお天気、お天気アイコンのファイル名、日付の必要なデータを以下の関数を実行して抽出していく。
makeWeatherDescriptionList (晴、曇りなどのお天気データ)
makeWeatherIconList(お天気アイコンのファイル名)
getUnixTime(日付)
200以外の場合は、データ取得に失敗した旨をポップアップにて知らせる。
また、データの個数もcomponent "length of list" を使って取得し、変数lengthOfDataにセットしておく。
(もちろん、データの個数は1週間分なので7個とわかっており確定しているが。。。)
具体的な都市名をインプットして検索対象都市を指定する。
左上端にあるsearchImageButtonをタップすると アイコンが に変わる。
=>それと同時に都市名を冠していた4つのボタンは非表示に。
=>その代わりに、都市名入力TextBoxと「Fetch Data」ボタンが表示される。
4つのボタンはHorizontalArrangement2に、TextBoxと「Fetch Data」はVerticalArrangement1にそれぞれ格納されている。
このHorizontalArrangement2とVerticalArrangement1の表示、非表示を行うため、まず変数selectButtonStatusを設定。
searchImageButtonをタップするたびに、このselectButtonStatusに格納されている真偽値を変更しArrangementの
表示、非表示並びにsearchImageButtonのアイコン・イメージ( または )を交互に表示する。
ちなみに、 のファイル名は maginifyingGlassTrans2.png、 はbackToButtonTrans.png。
検索対象都市名を入力して「Fetch Data」ボタンをタップすると関数fetchData(ボタンのタップ時と同じ関数)が実行される。
また、プログレス・スピナー(CircularProgress1)が表示され、データを取得中であることをユーザーに知らせる。
3. 取得したJSONデータより必要なデータを抽出し、データの項目ごとにリスト形式にまとめる。
お天気のデータ(晴れ、曇り、雨など)を抽出しリスト形式にまとめる
データを格納する変数weatherDescriptionListを設定。
JSONDataの中を、list => weather => description とキーを辿っていけばお天気データを取得できる。
7日分なので、component "for each ~"を使って7回(lengthOdData)反復すれば1週間分のデータを抽出できる。
お天気アイコンのファイル名を抽出し、リスト形式にまとめる。
後で、ファイル名とファイルが保存されているURL、拡張子を連結する。
ファイル名を格納する変数weatherIconListを設定。
JSONDataの中を、list => weather => icon とキーを辿っていけばアイコンのファイル名を取得できる。
日付はUnix Timeで提供されているの取得したUnix time形式を通常の年月日の形式に整える。
年月日形式の日付のリストを格納する変数dateを設定。
Unix Timeおよび年月日に変換後の日付を格納する変数unixTimeを設定。(変数名がちょっと紛らわしい)
変数unixTimeの値をリスト形式で格納する変数unixTimeListを設定。
Unix Timeから曜日を算出するため用に使うUnix Timeのリストを格納する変数tempDayOfWeekListを設定。
取得した曜日の番号を格納する変数DayOfWeekを設定。
曜日の番号をリスト形式で格納する変数dayOfWeekListを設定。
関数getUniTime:Unix Timeを抽出し、年月日に変換の上、変数dateにリスト形式で格納する。
また、曜日の番号を取得しdayOfWeekListに格納しておく。(赤白点線内)
省略した「modulo of floor select list...」を展開すると以下の通りとなる。
この算出式については、「MIT App Inventorで遊ぶ (New Weather App 4 曜日の表示2)」を参照。
関数getDate:Unix Timeより年、月、日を取り出す。
MIT App Inventor 2では、Unix Timeはミリ秒単位、一方、OpenWeatherMapでは秒単位。
このため、取得したUnix Timeを1000倍する必要あり。componetにも単位は "millis" と表示されている。
今回、コーディング途中で1000倍するのを忘れたため、年月日の値を取り出せず時間がかかってしまった。
項目ごとに抽出したデータ(リスト形式)を統合して一つのリスト形式のデータを作る
ListView用に作成した統合されたデータを格納する変数dataForListViewを設定。
関数makeDataForListView:
ListView用のcomponent "CreateElement" を使って、リストの各行に表示するデータを作成する。
リストの各行は、mainText、detailText、imageNameの要素に分けられている。
mainText =>"変数dataに保存してある日付(年月日)" + "(" + "曜日" + ")"
曜日については、decodeListJpまたはdecodeListEnより言語("lang")に応じた
日本語あるいは英語表記の曜日を使用。
detailText=>変数weather DescriptionListに格納してあるお天気データ
imageName=>https://openweathermap.org/wn/ +変数weatherIconListに格納されているファイル名 + "@2x.png"
変数dataForListViewに格納されたデータをListViewに表示し、プログレス・スピナーを非表示とする。(赤黄点線部分)
**********************************************************
前回までのブログ:
MIT App Inventor 2で遊ぶ (Weather App New 2)
MIT App Inventor 2で遊ぶ (Weather App New 1)