2015年1月20日 星期二

[Android] 簡單氣象搜尋 (使用Yahoo Weather api)

氣象主要可以分為兩類:

1)使用地名(自行輸入)搜尋

2)使用座標(GPS)搜尋

這邊實作的部分是(1)

參考資料為:  zh-wang 在 Github上分享的程式碼

不過稍作修改-------下拉式更新天氣 , 跳出視窗式輸入地名

當然介面也有做調整,不過整體架構還是跟著參考資料修改而來的.


----------------------------------------

整個程式就分為3部分

1) 輸入地名(使用AlertDialog技術)

2) 下拉式更新(使用SwipeRefreshLayout技術)

3) 呼叫/解析Yahoo Weather Api 所傳回來的xml(呼叫yahoo Library)


先把MainActivity.class寫出來:

package com.example.weather_practice;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.civetcat.weather.library.WeatherInfo;
import com.civetcat.weather.library.YahooWeather;
import com.civetcat.weather.library.YahooWeather.SEARCH_MODE;
import com.civetcat.weather.library.YahooWeatherInfoListener;

public class MainActivity extends Activity implements YahooWeatherInfoListener {

private ImageView icon_img;
private TextView city_country_txv;
private TextView weather_status1_txv;
private TextView weather_status2_txv;
private TextView temperature_txv;
private AlertDialog dialog;
private static String City_Name;
private SwipeRefreshLayout laySwipe;

private YahooWeather mYahooWeather = YahooWeather.getInstance(5000, 5000, true);


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
        icon_img = (ImageView) findViewById(R.id.icon_img);
        city_country_txv = (TextView) findViewById(R.id.city_country_txv);
        weather_status1_txv = (TextView) findViewById(R.id.weather_status1_txv);
        weather_status2_txv = (TextView) findViewById(R.id.weather_status2_txv);
        temperature_txv = (TextView) findViewById(R.id.temperature_txv);    
       
        search_dialog();

initView();
        //searchByPlaceName("pingtung city");
}

private void search_dialog(){
// -----------取得Layout reference----------
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
final View view = inflater.inflate(R.layout.input_city, null);      
       
// -----------產生登入視窗--------
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("天氣查詢");
builder.setMessage("輸入查詢天氣城市名稱:(英文)");//"Input Target IP:"
builder.setView(view);
builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
EditText edt = (EditText) view.findViewById(R.id.city_edt);
City_Name = edt.getText().toString();
Log.d("show",edt.getText().toString());
searchByPlaceName(edt.getText().toString());
}
});
builder.setNegativeButton("取消", null);
dialog = builder.create();
dialog.show();
}


private void initView(){
laySwipe = (SwipeRefreshLayout) findViewById(R.id.laySwipe);
laySwipe.setOnRefreshListener(onSwipeToRefresh);
laySwipe.setColorSchemeResources(
           android.R.color.holo_red_light,
           android.R.color.holo_blue_light,
           android.R.color.holo_green_light,
           android.R.color.holo_orange_light);
}

private OnRefreshListener onSwipeToRefresh = new OnRefreshListener(){

@Override
public void onRefresh() {
// TODO Auto-generated method stub
laySwipe.setRefreshing(true);
new Handler().postDelayed(new Runnable(){

@Override
public void run() {
// TODO Auto-generated method stub
laySwipe.setRefreshing(false);
searchByPlaceName(City_Name);
Toast.makeText(getApplicationContext(), "Refresh done!", Toast.LENGTH_SHORT).show();
}},5000);
}};

private void searchByPlaceName(String location) {
mYahooWeather.setNeedDownloadIcons(true);
mYahooWeather.setSearchMode(SEARCH_MODE.PLACE_NAME);
Log.d("searchByPlaceName","searchByPlaceName");
mYahooWeather.queryYahooWeatherByPlaceName(getApplicationContext(), location, MainActivity.this);
}

@Override
public void gotWeatherInfo(WeatherInfo weatherInfo) {
// TODO Auto-generated method stub
// 屏東代碼2306213 or TWXX0015
Log.d("got weather info","got weather info");
        if (weatherInfo != null) {
        city_country_txv.setText(City_Name+ ", "+ weatherInfo.getWOEIDCountry());

        weather_status1_txv.setText(weatherInfo.getCurrentConditionDate());
        weather_status2_txv.setText(weatherInfo.getCurrentText());
       
        temperature_txv.setText(weatherInfo.getCurrentTempC()+"℃");

        Log.d("weather info",weatherInfo.getCurrentText());
if (weatherInfo.getCurrentConditionIcon() != null) {
//設定icon

switch(weatherInfo.getCurrentText()){
//不全部列舉,有些不會發生
case "Freezing Drizzle":
break;
case "Drizzle":
break;
case "Freezing Rain":
break;
case "Light Rain":
icon_img.setImageResource(R.drawable.rain_wh);
break;
case "Showers":
break;
case "Blustery":
break;
case "Windy":
break;
case "Cold":
break;
case "Cloudy":
break;
case "Mostly Cloudy":
icon_img.setImageResource(R.drawable.double_cloud_wh);
break;
case "Partly Cloudy":
icon_img.setImageResource(R.drawable.cloud_wh);
break;
case "Clear": //night
break;
case "Sunny":
break;
case "Fair": //day or night
icon_img.setImageResource(R.drawable.night_wh);
break;
case "Hot":
break;
case "Isolated Thunderstorms":
break;
case "Scattered Thunderstorms":
break;
case "Scattered Showers":
break;
case "Thundershowers":
break;
case "Isolated Thundershowers":
break;
case "Haze":
icon_img.setImageResource(R.drawable.haze_wh);
break;
case "Fog":
icon_img.setImageResource(R.drawable.haze_wh);
break;
case "not available":
break;
}
}
        } else {
        }
}



@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}


********在這邊特別註明一下,yahoo有些天氣狀態還沒更新上去,所以switch case的部分要自行做調整(不過不影響整個程式碼運行)*******


search_dialog()函式就是負責跳出視窗讓使用者可以輸入地名,查詢天氣

initView() 則是初始化下拉式更新的元件

OnRefreshListener() 就監聽 沒別的 onRefresh()裡面就寫你更新時要做的動作,至於handler只是

因為要show toast而已,沒太大用處:)

searchByPlaceName() 這個很重要,他會呼叫到yahoo library 透過

SEARCH_MODE.PLACE_NAME 這方式來搜尋天氣

然後因為我們一開頭有implement YahooWeatherInfoListener 所以他會自己監聽,(裡面有一個函式gotWeatherInfo,就是listener 實作的方法)


詳細的就請大家自己看一下囉,應該不難才對(?)


Activity_main.xml:

<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/laySwipe"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#87CEFA"
    android:orientation="vertical"
    tools:context="ah.hathi.simpleweather.WeatherActivity"
    tools:ignore="MergeRootFrame" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/city_country_txv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/activity_vertical_margin"
            android:gravity="center"
            android:text="城市,國家"
            android:textAppearance="?android:attr/textAppearanceMedium" />

        <ImageView
            android:id="@+id/icon_img"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:src="@drawable/sun_wh" />

        <TextView
            android:id="@+id/weather_status1_txv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="天氣狀態1"
            android:textAppearance="?android:attr/textAppearanceMedium" />

        <TextView
            android:id="@+id/weather_status2_txv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="天氣狀態2"
            android:textAppearance="?android:attr/textAppearanceMedium" />

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="0.5" >
        </FrameLayout>

        <TextView
            android:id="@+id/temperature_txv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/activity_vertical_margin"
            android:gravity="center"
            android:text="溫度"
            android:textAppearance="?android:attr/textAppearanceLarge"
            android:textSize="@dimen/temperature_text_size" />
    </LinearLayout>

</android.support.v4.widget.SwipeRefreshLayout>


input_city.xml:

<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/city_edt"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

</EditText>

然後再values/dimens.xml 還有宣告一個

<resources>

    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
    <dimen name="temperature_text_size">30dp</dimen>

</resources>

修改這邊就可以方便修改溫度的字型大小




附上完整檔案,以上 


End