新闻客户端案例开发
最后更新于:2022-04-01 14:32:38
新闻客户端,顾名思义就是看新闻用的客户端。
该新闻用到的知识模块有:android高级界面设计(Fragment、ViewPager),android网络通信(http通信),开源组件(xutils框架-HttpUtils模块、xutils框架-BitmapUtils模块),开源框架(library)。所需jar包:xUtils、gson、android-support-v4。
主界面滑动标签:library框架用于主界面标签
•主界面ViewPager:ViewPager与上部分的library框架结合做成Fragment动态效果
•ListView中的每个Item:
•HttpUtils模块进行是用于进行访问网络,获取json数据
•BitmapUtils模块进行网络图片的加载和显示
•android-support-v4.jar包提供ViewPager控件
•library开源代码框架库,是用来实现简易新闻客户端上端的滑动标签,同时它与ViewPager控件结合最终实现的是[Fragment](http://blog.csdn.net/sdksdk0/article/details/Fragment%E4%BB%8B%E7%BB%8D.doc)的动态实现。
•简易新闻客户端上端滑动标签是用了library开源代码框架中的com.viewpagerindicator.TabPageIndicator控件
•ViewPager控件是android-support-v4.jar包中的android.support.v4.view.ViewPager控件。
•用了com.viewpagerindicator.TabPageIndicator这个控件之后,要对界面主题(Theme)进行修改,在styles.xml文件中创建相关的style
首先导入libary库:千万不要直接把库拷贝进项目文件夹中,这样可能会出现各种其他不知名的错误,建议通过Import Module方式一步步导入库文件。然后在file->project structure->dependencies->3Model dependency中选择library库就可以了,还要在2中导入一个gson.jar和xUtils.jar。此时库已成功导入。
我们首先来写布局文件,activity_main.xml
~~~
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<include
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="@dimen/header_height"
layout="@layout/header"/>
<com.viewpagerindicator.TabPageIndicator
android:id="@+id/indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/header">
</com.viewpagerindicator.TabPageIndicator>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/indicator">
</android.support.v4.view.ViewPager>
</RelativeLayout>
~~~
第2个是头部header.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/header_height"
android:background="@mipmap/setting_iv_bg"
android:gravity="center">
<TextView
android:text="@string/header_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/header_text_size"
/>
</RelativeLayout>
~~~
第三个是下面的viepage页面,fragment.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/newsList"
android:layout_width="match_parent"
android:layout_height="wrap_content"></ListView>
</LinearLayout>
~~~
以及细节部分fragment_list_item.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:id="@+id/newIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:src="@mipmap/skyblue_logo_whatsapp_checked"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_toRightOf="@+id/newIcon"
>
<TextView
android:id="@+id/newTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/newTitleTxtSize"
/>
<TextView
android:id="@+id/newTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/newTimeTxtSize"
/>
</LinearLayout>
</RelativeLayout>
~~~
既然是一个新闻客户端那必须要有数据,那么数据当然就需要json解析来从第三方网站获取新闻数据,下面来简要介绍一下json数据的解析过程。
•JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它基于ECMAScript的一个子集。JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C、C++、C#、Java、JavaScript、Perl、Python等)。这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成(一般用于提升网络传输速率)。
这个时候我们需要在src中新建一个bean类来存放json的数据
~~~
public class jsonBean {
private String title;
private String url;
private String listimage;
private String pubdate;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getListimage() {
return listimage;
}
public void setListimage(String listimage) {
this.listimage = listimage;
}
public String getPubdate() {
return pubdate;
}
public void setPubdate(String pubdate) {
this.pubdate = pubdate;
}
}
~~~
然后再bean中再创建一个ListBean.java,用于存取多个新闻的内容,这里面需要两个内部类,通过data获取NewsList,然后通过NewsLis获取到NewsItem中的值。
~~~
public class listBean {
//变量名最好跟json中一样
public NewsList data;
public static class NewsList{
//变量名最好跟json中一样
public ArrayList<NewsItem> news;
}
public static class NewsItem{
public String title;
public String url;
public String listimage;
public String pubdate;
}}
~~~
接下来就需要访问网络了,新建一个utils包,再建一个NetUtils.java类
~~~
public class NetUtils {
//定义我们需要的变量
private HttpUtils httpUtils;
//全局变量
private Gson gson=new Gson();
private List<News> newsList=new ArrayList<News>();
private News news;
//获取新闻信息
public List<News> getNews(String url){
//访问网络是一个耗时操作,建议开启新线程
GetNewsRunnable getNewsRunnable=new GetNewsRunnable(httpUtils, gson, newsList, news, url);
getNewsRunnable.run();
return newsList;
}
public void addAll(List<News> newsList){
this.newsList.addAll(newsList);
}
}
~~~
新建一个GetNewsRunnable.java,请求网络。
~~~
public class GetNewsRunnable implements Runnable{
private HttpUtils httpUtils;
private Gson gson;
private List<News> newsList;
private News news;
private String url;
private NetUtils netUtils;
public GetNewsRunnable(HttpUtils httpUtils,Gson gson,List<News> newsList,News news,String url){
this.httpUtils=httpUtils;
this.gson=gson;
this.newsList=newsList;
this.news=news;
this.url=url;
netUtils=new NetUtils();
}
//run方法中访问网络并解析json数据
public void run() {
if(newsList==null){
newsList=new ArrayList<News>();
}
httpUtils=new HttpUtils();
httpUtils.send(HttpMethod.GET, url, new RequestCallBack<String>() {
public void onFailure(HttpException arg0, String arg1) {
Log.e("failure", "访问失败");
}
public void onSuccess(ResponseInfo<String> responseInfo) {
Log.e("success", "访问成功");
//访问成功,就进行数据解析
NewsListBean newsListBean=gson.fromJson(responseInfo.result, NewsListBean.class);
//for-each循环
for(NewsListBean.NewsItem newsItem:newsListBean.data.news){
news=new News();
news.setTitle(newsItem.title);
news.setListimage(newsItem.listimage);
news.setUrl(newsItem.url);
news.setPubdate(newsItem.pubdate);
newsList.add(news);
netUtils.addAll(newsList);
}
}
});
}
}
~~~
好了,我们现在需要添加一个适配器了,4个构造方法getCount()、getItem、getItemId、getView可以自动生成就可以了,在适配器中我们首先把变量写好
~~~
//定义变量
private List<News> newsList;
private LayoutInflater mInflater; //获取外部布局用的
private BitmapUtils mBitmapUtils; //加载和显示图片用的
~~~
~~~
public NewsListAdapter(Context context,List<News> newsList){
this.newsList=newsList;
this.mInflater=LayoutInflater.from(context);
mBitmapUtils=new BitmapUtils(context);
}
~~~
~~~
//真正存放东西的方法
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder=null;
if(convertView==null){//如果传进来的view为空,就进行创建,并填充内容
holder=new ViewHolder();
convertView=mInflater.inflate(R.layout.fragment_list_item, null);
holder.newIcon=(ImageView) convertView.findViewById(R.id.newIcon);
holder.newTime=(TextView) convertView.findViewById(R.id.newTime);
holder.newTitle=(TextView) convertView.findViewById(R.id.newTitle);
convertView.setTag(holder);
}else{
holder=(ViewHolder) convertView.getTag();
}
//将数据放到我们的控件当中
News news=newsList.get(position);
holder.newTitle.setText(news.getTitle());
holder.newTime.setText(news.getPubdate());
mBitmapUtils.display(holder.newIcon, news.getListimage());
return convertView;
}
//模拟我们传递的控件
class ViewHolder{
ImageView newIcon;
TextView newTitle;
TextView newTime;
}
//把所有News加进List中
public void addListItem(List<News> list){
newsList.addAll(list);
~~~
通过适配器将数据传送到listview中,之后我们要用到fragment,
~~~
//这里是ListView的滚动和点击事件
newsList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3) {
// TODO Auto-generated method stub
//获取新闻详细信息的地址
String descriptionUrl=newsDatas.get(position).getUrl();
//定义并实例化Intent
Intent intent=new Intent(getActivity().getApplicationContext(),DescriptActivity.class);
String name="url";
//将值放到intent当中
intent.putExtra(name, descriptionUrl);
//开启Activity
startActivity(intent);
}
});
~~~
然后我们添加一些详情页TabIndicatorAdapter
最后描述新闻详情
~~~
public class DescriptActivity extends Activity {
private WebView newsDescription;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_descript);
String url=this.getIntent().getExtras().get("url").toString();
newsDescription=(WebView) findViewById(R.id.newsDescription);
/**
* 适配屏幕
*/
newsDescription.getSettings().setUseWideViewPort(true);
newsDescription.getSettings().setLoadWithOverviewMode(true);
newsDescription.setVerticalScrollBarEnabled(true);
newsDescription.setHorizontalScrollBarEnabled(false);
newsDescription.loadUrl(url);
}
}
~~~
记得在清单文件中添加网络权限等,还有一些步骤就不一一细说了,具体的可以下载源码看一下。
~~~
<uses-permission android:name="android.permission.INTERNET" />
~~~
最终效果图为:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-14_56e65d6e9a21c.jpg)[点击打开链接](http://download.csdn.net/detail/sdksdk0/9446330)
源码下载地址:[点击打开链接](http://download.csdn.net/detail/sdksdk0/9446330)http://download.csdn.net/detail/sdksdk0/9446330