实时地震查询
-
EarthQuakeAPP.zip
地震信息查询App,这是我在大二寒假时间开发的,使用了volly+jsoup+MPAndroidChart+bottom-navigation-bar等第三方开源库,数据来源是:中国地震台网,jsoup解析xml,该App内还有天气查询的功能,数据来源是:和风天气,还有百度地图功能,定位功能等。是一款综合性比较强的Android案例,需要的下载去学习,情况本人博客中的演示效果:https://blog.csdn.net/smile_Running/article/details/94502113(大伙觉得不错的给个赞和评论哦,您的点赞和评论就是写作的动力!)
立即下载
博主声明:
转载请在开头附加本文链接及作者信息,并标记为转载。本文由博主 威威喵 原创,请多支持与指教。
本文首发于此 博主:威威喵 | 博客主页:https://blog.csdn.net/smile_running
这是一款地震信息查询App,说是地震信息查询,但我又结合了天气查询,百度地图、定位等功能。这是在2018年那个大二寒假期间开发的,主要是当初回到家里没事情干,就随手写了一个Demo,由于比赛集训的原因,我的寒假被压缩只剩半个月,后来到学校就去比赛了,忙着比赛的事情,就无暇顾及这个 App 的工作进度,导致很多功能都没有实现。希望以后我有时间再去完善吧!
下面我把已经实现的功能及运用到 Android 技术点介绍一下。
- bottom-navigation-bar
- okhttp
- volley
- tosaty
- glide
- MPAndroidChart
- nineoldandroids
- gson
- jsoup
- baiduMap SDk
本项目数据来源与感谢:
中国地震台网
和风天气
之前对 Android 的学习与了解比较浅,也是在 Android 刚入门时候编写的此项目,所以本项目有很多不足的地方,代码冗余、程序没有优化,但给予初学者的帮助还是足够多了,需要的可以下载本项目,或者可以作为 Android 课程的作业,也足够了,哈哈!
项目下载地址:地震信息查询App
介绍完了本项目的开发背景,下面我们来看看这个 App 到底有什么功能,我们来看截图吧!
首先,一打开项目,就是我们的主页面了,主页面包含四个 Fragment 和一个侧拉导航 drawerlayout ,DrawerLayout 是常见的功能,类似于 QQ 的侧拉个人信息一样。
主页下面底部按钮使用的就是 bottom-navigation-bar 来创建的四个底部按钮,头部是一个 spinner 控件,中间是用于显示地震信息的 recyclerview 控件。数据是使用 jsoup 爬取 中国地震台网 的数据,解析 xml 标签得到一条一套的数据再显示,在recyclerview 往下滑动的时候,会开启一个滑动的缩放动画,并且滑倒一定数据量是,有一个 top 的返回到顶部的功能。
动态效果图:
在适配器中加入动画效果代码:
ObjectAnimator scaleX = ObjectAnimator.ofFloat(holder.itemView, "scaleX", 0.5f, 1f);
scaleX.start();
mLastPosition = holder.getLayoutPosition();
第二个 Fragment 是百度地图的显示功能,可以根据当前定位信息来显示对应的地图,因为模拟器的原因,自己可以放手机上尝试。这里要注意一点,如果你把项目重新编译运行后,要记得修改自己的百度地图密钥,否则无法显示地图!
动态效果图:
这里有一个问题要解决,就是 viewpager 与 百度地图的 控件会发生事件冲突,所以在 MapView 这个页面时,我将ViewPager 的滑动事件交与 MapView 处理,我重写了 ViewPager 的 canscroll 事件,判断当前的 View 是否是 MapView,如果是,ViewPager 禁止滑动事件,由 MapView 去消费。
@Override
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
if (v.getClass().getName().equals("com.baidu.mapapi.map.MapView")) {
return true;
} else {
return super.canScroll(v, checkV, dx, x, y);
}
}
然后,我们接着来看侧拉导航里面的菜单,实现了定位与显示功能,相机功能,天气信息显示功能与天气模块。
动态效果图:
我们来看看【我的位置】这个菜单功能,进入这个页面,就是单纯的使用 TextView 显示当前的定位信息与地址,默认位置是北京。
动态效果图:
可以看到这里的 ScrollView 的滑动,当滑倒顶部与底部的时候,内容都会随着手指滑动出屏幕以外的区域,然后松开的时候会自动的回弹到原先的位置,这也是一个自定义的 ScrollView ,重写了 onTouchEvent 事件,我是通过获取 ScrollView 中子 View 的实例,通过计算手指滑动时 View 的滑动距离来重新布局,调用 view.layout() 方法,改变 View 的位置来达到目的。
public class BaseScrollView extends ScrollView {
private View inner;// 孩子View
private float y;// 点击时y坐标
private Rect normal = new Rect();// 矩形(这里只是个形式,只是用于判断是否需要动画.)
private boolean isCount = false;// 是否开始计算
public BaseScrollView(context context, AttributeSet attrs) {
super(context, attrs);
}
/***
* 根据 XML 生成视图工作完成.该函数在生成视图的最后调用,在所有子视图添加完之后. 即使子类覆盖了 onfinishinflate
* 方法,也应该调用父类的方法,使该方法得以执行.
*/
@Override
protected void onFinishInflate() {
if (getChildCount() > 0) {
inner = getChildAt(0);
}
}
/***
* 监听touch
*/
@Override
public boolean onTouchEvent(motionevent ev) {
if (inner != null) {
commOnTouchEvent(ev);
}
return super.onTouchEvent(ev);
}
/***
* 触摸事件
*
* @param ev
*/
public void commOnTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_UP:
// 手指松开.
if (isNeedAnimation()) {
animation();
isCount = false;
}
break;
/***
* 排除出第一次移动计算,因为第一次无法得知y坐标, 在MotionEvent.ACTION_DOWN中获取不到,
* 因为此时是MyScrollView的touch事件传递到到了listview的孩子item上面.所以从第二次计算开始.
* 然而我们也要进行初始化,就是第一次移动的时候让滑动距离归0. 之后记录准确了就正常执行.
*/
case MotionEvent.ACTION_MOVE:
final float preY = y;// 按下时的y坐标
float nowY = ev.getY();// 时时y坐标
int deltaY = (int) (preY - nowY);// 滑动距离
if (!isCount) {
deltaY = 0; // 在这里要归0.
}
y = nowY;
// 当滚动到最上或者最下时就不会再滚动,这时移动布局
if (isNeedMove()) {
// 初始化头部矩形
if (normal.isempty()) {
// 保存正常的布局位置
normal.set(inner.getLeft(), inner.getTop(),
inner.getRight(), inner.getBottom());
}
// 移动布局
inner.layout(inner.getLeft(), inner.getTop() - deltaY / 2,
inner.getRight(), inner.getBottom() - deltaY / 2);
}
isCount = true;
break;
default:
break;
}
}
/***
* 回缩动画
*/
public void animation() {
// 开启移动动画
translateanimation ta = new TranslateAnimation(0, 0, inner.getTop(),
normal.top);
ta.setDuration(200);
inner.startAnimation(ta);
// 设置回到正常的布局位置
inner.layout(normal.left, normal.top, normal.right, normal.bottom);
normal.setEmpty();
}
// 是否需要开启动画
public boolean isNeedAnimation() {
return !normal.isEmpty();
}
/***
* 是否需要移动布局 inner.getmeasuredHeight():获取的是控件的总高度
* <p>
* getHeight():获取的是屏幕的高度
*
* @return
*/
public boolean isNeedMove() {
int offset = inner.getMeasuredHeight() - getHeight();
int scrollY = getScrollY();
// 0是顶部,后面那个是底部
if (scrollY == 0 || scrollY == offset) {
return true;
}
return false;
}
}
接下来是【气象中心】菜单按钮,这里接入的是 和风天气 api,但是由于之前写的比较早,和风天气 api 现在已经做了升级了,有写 Json 数据返回被删除或修改了,已经获取不到数据值了,会报空指针异常,这里我也不做多的修改了。
实现的功能有这些,中间区域的 小时预报 是用了 MPAndroidChart 开源库来绘制了一条温度的曲线图,由于 api 的原因,导致现在数据显示不出来了。还有用到了 ViewPager + 切换的缩放动画效果,背景是必应每日一图,这个天气是参考郭霖大佬的《第一行代码》书籍里面的酷欧天气写的,但界面被我完全的修改了,改成自己设计的一套界面。
动态效果图
这里用了两个 ViewPager 切换动画的封装,一种是缩放动画,另一种是旋转动画。
public class ViewPagerTrans_Zoom implements PageTransformer {
public static final float MIN_SCALE = 0.85f;
public static final float MIN_ALPHA = 0.5f;
@Override
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position < -1) {
view.setAlpha(0);
} else if (position <= 1) {
float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (position < 0) {
view.setTranslationX(horzMargin - vertMargin / 2);
} else {
view.setTranslationY(vertMargin - horzMargin / 2);
}
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE)
/ (1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else {
view.setAlpha(0);
}
}
}
public class ViewPagerTrans_Rotate implements PageTransformer {
private static final float ROT_MAX = 20.0f;
private float mRot;
@Override
public void transformPage(View view, float position) {
if (position < -1) {
ViewHelper.setRotation(view, 0);
} else if (position <= 1) {
if (position < 0) {
mRot = (ROT_MAX * position);
ViewHelper.setPivotX(view, view.getMeasuredWidth() * 0.5f);
ViewHelper.setPivotY(view, view.getMeasuredHeight());
ViewHelper.setRotation(view, mRot);
} else {
mRot = (ROT_MAX * position);
ViewHelper.setPivotX(view, view.getMeasuredWidth() * 0.5f);
ViewHelper.setPivotY(view, view.getMeasuredHeight());
ViewHelper.setRotation(view, mRot);
}
} else {
ViewHelper.setRotation(view, 0);
}
}
}
看上面 ViewPager 切换时底部会有一个小圆点也跟着切换,这个是 ViewPagerIndicator(指示器),其实可以把它看作一个横向的 LinearLayout ,然后动态的往里面添加 ImageView 并设置不同的图片,根据 ViewPager 提供的 onPageChangeListener 接口来监听当前 ViewPager 所显示的页面来动态的设置 ImageView 的图片。
public class MyViewpagerIndicator implements ViewPager.OnPageChangeListener {
private Context mContext;
private int mPageCount;
private LinearLayout mLinearLayout;
private int imgSelect, imgUnselect;
private int imgSize;
private List<ImageView> imgList;
/**
* @context 上下文
* @linearLayout 父容器
* @pageCount 页面数
* @imgSize 图片大小
* @imgSelect 选中时的图片
* @imgUnselect 未选中时的图片
*/
public MyViewpagerIndicator(Context context, LinearLayout linearLayout,
int pageCount, int imgSize, int imgSelect, int imgUnselect) {
imgList = new ArrayList<>();
this.mContext = context;
this.mLinearLayout = linearLayout;
this.mPageCount = pageCount;
this.imgSize = imgSize;
this.imgSelect = imgSelect;
this.imgUnselect = imgUnselect;
for (int i = 0; i < mPageCount; i++) {
ImageView imageView = new ImageView(mContext);
LinearLayout.layoutparams params = new LinearLayout.LayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.wrap_content, ViewGroup.LayoutParams.WRAP_CONTENT));
//为小圆点左右添加间距
params.leftMargin = 10;
params.rightMargin = 10;
//手动给小圆点一个大小
params.height = imgSize;
params.width = imgSize;
if (i == 0) {
imageView.setBackgroundResource(imgSelect);
} else {
imageView.setBackgroundResource(imgUnselect);
}
//为LinearLayout添加ImageView
mLinearLayout.addView(imageView, params);
imgList.add(imageView);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
for (int i = 0; i < mPageCount; i++) {
//选中的页面改变小圆点为选中状态,反之为未选中
if ((position % mPageCount) == i) {
((View) imgList.get(i)).setBackgroundResource(imgSelect);
} else {
((View) imgList.get(i)).setBackgroundResource(imgUnselect);
}
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
到此为止,本项目的实现的功能及展示结束了,还有一些边边角角的地方没有提及,大家可以下载源码自行增改与完善。
项目下载地址:地震信息查询App
分享既是快乐,感谢您的阅读。尊重他人劳动成果,转载请附加博客原文链接。点赞是一种积极的生活态度! |
相关阅读
ACM:下面是512汶川大地震部分受灾学校伤亡情况(惨痛!!)
/*Problem Description下面是512汶川大地震部分受灾学校伤亡情况(惨痛!!)<br><br>1、 四川省都江堰市 聚源中学<br>伤亡情况:遇难学生
**kaggle地震剩余时间预测挑战(一) 写在前面的话 这是我第一次参加kaggle的挑战,希望能够记录下来,并且给你们分享,在这里我会记录我的
今天是汶川大地震八周年,各地开展活动悼念地震中遇难的同胞,回顾那些定格的瞬间,祭奠历史,悼念遇难者。
地震是地壳快速释放能量过程中造成振动,产生地震波的一种自然现象。主要原因是由于地球上板块与板块之间相互挤压碰撞,造成板块边沿
1975年2月4日19时36分,在辽宁省海城、营口一带发生7.3级强烈地震。震源深度为16公里,震中烈度为9度强。