这个项目是很早之前在学校做的,如今再回首。很多代码很是粗糙,逻辑也不尽完善。还望各位看官海涵。
前言
通过上一篇文章的功能设计,我们可以发现新闻通知公告等是APP的最主要功能点。主要是聚合展示学校官网的通知公告,官方微信,微博的重要信息,学校社团的活动,以及学校优秀自媒体的文章等等。
系列文章:
- 手把手带你撸一个校园APP(一):项目简介
- 手把手带你撸一个校园APP(二):应用启动和欢迎页面
- 手把手带你撸一个校园APP(三):用户模块(登录注册等)
- 手把手带你撸一个校园APP(四):APP框架及功能设计
- 手把手带你撸一个校园APP(五):新闻中心模块
- 手把手带你撸一个校园APP(六):失物招领&二手交易模块
- 手把手带你撸一个校园APP(七):图说校园模块
- 手把手带你撸一个校园APP(八):校园通讯录模块
- 手把手带你撸一个校园APP(九):课程表模块(模拟登陆爬取教务处课程信息)
- 手把手带你撸一个校园APP(十):APP通用模块(更新,意见反馈等)
实现效果
新闻部分主要是分了“通知公告”,“新闻速递”,“自媒体”,“校园文化”四个栏目,之间可以通过左右滑动进行切换。效果图如下:
分析
其实这是挺常见的一个新闻资讯模块。我们也可以轻易得出以下内容:
- 新闻条目 一般都有标题,配图,作者,发表时间等组成。我们的新闻只是聚合展示使用,可以外加一个资讯链接;
- 配图数量并不一致,有无图的,1 张配图的,以及 3 张配图的。我们需要根据配图的数量进行不同布局的设置;
- 新闻列表应该拥有下拉刷新,上拉加载的功能。
实现
本项目基于Bmob进行开发,很多地方需要Bmob相关知识。大家如果没了解过的话,可先自行查看 Bmob开发文档 。
数据库
当初设计数据库字段的时候,很多东西都为了简单,没有做更合理的规划。字段如下:
字段名 | 描述 | 类型 | 主键 |
---|---|---|---|
objectId | 用户id | String | 是 |
title | 标题 | String | |
author | 作者 | String | |
time | 发布时间 | String | |
kind | 栏目分类 | String | |
content | 内容链接 | String | |
pic1 | 缩略图一 | String | |
pic2 | 缩略图二 | String | |
pic3 | 缩略图三 | String | |
tag | 布局样式(图片数量) | String |
大家如果自己从头来的话,建议适当更改部分字段的类型以及组合方式,会更合理些。比如time改为时间类型,图片改为列表等。本文暂且不表。
安卓
逻辑流程讲解
本模块逻辑设计如下:
- 使用CoordinatorTabLayout + ViewPager + Fragment 完成新闻模块主页面的显示;
- Fragment 进行网络请求,获取新闻数据并展示,使用 RecyclerView 展示新闻列表,根据缩略图数量对应3种条目布局;
- 新闻详情页面使用WebView 用于展示新闻详情。
代码实现
在这里为了能快速开发,我们使用了 CoordinatorTabLayout 。
文章:CoordinatorTabLayout组件库
Github地址:CoordinatorTabLayout
作者:hugeterry
使用 CoordinatorTabLayout 搭建新闻主页面
使用步骤如下:
- 在 app 的 build.gradle 中添加依赖
dependencies {
implementation 'cn.hugeterry.coordinatortablayout:coordinatortablayout:1.2.2'
}
- 布局文件中使用
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<cn.hugeterry.coordinatortablayout.CoordinatorTabLayout
android:id="@+id/cootablayout_news"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/vp_news"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</cn.hugeterry.coordinatortablayout.CoordinatorTabLayout>
</RelativeLayout>
- 在 java 代码中使用
// 四个栏目标题
String[] mTitles = {"通知公告", "新闻速递", "自媒体", "校园文化"}
// 初始化 Fragment 列表
ArrayList<Fragment> mFragments = new ArrayList<>();
mFragments.add(MainFragment1.getInstance(mTitles[0]));
mFragments.add(MainFragment2.getInstance(mTitles[1]));
mFragments.add(MainFragment3.getInstance(mTitles[2]));
mFragments.add(MainFragment4.getInstance(mTitles[3]));
// 设置Viewpager
mViewPager.setOffscreenPageLimit(4);
mViewPager.setAdapter(new MyPagerAdapter(getChildFragmentManager(), mFragments, mTitles));
// 设置顶部 展开后 4 张背景图
mImageArray = new int[]{
R.mipmap.keshi1,
R.mipmap.keshi4,
R.mipmap.img_bg_news3,
R.mipmap.img_bg_news4};
// 设置顶部 收缩后 4 种背景色
mColorArray = new int[]{
android.R.color.holo_blue_light,
android.R.color.holo_red_light,
android.R.color.holo_orange_light,
android.R.color.holo_green_light};
// 设置 CoordinatorTabLayout 属性
mCoordinatorTabLayout.setTransulcentStatusBar(mActivity)
.setTitle("")
.setImageArray(mImageArray, mColorArray)
.setupWithViewPager(mViewPager);
网络请求,数据填充
- 建立数据库对应表 bean 类
public class NewsBean extends BmobObject {
private String title;
private String author;
private String time;
private String tag;
private String pic1;
private String pic2;
private String pic3;
private String content;
// ....get set 方法
}
- 网络请求数据,并填充
mAdapter = new NNNAdapter();
newsBeanList = new ArrayList<>();
BmobQuery<NewsBean> query = new BmobQuery<NewsBean>();
query.order("-time");
// kind: [a="通知公告", b="新闻速递", c="自媒体", d="校园文化"]
query.addWhereEqualTo("kind", "a");
query.setLimit(10);
query.findObjects(new FindListener<NewsBean>() {
@Override
public void done(List<NewsBean> object, BmobException e) {
if (e == null) {
for (NewsBean newsBean : object) {
newsBeanList.add(newsBean);
LogUtils.e(newsBean.getAuthor());
}
mAdapter.setData(newsBeanList);
} else {
}
}
});
mRecyclerView.setAdapter(mAdapter);
- 图片数量不同对应不同的布局
public class NewsBean extends BmobObject implements IMultiItem {
@Override
public int getLayoutRes() {
if ("3".equals(tag)) {
return R.layout.item_news_type3;
} else if ("2".equals(tag)) {
return R.layout.item_news_type2;
} else {
return R.layout.item_news_type1;
}
}
// 省略其它...
}
- 新闻详情页面
Fragment 中给 RecycleView 设置点击事件,传递网址到详情Activity
mAdapter.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(@NonNull View view, int position) {
Intent intent = new Intent(getActivity(), NewsWebActivity.class);
intent.putExtra("url", newsBeanList.get(position).getContent());
startActivity(intent);
}
});
网页详情页面 NewsActivity 中只有一个WebView。接收上个页面传递过来的参数,并且展示页面。这里做了一些初始化操作,大家在别处需要的话,也可以直接复制过去
String url = getIntent().getStringExtra("url");
if (TextUtils.isEmpty(url)) {
Toast.makeText(this, "该新闻已经失效!", Toast.LENGTH_SHORT).show();
return;
}
MyWebViewClient myWebViewClient = new MyWebViewClient();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
wvNews.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
wvNews.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);//设置js可以直接打开窗口,如window.open(),默认为false
wvNews.getSettings().setJavaScriptEnabled(true);//是否允许执行js,默认为false。设置true时,会提醒可能造成XSS漏洞
wvNews.getSettings().setSupportZoom(true);//是否可以缩放,默认true
wvNews.getSettings().setBuiltInZoomControls(true);//是否显示缩放按钮,默认false
wvNews.getSettings().setUseWideViewPort(true);//设置此属性,可任意比例缩放。大视图模式
wvNews.getSettings().setLoadWithOverviewMode(true);//和setUseWideViewPort(true)一起解决网页自适应问题
wvNews.getSettings().setAppCacheEnabled(true);//是否使用缓存
wvNews.getSettings().setDomStorageEnabled(true);//DOM Storage
wvNews.setWebChromeClient(new WebChromeClient());
wvNews.setWebViewClient(myWebViewClient);
wvNews.loadUrl(url);
// ....
private class MyWebViewClient extends WebViewClient {
//重写父类方法,让新打开的网页在当前的WebView中显示
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
至此,新闻模块页面基本完成。还有就是本文挺长的,很感谢你可以看到这里。
如果本文对你有所帮助,还望可以随手赏一个点赞哈 ~ ~