1、项目效果图:
2、主页面MainActivity代码如下:
MainActivity.java
package com.qianfeng.weather;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ImageView refreshIv;
private ImageView searchIv;
private TextView cityTv;
private TextView pmTv;
private TextView errorTv;
private TextView tempTv;
private TextView weatherTv;
private TextView windTv;
private TextView dateTv;
private View lineView;
private LinearLayout otherLl;
private List weekList;
private Handler handler;
private int code = 101100101;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
getData(code);
setListener();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 100) {
code = resultCode;
getData(code);
}
}
private void setListener() {
refreshIv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getData(code);
}
});
searchIv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,
SearchActivity.class);
startActivityForResult(intent, 100);
}
});
}
/**
*
*/
private void initData() {
// 在Android中借助handler类实现从服务器获取数据后更新UI页面(Handler原理)
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 200) {
errorTv.setText((String) msg.obj);
}
if (msg.what == 100) {
errorTv.setText("");
// 停止转圈动画
refreshIv.setBackgroundResource(R.mipmap.refresh);
List list = (List) msg.obj;
cityTv.setText(list.get(0).getCity());
pmTv.setText(list.get(0).getPm());
tempTv.setText(list.get(0).getTempCurrent());
weatherTv.setText(list.get(0).getWeather() + " " + list.get(0).getTemp());
windTv.setText(list.get(0).getWindCurrent());
dateTv.setText(list.get(0).getDate_y() + " " + list.get(0).getWeek());
if (list.get(0).getPm().substring(list.get(0).getPm().lastIndexOf(" ") + 1).equals("优")) {
lineView.setBackgroundColor(getResources().getColor(R.color.pm1));
} else if (list.get(0).getPm().substring(list.get(0).getPm().lastIndexOf(" ") + 1).equals("良")) {
lineView.setBackgroundColor(getResources().getColor(R.color.pm2));
} else if (list.get(0).getPm().substring(list.get(0).getPm().lastIndexOf(" ") + 1).equals("轻度污染")) {
lineView.setBackgroundColor(getResources().getColor(R.color.pm3));
} else if (list.get(0).getPm().substring(list.get(0).getPm().lastIndexOf(" ") + 1).equals("中度")) {
lineView.setBackgroundColor(getResources().getColor(R.color.pm4));
} else if (list.get(0).getPm().substring(list.get(0).getPm().lastIndexOf(" ") + 1).equals("重度")) {
lineView.setBackgroundColor(getResources().getColor(R.color.pm5));
} else if (list.get(0).getPm().substring(list.get(0).getPm().lastIndexOf(" ") + 1).equals("严重")) {
lineView.setBackgroundColor(getResources().getColor(R.color.pm6));
}
// 清空水平滚动条的孙子辈视图
otherLl.removeAllViews();
// 将未来五天的天气信息动态设置到水平滚动条中的线性布局中的子视图中
for (int i = 1; i < list.size(); i++) {
View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.item, null);
TextView weekItemTv = (TextView) view.findViewById(R.id.tv_week_item);
TextView weatherItemTv = (TextView) view.findViewById(R.id.tv_weather_item);
TextView tempItemTv = (TextView) view.findViewById(R.id.tv_temp_item);
weekItemTv.setText(list.get(i).getWeek());
weatherItemTv.setText(list.get(i).getWeather());
tempItemTv.setText(list.get(i).getTemp());
// 动态将item视图添加到otherLl中
otherLl.addView(view);
}
}
}
};
weekList = new ArrayList<>();
weekList.add("星期一");
weekList.add("星期二");
weekList.add("星期三");
weekList.add("星期四");
weekList.add("星期五");
weekList.add("星期六");
weekList.add("星期日");
}
/**
* 北京
*/
private void initView() {
refreshIv = (ImageView) findViewById(R.id.refresh_iv);
searchIv = (ImageView) findViewById(R.id.search_iv);
cityTv = (TextView) findViewById(R.id.city_tv);
pmTv = (TextView) findViewById(R.id.pm_tv);
errorTv = (TextView) findViewById(R.id.error_tv);
tempTv = (TextView) findViewById(R.id.temp_tv);
weatherTv = (TextView) findViewById(R.id.weather_tv);
windTv = (TextView) findViewById(R.id.wind_tv);
dateTv = (TextView) findViewById(R.id.date_tv);
lineView = findViewById(R.id.line_view);
otherLl = (LinearLayout) findViewById(R.id.other_ll);
}
/**
* 获取网络数据
*/
private void getData(final int code) {
if (!NetUtils.isActive(MainActivity.this)) {
errorTv.setText("请确认是否有网");
Toast.makeText(MainActivity.this, "亲,确认您是否有网!", Toast.LENGTH_LONG).show();
return;
}
refreshIv.setBackgroundResource(R.drawable.pb_bg);
//封装 继承 多态
AnimationDrawable animationDrawable = (AnimationDrawable) refreshIv.getBackground();
animationDrawable.start();
// 开一个子线程进行网络请求 获取服务器json数据(注意:Android主线程不能操作耗时代码块)
new Thread(new Runnable() {
@Override
public void run() {
String uri = "http://weather.123.duba.net/static/weather_info/" + code + ".html";
String result = NetUtils.doGet(uri);
// list集合中存的今天+未来五天的天气信息
List list = parserJson(result);
Message message = handler.obtainMessage();
// 集合数据为空时让其检查网络问题,或请程序员核查代码(未彻底优化代码结构以及代码性能等)
if (list == null || list.size() == 0) {
message.what = 200;
message.obj = "请检查网络";
handler.sendMessage(message);
return;
}
message.what = 100;
message.obj = list;
handler.sendMessage(message);
// 注意:子线程不能更新UI主线程的页面
// cityTv.setText(list.get(0).getCity());
}
}).start();
}
/**
* 解析json数据
*
* @param result
*/
private List parserJson(String result) {
List list = new ArrayList<>();
try {
JSONObject jsonObject = new JSONObject(result);
JSONObject weatherInfo = jsonObject.getJSONObject("weatherinfo");
// 保存今天+未来五天的天气数据
for (int i = 1; i < 7; i++) {
WeatherBean weatherBean = new WeatherBean();
if (i == 1) {
weatherBean.setCity(weatherInfo.getString("city"));
weatherBean.setCityId(weatherInfo.getString("cityid"));
weatherBean.setDate_y(weatherInfo.getString("date_y"));
weatherBean.setPm("PM:" + weatherInfo.getString("pm") + " " + weatherInfo.getString("pm-level"));
weatherBean.setTempCurrent(weatherInfo.getString("temp") + "°");
weatherBean.setWindCurrent(weatherInfo.getString("wd") + " " + weatherInfo.getString("ws"));
}
weatherBean.setWeek(getWeek(i, weatherInfo.getString("week")));
weatherBean.setTemp(weatherInfo.getString("temp" + i));
weatherBean.setWeather(weatherInfo.getString("weather" + i));
// 将每天的天气信息保存到集合中
list.add(weatherBean);
}
return list;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* @param i
* @param week
* @return
*/
private String getWeek(int i, String week) {
int index = 0;
for (int j = 0; j < weekList.size(); j++) {
if (weekList.get(j).equals(week)) {
index = j;
break;
// continue;
}
}
if (index + i < 8) {
index = index + i - 1;
} else {
index = index + i - 8;
}
return weekList.get(index);
}
}
NetUtils(网络工具类):
package com.qianfeng.weather;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
public class NetUtils {
/**
* 监测是否有网
*/
public static boolean isActive(Context context) {
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = manager.getActiveNetworkInfo();
if (info != null) {
return info.isConnected();
}
return false;
}
/**
* 根据传过来的接口地址,返回服务器吐出来的字符串
*/
public static String doGet(String uri) {
StringBuffer stringBuffer = new StringBuffer();
String result = null;
URLConnection connection = null;
InputStream inputStream = null;
try {
URL url = new URL(uri);
connection = url.openConnection();
connection.setConnectTimeout(10 * 1000);
inputStream = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = bufferedReader.readLine();
while (line != null) {
stringBuffer.append(line);
line = bufferedReader.readLine();
}
result = stringBuffer.substring(stringBuffer.indexOf("(") + 1, stringBuffer.lastIndexOf(")"));
return result;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
WeatherBean.java
package com.qianfeng.weather;
public class WeatherBean {
private String city;
private String cityId;
private String week;
private String temp;
private String date_y;
private String wind;
private String weather;
private String pm;
private String tempCurrent;
private String windCurrent;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCityId() {
return cityId;
}
public void setCityId(String cityId) {
this.cityId = cityId;
}
public String getWeek() {
return week;
}
public void setWeek(String week) {
this.week = week;
}
public String getTemp() {
return temp;
}
public void setTemp(String temp) {
this.temp = temp;
}
public String getDate_y() {
return date_y;
}
public void setDate_y(String date_y) {
this.date_y = date_y;
}
public String getWind() {
return wind;
}
public void setWind(String wind) {
this.wind = wind;
}
public String getWeather() {
return weather;
}
public void setWeather(String weather) {
this.weather = weather;
}
public String getPm() {
return pm;
}
public void setPm(String pm) {
this.pm = pm;
}
public String getTempCurrent() {
return tempCurrent;
}
public void setTempCurrent(String tempCurrent) {
this.tempCurrent = tempCurrent;
}
public String getWindCurrent() {
return windCurrent;
}
public void setWindCurrent(String windCurrent) {
this.windCurrent = windCurrent;
}
}
3、主页面XML布局如下:
activity_main.xml:
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/background">
android:id="@+id/refresh_iv"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_margin="12dp"
android:background="@mipmap/refresh" />
android:id="@+id/search_iv"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentRight="true"
android:layout_margin="12dp"
android:background="@mipmap/search" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="12dp"
android:gravity="center_horizontal"
android:orientation="vertical">
android:id="@+id/city_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFF"
android:textSize="28sp" />
android:id="@+id/pm_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFF"
android:textSize="20sp" />
android:id="@+id/line_view"
android:layout_width="match_parent"
android:layout_height="10dp"
android:background="#6BCD07" />
android:id="@+id/error_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#F00"
android:textSize="20sp" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="12dp">
android:id="@+id/temp_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFF"
android:textSize="40sp" />
android:id="@+id/weather_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/temp_tv"
android:layout_toRightOf="@+id/temp_tv"
android:textColor="#FFF" />
android:id="@+id/wind_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/temp_tv"
android:textColor="#FFF" />
android:id="@+id/date_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/wind_tv"
android:textColor="#FFF" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
android:id="@+id/other_ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#6666"
android:orientation="horizontal">
item.xml(用在Java代码动态加载后五天天气信息Item小布局):
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingLeft="5dp"
android:paddingRight="5dp">
android:id="@+id/tv_week_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:text="星期三"
android:textColor="#FFF"
android:textSize="18sp" />
android:id="@+id/tv_weather_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="多云"
android:textColor="#FFF"
android:textSize="18sp" />
android:id="@+id/tv_temp_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:text="20°C~29°C"
android:textColor="#FFF"
android:textSize="16sp" />
4、搜索页面实现SearchActivity.java,主要包含XML解析,具体代码如下:
SearchActivity.java
package com.qianfeng.weather;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
public class SearchActivity extends AppCompatActivity {
private EditText auto = null;
private Map map = null;
private ImageView iv_search = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
initData();
initView();
}
private void initView() {
auto = (EditText) findViewById(R.id.autoTV);
iv_search = (ImageView) findViewById(R.id.iv_search);
iv_search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String city = auto.getText().toString().trim();
String codeStr = map.get(city);
if (codeStr != null) {
int code = Integer.parseInt(codeStr);
SearchActivity.this.setResult(code);
finish();
} else {
auto.setText("中国没有这样的城市,请重新输入"
+ "或"
+ "输入内容不能为空");
}
}
});
}
private void initData() {
try {
InputStream is = getAssets().open("city_code.xml");
map = new XMLParser().getMap(is);
} catch (IOException e) {
e.printStackTrace();
}
}
}
XMLParser(XML解析工具类)
package com.qianfeng.weather;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.Key;
import java.util.HashMap;
import java.util.Map;
import static java.net.Proxy.Type.HTTP;
public class XMLParser {
/**
*xml解析 pull sax 。。。
*/
public Map getMap(InputStream is) {
Map map = new HashMap<>();
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser parser = factory.newPullParser();
parser.setInput(new BufferedReader(new InputStreamReader(is)));
// parser.setInput(is,null);
// XmlPullParser.END_DOCUMENT
// XmlPullParser.START_DOCUMENT
// XmlPullParser.START_TAG
// XmlPullParser.END_TAG
// XmlPullParser.TEXT
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
String name = parser.getName();
if ("key".equals(name)) {
String key = parser.nextText();
parser.next();
parser.next();
String value = parser.nextText();
map.put(key, value);
}
}
parser.next();
eventType = parser.getEventType();
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
}
activity_search.xml(搜索页面布局)
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/background"
android:padding="5dp"
android:orientation="vertical" >
android:id="@+id/iv_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="17dp"
android:src="@mipmap/search" />
android:id="@+id/autoTV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="41dp"
android:layout_marginRight="41dp"
android:hint="请输入城市" />
5、AndroidManifest清单文件如下:
package="com.qianfeng.weather">
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
7、加载网络不好转圈动画用的自定义帧动画pb_bg.xml,具体代码如下:
android:drawable="@mipmap/pb00"
android:duration="200"/>
android:drawable="@mipmap/pb01"
android:duration="200"/>
android:drawable="@mipmap/pb02"
android:duration="200"/>
android:drawable="@mipmap/pb03"
android:duration="200"/>
android:drawable="@mipmap/pb04"
android:duration="200"/>
android:drawable="@mipmap/pb05"
android:duration="200"/>
android:drawable="@mipmap/pb06"
android:duration="200"/>
android:drawable="@mipmap/pb07"
android:duration="200"/>
android:drawable="@mipmap/pb08"
android:duration="200"/>
android:drawable="@mipmap/pb09"
android:duration="200"/>
android:drawable="@mipmap/pb10"
android:duration="200"/>
android:drawable="@mipmap/pb11"
android:duration="200"/>
6、资源图片等具体代码可参考本人共享发送上传代码资源Weather.zip