Android demo-->网易新闻风格的RSS新闻抓取项目(一) 菜单栏、滚动广告和新闻列表的配置
2017-02-04 09:16
309 查看
启动页自定义一个加载等待层
主界面是一个仿网易新闻客户端的样式,顶部从左到右,依次是跳转设置按钮,标题,天气按钮。下面是新闻菜单栏,分别是头条、体育、科技、娱乐、财经、更多。其中头条下先放置了一个轮播图片,再放置新闻列表,其他菜单只放置了新闻列表。
菜单栏下面有一个横条,
首先计算这个横条的移动距离
当点击某个菜单的时候这个横条就平移到当前菜单下
新闻列表展示使用的是ViewPager,首先把所有页面放入一个list
然后给ViewPager设置适配器来加载各菜单页面
头条页面需要轮播图片,这里开启一个线程使用了Jsoup来解析URL地址,将解析到的图片信息放入list,然后通知MainActivity的Handler去处理图片信息
PictureObtainFromWeb负责将图片链接转换成Bitmap
获取了图片之后,创建tvImageHandler来进行UI线程图片更新,对viewPagerImg设置适配器,开启一个线程实现每5秒换图片
接下来获取头条新闻列表,其他体育、科技、娱乐、财经和更多的新闻列表跟头条的一样,因此只讲述头条新闻列表的获取方式
首先创建一个RSSHandler,使用xml解析方式获取uri对应的数据,包括新闻标题、链接、描述、时间、作者。
然后创建TopNewsListObtainFromXml类,为ListView数据加载做准备
最后ListView展示数据
项目名称:NewsReader
public class LoadProgressDialog extends Dialog { public Context context; public LoadProgressDialog(Context context) { super(context); this.context = context; } public LoadProgressDialog(Context context, boolean cancelable, OnCancelListener cancelListener) { super(context, cancelable, cancelListener); this.context = context; } public LoadProgressDialog(Context context, int theme) { super(context, theme); this.context = context; View view = LayoutInflater.from(context).inflate(R.layout.load, null); ImageView img_loading = (ImageView) view.findViewById(R.id.img_load); RelativeLayout img_close = (RelativeLayout) view.findViewById(R.id.img_cancel); RotateAnimation rotateAnimation = (RotateAnimation)AnimationUtils.loadAnimation(context, R.anim.progress_bar_refresh); img_loading.setAnimation(rotateAnimation); setContentView(view); img_close.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { dismiss(); } }); } }
主界面是一个仿网易新闻客户端的样式,顶部从左到右,依次是跳转设置按钮,标题,天气按钮。下面是新闻菜单栏,分别是头条、体育、科技、娱乐、财经、更多。其中头条下先放置了一个轮播图片,再放置新闻列表,其他菜单只放置了新闻列表。
菜单栏下面有一个横条,
首先计算这个横条的移动距离
//计算横条移动距离 private void calculateOffset(){ cursor = (ImageView)findViewById(R.id.cursor); DisplayMetrics dm = new DisplayMetrics(); getWin 4000 dowManager().getDefaultDisplay().getMetrics(dm); int disPlayWidth = dm.widthPixels;// 获取屏幕分辨率宽度 offSet = disPlayWidth / 6; // 偏移量为六分之一屏幕 Matrix matrix = new Matrix(); matrix.postTranslate(offSet, 0); cursor.setImageMatrix(matrix);// 设置动画初始位置 }
当点击某个菜单的时候这个横条就平移到当前菜单下
newsTitle1.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub //设置当前显示页面 viewPager.setCurrentItem(0); if(curPage != 0) { ta = new TranslateAnimation(curPage * offSet, 0, 0, 0); ta.setFillAfter(true); ta.setDuration(200); cursor.startAnimation(ta); } curPage = 0; } }); newsTitle2.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub viewPager.setCurrentItem(1); if(curPage != 1) { ta = new TranslateAnimation(curPage * offSet, offSet, 0, 0); ta.setFillAfter(true); ta.setDuration(200); cursor.startAnimation(ta); } curPage = 1; } }); newsTitle3.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub viewPager.setCurrentItem(2); if(curPage != 2) { ta = new TranslateAnimation(curPage * offSet, offSet * 2, 0, 0); ta.setFillAfter(true); ta.setDuration(200); cursor.startAnimation(ta); } curPage = 2; } }); newsTitle4.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub viewPager.setCurrentItem(3); if(curPage != 3) { ta = new TranslateAnimation(curPage * offSet, offSet * 3, 0, 0); ta.setFillAfter(true); ta.setDuration(200); cursor.startAnimation(ta); } curPage = 3; } }); newsTitle5.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub viewPager.setCurrentItem(4); if(curPage != 4) { ta = new TranslateAnimation(curPage * offSet, offSet * 4, 0, 0); ta.setFillAfter(true); ta.setDuration(200); cursor.startAnimation(ta); } curPage = 4; } }); newsTitle6.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub viewPager.setCurrentItem(5); if(curPage != 5) { ta = new TranslateAnimation(curPage * offSet, offSet * 5, 0, 0); ta.setFillAfter(true); ta.setDuration(200); cursor.startAnimation(ta); } curPage = 5; } });
新闻列表展示使用的是ViewPager,首先把所有页面放入一个list
//映射newsViewPager需要的页面列表 viewList = new ArrayList<View>(); viewList.add(getLayoutInflater().inflate(R.layout.news_pager_1, null)); viewList.add(getLayoutInflater().inflate(R.layout.news_pager_2, null)); viewList.add(getLayoutInflater().inflate(R.layout.news_pager_3, null)); viewList.add(getLayoutInflater().inflate(R.layout.news_pager_4, null)); viewList.add(getLayoutInflater().inflate(R.layout.news_pager_5, null)); viewList.add(getLayoutInflater().inflate(R.layout.news_pager_6, null));
然后给ViewPager设置适配器来加载各菜单页面
viewPager.setAdapter(new PagerAdapter() { @Override public void destroyItem(View arg0, int arg1, Object arg2) { // TODO Auto-generated method stub ((ViewPager)arg0).removeView((View)viewList.get(arg1)); } @Override public void finishUpdate(View arg0) { // TODO Auto-generated method stub } @Override public int getCount() { // TODO Auto-generated method stub return viewList.size(); } @Override public Object instantiateItem(View arg0, int arg1) { ((ViewPager)arg0).addView((View)viewList.get(arg1), 0); switch (arg1) { case 0: initNewsImgViewPager(new PictureInfoObtainFromWeb(), AllURL.picURL); if(flagCountTopNews){ requestTopNews(new TopNewsListObtainFromXml(), AllURL.URLmarquee, new RSSHandler(0)); flagCountTopNews = false; } else getTopNews(); break; case 1: if (flagCountSportsNews) { requestSportsNews(new TopNewsListObtainFromXml(), AllURL.URLsports, new RSSHandler(1)); flagCountSportsNews = false; } else getSportsNews(); break; case 2: if(flagCountScienceNews){ requestScienceNews(new TopNewsListObtainFromXml(), AllURL.URLscience, new RSSHandler(2)); flagCountScienceNews = false; }else getScienceNews(); break; case 3: if(flagCountEntainNews){ requestEntainNews(new TopNewsListObtainFromXml(), AllURL.URLentain, new RSSHandler(3)); flagCountEntainNews = false; }else getEntainNews(); break; case 4: if(flagCountFinanceNews){ requestFinanceNews(new TopNewsListObtainFromXml(), AllURL.URLfinance, new RSSHandler(4)); flagCountFinanceNews = false; }else getFinanceNews(); break; } return (View)viewList.get(arg1); } @Override public boolean isViewFromObject(View arg0, Object arg1) { // TODO Auto-generated method stub return arg0 == arg1; } @Override public void restoreState(Parcelable arg0, ClassLoader arg1) { // TODO Auto-generated method stub } @Override public Parcelable saveState() { // TODO Auto-generated method stub return null; } @Override public void startUpdate(View arg0) { // TODO Auto-generated method stub } });
头条页面需要轮播图片,这里开启一个线程使用了Jsoup来解析URL地址,将解析到的图片信息放入list,然后通知MainActivity的Handler去处理图片信息
public class PictureInfoObtainFromWeb{ private String url = null; public void pictureInfoObtain(String URL){ this.url = URL; new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { Document doc = Jsoup.connect(url).timeout(8000).get(); //找到class为slides的节点 Elements divs = doc.select("div.slides"); if (divs != null) { List<StringBuffer> picTitleBuffer = new ArrayList<StringBuffer>(); List<StringBuffer> picLinkBuffer = new ArrayList<StringBuffer>(); List<StringBuffer> pageLinkBuffer = new ArrayList<StringBuffer>(); Elements pageLink = divs.select("a[href]"); Elements picTitle = divs.select("img[alt]"); Elements picLink = divs.select("img[src]"); for(int j = 0; j < pageLink.size(); ++j){ if (pageLink.get(j) != null) { StringBuffer temp = new StringBuffer(); temp.append(pageLink.get(j).attr("abs:href")); pageLinkBuffer.add(temp); } } for(int j = 0; j < pageLink.size(); ++j){ if (picLink.get(j) != null) { StringBuffer temp = new StringBuffer(); temp.append(picLink.get(j).attr("abs:src")); picLinkBuffer.add(temp); } } for(int j = 0; j < pageLink.size(); ++j){ if (picTitle.get(j) != null) { StringBuffer temp = new StringBuffer(); temp.append(picTitle.get(j).attr("alt")); picTitleBuffer.add(temp); } } for (int k = 0; k < pageLink.size(); ++k) { PictureInfo info = new PictureInfo(); info.setPageLink(pageLinkBuffer.get(k)); info.setPicLink(picLinkBuffer.get(k)); info.setPicTitle(picTitleBuffer.get(k)); MainActivity.picInfoList.add(info); } } if (MainActivity.picInfoList != null) MainActivity.srcHandler0.sendEmptyMessage(1); } catch (MalformedURLException e) { // TODO: handle exception e.printStackTrace(); } catch (IOException e) { // TODO: handle exception e.printStackTrace(); } } }).start(); } }
PictureObtainFromWeb负责将图片链接转换成Bitmap
public class PictureObtainFromWeb { private String url = null; // public static ImageView tv_image = null; // public static TextView tv_title = null; private Bitmap bitmap = null; public Bitmap getPictureFromWeb(PictureInfo picInfo) { this.url = picInfo.getPicLink().toString(); // 如果imgCache集合中有当前bitmap的url,就直接获取bitmap if (MainActivity.imgCache.containsKey(url)) { synchronized (MainActivity.imgCache) { // SoftReference 软引用,如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它; // 如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。 // 软引用可用来实现内存敏感的高速缓存 SoftReference<Bitmap> bitmapReference = MainActivity.imgCache .get(url); if (bitmapReference != null) bitmap = bitmapReference.get(); } } else {// 如果imgCache集合中没有当前bitmap的url,则通过流转换,并保存到imgCache中 try { URL u = new URL(url); HttpURLConnection con = (HttpURLConnection) u.openConnection(); InputStream iStream = con.getInputStream(); bitmap = BitmapFactory.decodeStream(iStream); MainActivity.imgCache.put(url, new SoftReference<Bitmap>(bitmap)); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } return bitmap; } }
获取了图片之后,创建tvImageHandler来进行UI线程图片更新,对viewPagerImg设置适配器,开启一个线程实现每5秒换图片
imgAutoChangeHandler = new Handler(){ @Override public void handleMessage(Message msg){ if (msg.what == 1) { viewPagerImg.setCurrentItem(msg.arg1); } } }; //图片list已准备好 可以为viewpagerImg的pageradapter提供数据 tvImageHandler = new Handler(){ public void handleMessage(Message msg){ tv_title.setText(picInfoList.get(0).getPicTitle()); //隐藏欢迎页面 welcomeImage.setVisibility(ImageView.INVISIBLE); loadProgressDialog.dismiss(); viewPagerImg.setAdapter(new PagerAdapter() { @Override public boolean isViewFromObject(View arg0, Object arg1) { // TODO Auto-generated method stub return arg0 == arg1; } @Override public void destroyItem(View arg0, int arg1, Object arg2) { // TODO Auto-generated method stub ((ViewPager)arg0).removeView((ImageView)arg2); } @Override public void finishUpdate(View arg0) { // TODO Auto-generated method stub } @Override public int getCount() { // TODO Auto-generated method stub return imageViewList.size(); } @Override public Object instantiateItem(View arg0, int arg1){ ((ViewPager)arg0).addView((ImageView)imageViewList.get(arg1), 0); return (ImageView)imageViewList.get(arg1); } }); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub while(true) { try { Thread.sleep(5000); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } Message msg = imgAutoChangeHandler.obtainMessage(); msg.what = 1; if (picInfoList.size() == 0) msg.arg1 = (curPageImg + 1) % 3; else msg.arg1 = (curPageImg + 1) % picInfoList.size(); imgAutoChangeHandler.sendMessage(msg); curPageImg += 1; } } }).start(); } }; } }; viewPagerImg.setCurrentItem(0); viewPagerImg.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int arg0) { // TODO Auto-generated method stub // curPageImg = arg0; viewPagerImg.setCurrentItem(arg0); tv_title.setText(picInfoList.get(arg0).getPicTitle()); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { // TODO Auto-generated method stub } @Override public void onPageScrollStateChanged(int arg0) { // TODO Auto-generated method stub } });
接下来获取头条新闻列表,其他体育、科技、娱乐、财经和更多的新闻列表跟头条的一样,因此只讲述头条新闻列表的获取方式
首先创建一个RSSHandler,使用xml解析方式获取uri对应的数据,包括新闻标题、链接、描述、时间、作者。
public class RSSHandler extends DefaultHandler{ private RSSItem item = null; private String tag = ""; private String temp = null; private StringBuffer bufferTitle = null; private StringBuffer bufferDes = null; private int newsType = 0; public RSSHandler(int type){ this.newsType = type; } public void startDodument(){ } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException{ super.startElement(uri, localName, qName, attributes); if (localName.equals("item")){ item = new RSSItem(); bufferTitle = new StringBuffer(); bufferDes = new StringBuffer(); } tag = localName; } @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); if (localName.equals("item")) { switch (newsType) { case 0: MainActivity.tempNewsList.add(item); break; case 1: MainActivity.tempSportsNewsList.add(item); break; case 2: MainActivity.tempScienceNewsList.add(item); break; case 3: MainActivity.tempEntainNewsList.add(item); break; case 4: MainActivity.tempFinanceNewsList.add(item); break; } item = null; bufferTitle = null; bufferDes = null; } tag = null; } @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); if (item != null) { temp = new String(ch, start, length); if (tag == "title") { item.setTitle(bufferTitle.append(Html.fromHtml(temp))); }else if (tag == "link"){ item.setLink(temp); }else if(tag == "description") { // if (temp.length() < 6) { // item.setDescription(item.getTitle()); // }else item.setDescription(bufferDes.append(Html.fromHtml(temp.replaceAll("\\s", "")))); }else if (tag == "author") { item.setAuthor(temp); }else if (tag == "pubDate") { //String data = temp.substring(16, 25); //item.setPubDate(data); item.setPubDate(temp); } } } @Override public void endDocument() throws SAXException { super.endDocument(); } }
然后创建TopNewsListObtainFromXml类,为ListView数据加载做准备
//实现topNewsListObtain接口 用户在这里实现获取listView所需数据 public class TopNewsListObtainFromXml{ private DefaultHandler mRssHandler = null; public void topNewsListObtain(final String RssUrl, DefaultHandler rssHandler){ this.mRssHandler = rssHandler; new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { URL url = new URL(RssUrl); URLConnection con = url.openConnection(); con.connect(); InputStream input = con.getInputStream(); SAXParserFactory fac = SAXParserFactory.newInstance(); SAXParser parser = fac.ne aca0 wSAXParser(); XMLReader reader = parser.getXMLReader(); reader.setContentHandler(mRssHandler); Reader r = new InputStreamReader(input, Charset.forName("utf-8")); reader.parse(new InputSource(r)); if (RssUrl == AllURL.URLmarquee && MainActivity.tempNewsList.size() > 0) { MainActivity.mMsgHandler.sendEmptyMessage(0); }else if (RssUrl == AllURL.URLsports && MainActivity.tempSportsNewsList.size() > 0) { MainActivity.mMsgSportsHandler.sendEmptyMessage(1); }else if (RssUrl == AllURL.URLscience && MainActivity.tempScienceNewsList.size() > 0) { MainActivity.mMsgScienceHandler.sendEmptyMessage(2); }else if (RssUrl == AllURL.URLentain && MainActivity.tempEntainNewsList.size() > 0) { MainActivity.mMsgEntainHandler.sendEmptyMessage(3); }else if (RssUrl == AllURL.URLfinance && MainActivity.tempFinanceNewsList.size() > 0) { MainActivity.mMsgFinanceHandler.sendEmptyMessage(4); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }).start(); } }
最后ListView展示数据
private void requestFinanceNews(TopNewsListObtainFromXml topNewsListOb, final String url, DefaultHandler rsshandler){ topFinanceNewsList = new ArrayList<RSSItem>(); tempFinanceNewsList = new ArrayList<RSSItem>(); //获取adapter所属数据 topNewsListOb.topNewsListObtain(url, rsshandler); mMsgFinanceHandler = new Handler(){ @Override public void handleMessage(Message msg) { if (msg.what == 4) { try { for(int i = 0; i < tempFinanceNewsList.size(); ++i) topFinanceNewsList.add(tempFinanceNewsList.get(i)); tempFinanceNewsList.clear(); topFinanceNewsListView = (TopNewsListView)findViewById(R.id.top_finance_news_listView); listAdapterFinance = new ListAdapterFinance(); topFinanceNewsListView.setAdapter(listAdapterFinance); topFinanceNewsListViewRefresh(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } } }; }
项目名称:NewsReader
相关文章推荐
- Android demo-->网易新闻风格的RSS新闻抓取项目(二) 新闻列表刷新、天气预报、设置页面滑动开关
- 黑马北京新闻项目连载(2)--->侧滑菜单栏、主页面Fragment搭建
- (&lt;虚拟项目&gt;广告管理投放系统-2)Sql Server 2008 R2主数据管理系统的安装和配置
- 黑马北京新闻项目连载(4)--->ViewPagerIndicator结合FragmentPagerAdapter(开源库的Git上的demo)
- <Android 基础(九)> Ndk配置与Demo
- 运用WindowManager,当滚动列表时显示一个类似Toast的提示(android demo)
- JQuery实现页面企业广告图片切换和新闻列表滚动效果
- <Android 基础(九)> Ndk配置与Demo
- Android电商项目 ExpandableListView(二级列表)实现购物车(高仿淘宝) demo
- Android实战简易教程<三十五>(将二维码扫描和生成Demo引入项目实例)
- <转>android-滑动菜单栏-开源项目SlidingMenu的搭建和使用
- Android中VR全景图项目配置环境和具体项目Demo
- Android之类似网易新闻客户端首页新闻列表实现思路
- js,新闻列表滚动特效
- 使用websphere开发J2EE项目时,在服务器配置文件->“环境”->“类路径”中添加的ORACLE的JDBC文件classes12.zip文件是否有效呢?
- 基于jquery的滚动新闻列表
- 防网易新闻频道右侧新闻滚动效果
- (&lt;虚拟项目&gt;广告管理投放系统-1)技术体系结构
- 无间断的滚动新闻列表特效 兼容Firefox浏览器
- 如何在android手机项目中加入广告