前言:
正在做一个资讯类app,打算一边做一边整理,供自己学习与巩固。用到的知识复杂度不高,仅适于新手。经验不多,如果写出来的代码有不好的地方欢迎讨论。
以往的内容
第一章 滑动顶部导航栏
第二章 retrofit获取网络数据
第三章 新闻模块
本章内容最终效果:
知识点:
RecyclerView.Adapter,CoordinatorLayout,AppBarLayout,cardView,Glide,WebView
学习目标:
1、使用RecyclerView、cardView显示列表数据。
2、使用Glide加载图片。
3、WebView显示网页。
新闻模块是资讯类App的主体,主要内容包括新闻列表,新闻详情。
项目实战:
注意
本章用到的drawable资源、values资源皆存放在百度网盘
(请将values文件夹中的style.xml或color.xml更新一致后再运行,如有后续更新自行修改)
1.1 项目结构
本章增加的类和布局:
需导入的库:
导入了cardView和图片加载库Glide。
1.2 item_news及适配器
新闻的显示需要用RecyclerView,所以先完成每个新闻item的代码。
新建一个布局文件,命名为item_news。
然后为我们的item_news写上适配器代码。
新建一个java文件,命名为ItemNewsAdapter。
public class ItemNewsAdapter extends RecyclerView.Adapter {
private List objects = new ArrayList();
private Context context;
public ItemNewsAdapter(Context context) {
this.context = context;
}
public void setData(List objects) {
this.objects = objects;
}
@Override
public ItemNewsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_news, parent, false);
return new ItemNewsHolder(view);
}
@Override
public void onBindViewHolder(ItemNewsHolder holder, int position) {
NewsBean.Bean bean = objects.get(position);
if (bean == null) {
return;
}
Glide.with(context)
.load(bean.getImgsrc())
.into(holder.ivNewsImg);
if (position == 0) {
holder.tvNewsDigest.setVisibility(View.GONE);
holder.tvNewsTitle.setText("图片:" + bean.getTitle());
} else {
holder.tvNewsTitle.setText(bean.getTitle());
holder.tvNewsDigest.setText(bean.getMtime() + " : " + bean.getDigest());
}
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemCount() {
return objects.size();
}
protected class ItemNewsHolder extends RecyclerView.ViewHolder {
private ImageView ivNewsImg;
private TextView tvNewsTitle;
private TextView tvNewsDigest;
public ItemNewsHolder(View view) {
super(view);
ivNewsImg = (ImageView) view.findViewById(R.id.iv_news_img);
tvNewsTitle = (TextView) view.findViewById(R.id.tv_news_title);
tvNewsDigest = (TextView) view.findViewById(R.id.tv_news_digest);
}
}
}
这里面的图片加载用到的是Glide,这是谷歌推荐的图片加载库,加载速度快,引用也很简单。只需下面3行代码就能用。
中间对控件的处理也是基于api返回的数据(网易新闻接口会图片新闻的数据),这里只是做了个简单的处理,具体优化还需要进一步分析接口数据。
1.3 RecycleView
接下来我们让刚才做的item在fragment里显示出来。
首先修改fg_news_list的布局代码,加入RecycleView:
fg_news_list.xml
然后修改FgNewsListFragment的代码:
FgNewsListFragment.java
public class FgNewsListFragment extends Fragment implements INewsView {
private NewsPresenter presenter;
private int type;
private SwipeRefreshLayout srl_news;
private RecyclerView rv_news;
private ItemNewsAdapter adapter;
private List newsBeanList;
private TextView tv_news_list;
public static FgNewsListFragment newInstance(int type) {
Bundle args = new Bundle();
FgNewsListFragment fragment = new FgNewsListFragment();
args.putInt("type", type);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fg_news_list, null);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
type = getArguments().getInt("type");
presenter = new NewsPresenter(this);
rv_news = view.findViewById(R.id.rv_news);
adapter = new ItemNewsAdapter(getActivity());
tv_news_list = view.findViewById(R.id.tv_news_list);
srl_news = view.findViewById(R.id.srl_news);
srl_news.setColorSchemeColors(Color.parseColor("#ffce3d3a"));
srl_news.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
presenter.loadNews(type, 0);
}
});
presenter.loadNews(type, 0);
}
@Override
public void showNews(final NewsBean newsBean) {
switch (type) {
case FgNewsFragment.NEWS_TYPE_TOP:
newsBeanList = newsBean.getTop();
break;
case FgNewsFragment.NEWS_TYPE_NBA:
newsBeanList = newsBean.getNba();
break;
case FgNewsFragment.NEWS_TYPE_JOKES:
newsBeanList = newsBean.getJoke();
break;
}
adapter.setData(newsBeanList);
rv_news.setLayoutManager(new LinearLayoutManager(getActivity(),
LinearLayoutManager.VERTICAL, false));
rv_news.setAdapter(adapter);
tv_news_list.setVisibility(View.GONE);
}
@Override
public void hideDialog() {
srl_news.setRefreshing(false);
}
@Override
public void showDialog() {
srl_news.setRefreshing(true);
}
@Override
public void showErrorMsg(String error) {
tv_news_list.setText("加载失败:" + error);
}
}
效果:
1.4 CardView
每一个新闻怎么做到卡片显示呢?这里我们用到了控件cardView。
cardView的使用非常简单,我把一些设置直接写在布局里了,不需要写别的逻辑代码,只要把item_news里的东西包裹进去就好了。
item_news.xml
效果:
2.1 CoordinatorLayout与AppBarLayout
当滑动列表的时候,为了给屏幕腾出更多空间,上面的导航栏会有折叠的效果,这里就要用到CoordinatorLayout和AppBarLayout了。
到main_content文件里将最外层包裹上CoordinatorLayout,在将Toolbar放进AppBarLayout:
main_content.xml
AppBarLayout里有一个elevation属性,可以将bar浮起来,既然Toolbar浮到5,那么把fg_news里的TabLayout也浮到5吧。
fg_news.xml
效果:
3.1 WebView打开新闻详情网页
点击每个新闻卡片后,出现的新闻详情我直接用WebView显示。
新建布局文件a_detail(新增加的图片资源到我上面的网盘地址里找):
a_detail.xml
然后写WebView的Activity代码:
ADetailActivity.java
public class ADetailActivity extends Activity {
private WebView wbNews;
private String loadUrl, title;
private WebViewClient webViewClient;
private TextView tv_bar_title;
private ImageView iv_back;
private ProgressBar pb_load;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.a_detail);
loadUrl = getIntent().getStringExtra("url");
title = getIntent().getStringExtra("title");
initView();
setWebViewClient();
}
private void setWebViewClient() {
webViewClient = new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
pb_load.setVisibility(View.VISIBLE);
}
@Override
public void onPageFinished(WebView view, String url) {
pb_load.setVisibility(View.GONE);
}
};
wbNews.setWebViewClient(webViewClient);
}
private void initView() {
wbNews = (WebView) findViewById(R.id.wb_news);
wbNews.getSettings().setJavaScriptEnabled(true);
wbNews.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
wbNews.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
wbNews.canGoBack();
wbNews.canGoForward();
wbNews.loadUrl(loadUrl);
tv_bar_title = (TextView) findViewById(R.id.tv_bar_title);
tv_bar_title.setText(title);
iv_back = (ImageView) findViewById(R.id.iv_back);
iv_back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
pb_load = (ProgressBar) findViewById(R.id.pb_load);
}
@Override
protected void onDestroy() {
super.onDestroy();
wbNews.destroy();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == event.KEYCODE_BACK && wbNews.canGoBack()) {
wbNews.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
在ItemNewsAdapter里把跳转页面的代码补上:
到manifest文件中声明Activity:
效果:
本章的新闻模块显示的列表数量是有限的,这是因为还没做“加载更多”的功能,这些在以后有时间在慢慢优化。
项目源码:https://github.com/Huigesi/IdleReaderDemo
上一章:
第二章 滑动顶部导航栏
下一章:
第四章 电影模块