自己开发的项目里,添加了一个简易的“手机号码归属地查询”模块,纯手撸,没有采用第三方框架。
效果图:
开发思路:
界面实现--->获取数据--->数据处理--->界面展示
具体实现:
1. 界面实现
界面绘制比较简单,就不放代码了,其中为EditText做了几点处理:
- 自定义背景
bg_edit_selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_edit_normal" android:state_focused="false" />
<item android:drawable="@drawable/bg_edit_selected" android:state_focused="true" />
</selector>
bg_edit_normal:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="1dp"
android:color="@color/normalBlue" />
<corners android:radius="5dp" />
<solid android:color="@android:color/transparent" />
<padding
android:bottom="10dp"
android:left="12dp"
android:right="12dp"
android:top="10dp" />
</shape>
bg_edit_selected:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/transparent" />
<stroke
android:width="2dp"
android:color="@color/lightBlue" />
<corners android:radius="5dp" />
<padding
android:bottom="10dp"
android:left="12dp"
android:right="12dp"
android:top="10dp" />
</shape>
- 添加动画效果,简单的透明度、伸缩变化
java:
Animation animPhone = AnimationUtils.loadAnimation(this, R.anim.edit_phone_anim);
edtPhone.startAnimation(animPhone);
xml:tv_phone_result_anim
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="200"
android:fromAlpha="1.0"
android:repeatCount="1"
android:repeatMode="reverse"
android:toAlpha="0.3" />
- 点击查询按钮后隐藏键盘
private void hideKeyboard(View view) {
InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (im.isActive(view)) {
im.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0);
}
}
2. 获取数据
- 选用百度的API,写在项目的Consts类里:
public class Consts {
public static final String BAIDU_PHONE_URL = "http://mobsec-dianhua.baidu.com/dianhua_api/open/location";
}
- 自己开辟线程,执行网络请求,读取数据:
class PhoneThread extends Thread {
private String url;
private String number;
private PhoneThread(String url, String number) {
this.url = url;
this.number = number;
}
/**
* 子线程不能直接弹出Toast(其实就是子线程更新UI),方法:
* 1. Looper.prepare(); Looper.loop();
* 2. runOnUiThread(new Runnable(){});
* 3. mHandler.senMessage();
*/
@Override
public void run() {
String result = getJsonFromURL(url);
if (TextUtils.isEmpty(result)) {
Looper.prepare();
Toast.makeText(AttributionActivity.this, R.string.attribution_return_null,
Toast.LENGTH_SHORT).show();
Looper.loop();
} else {
Phone phone = parseJsonToPhone(result, number);
Message msg = Message.obtain();
msg.obj = phone;
mPhoneHandler.sendMessage(msg);
}
}
}
3. 数据处理
- 自定义Phone类(getter()、setter()和toString()略):
public class Phone {
private String number;
private String province;
private String carrier;
private String ownerCarrier;
}
- 解析json:使用Android自带的JSONObject,当然Gson和FastJson更方便
private Phone parseJsonToPhone(String url, String number) {
Phone phone = new Phone();
try {
JSONObject object = new JSONObject(url);
JSONObject numberObj = object.getJSONObject("response").getJSONObject(number);
JSONObject detailObj = numberObj.getJSONObject("detail");
phone.setNumber(number);
phone.setProvince(detailObj.getString("province"));
phone.setCarrier(detailObj.getString("operator"));
phone.setOwnerCarrier(numberObj.getString("location"));
} catch (JSONException e) {
e.printStackTrace();
}
return phone;
}
- 自定义Handler,用于子线程向主线程发送数据,更新UI:
@SuppressLint(&