手把手带你撸一个校园APP(五):新闻中心模块

这个项目是很早之前在学校做的,如今再回首。很多代码很是粗糙,逻辑也不尽完善。还望各位看官海涵。

前言

通过上一篇文章的功能设计,我们可以发现新闻通知公告等是APP的最主要功能点。主要是聚合展示学校官网的通知公告,官方微信,微博的重要信息,学校社团的活动,以及学校优秀自媒体的文章等等。

系列文章:

  1. 手把手带你撸一个校园APP(一):项目简介
  2. 手把手带你撸一个校园APP(二):应用启动和欢迎页面
  3. 手把手带你撸一个校园APP(三):用户模块(登录注册等)
  4. 手把手带你撸一个校园APP(四):APP框架及功能设计
  5. 手把手带你撸一个校园APP(五):新闻中心模块
  6. 手把手带你撸一个校园APP(六):失物招领&二手交易模块
  7. 手把手带你撸一个校园APP(七):图说校园模块
  8. 手把手带你撸一个校园APP(八):校园通讯录模块
  9. 手把手带你撸一个校园APP(九):课程表模块(模拟登陆爬取教务处课程信息)
  10. 手把手带你撸一个校园APP(十):APP通用模块(更新,意见反馈等)

实现效果

新闻部分主要是分了“通知公告”,“新闻速递”,“自媒体”,“校园文化”四个栏目,之间可以通过左右滑动进行切换。效果图如下:
科师有约新闻模块

分析

其实这是挺常见的一个新闻资讯模块。我们也可以轻易得出以下内容:

  1. 新闻条目 一般都有标题,配图,作者,发表时间等组成。我们的新闻只是聚合展示使用,可以外加一个资讯链接;
  2. 配图数量并不一致,有无图的,1 张配图的,以及 3 张配图的。我们需要根据配图的数量进行不同布局的设置;
  3. 新闻列表应该拥有下拉刷新,上拉加载的功能。

实现

本项目基于Bmob进行开发,很多地方需要Bmob相关知识。大家如果没了解过的话,可先自行查看 Bmob开发文档

数据库

当初设计数据库字段的时候,很多东西都为了简单,没有做更合理的规划。字段如下:

字段名描述类型主键
objectId用户idString
title标题String
author作者String
time发布时间String
kind栏目分类String
content内容链接String
pic1缩略图一String
pic2缩略图二String
pic3缩略图三String
tag布局样式(图片数量)String

大家如果自己从头来的话,建议适当更改部分字段的类型以及组合方式,会更合理些。比如time改为时间类型,图片改为列表等。本文暂且不表。

安卓

逻辑流程讲解

本模块逻辑设计如下:

  1. 使用CoordinatorTabLayout + ViewPager + Fragment 完成新闻模块主页面的显示;
  2. Fragment 进行网络请求,获取新闻数据并展示,使用 RecyclerView 展示新闻列表,根据缩略图数量对应3种条目布局;
  3. 新闻详情页面使用WebView 用于展示新闻详情。
代码实现

在这里为了能快速开发,我们使用了 CoordinatorTabLayout 。

文章:CoordinatorTabLayout组件库
Github地址:CoordinatorTabLayout
作者:hugeterry

使用 CoordinatorTabLayout 搭建新闻主页面

使用步骤如下:

  1. 在 app 的 build.gradle 中添加依赖
dependencies {
    implementation 'cn.hugeterry.coordinatortablayout:coordinatortablayout:1.2.2'
}
  1. 布局文件中使用
<?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>
  1. 在 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);
网络请求,数据填充
  1. 建立数据库对应表 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 方法
}
  1. 网络请求数据,并填充
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);
  1. 图片数量不同对应不同的布局
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;
        }
    }
    // 省略其它...
}
  1. 新闻详情页面
    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;
    }
}

至此,新闻模块页面基本完成。还有就是本文挺长的,很感谢你可以看到这里。

如果本文对你有所帮助,还望可以随手赏一个点赞哈 ~ ~

贝叶斯优化是一种基于贝叶斯定理的优化算法,可以用于求解黑盒函数的最优解。Python中有很多库可以实现贝叶斯优化算法,其中比较常用的是scikit-optimize和BayesianOptimization。 scikit-optimize库实现了多种全局优化算法,其中包括贝叶斯优化算法。以下是一个简单的示例代码: ``` from skopt import gp_minimize from skopt.space import Real def objective(x): return (x-2)**2 + (x+3)**2 space = [Real(-10, 10, name='x1'), Real(-5, 5, name='x2')] res = gp_minimize(objective, space) print("Minimum value found: %f" % res.fun) print("Minimum location found: ", res.x) ``` 在这个例子中,我们定义了一个目标函数objective,该函数接受一个长度为2的向量作为输入,并返回一个标量输出。我们使用gp_minimize函数来最小化这个函数,并指定搜索空间为两个连续变量x1和x2。最终,我们得到了最小值和最小值所在位置的输出。 BayesianOptimization库也提供了一个类似的API,以下是一个简单的示例代码: ``` from bayes_opt import BayesianOptimization def objective(x, y): return -(x**2 + (y-1)**2) pbounds = {'x': (-10, 10), 'y': (-5, 5)} optimizer = BayesianOptimization( f=objective, pbounds=pbounds, random_state=1, ) optimizer.maximize(n_iter=10) print(optimizer.max) ``` 在这个例子中,我们定义了一个目标函数objective,该函数接受两个连续变量x和y作为输入,并返回一个标量输出。我们使用BayesianOptimization类来最大化这个函数,并指定搜索空间为两个变量x和y。最终,我们得到了最大值和最大值所在位置的输出。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值