基于Android的小巫新闻客户端开发---显示新闻详细内容业务逻辑实现

http://blog.csdn.net/wwj_748/article/details/8619417

 

 

2013年2月27日,继续小巫新闻客户端的开发。

上一篇忘记谈及一个比较重要的内容,有些网友留言给小巫问:Json数据的明细是怎样的?,在这里小巫先声明一点,小巫对Json数据的格式也是刚接触,这是稍微知道其的结构组成,关于是否尤其内容并不是很清楚。但小巫对与怎么进行JSON格式的解析已经比较清晰了。下面就接这篇博客来介绍一下,新闻详细内容的JSON数据是怎样的,通过浏览器得到的数据到底是怎样的。

 

如果得到小巫所共享的资源的话,服务端的项目是一个叫web的JavaEE项目,如果有看过里面的具体实现的话,读者可能就会明白,服务端是如何与数据库进行交互的了。那好,部署好项目到Tomcat中,在浏览器就可以得到相应的JSON数据源。

获取新闻详细内容的Servlet代码如下:注:(这是服务端的代码),关于解析JSON数据的解析,在介绍客户端业务逻辑实现的时候会说明。

[java] view plain copy print ?
  1. package com.szy.web.servlet;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.PrintWriter;  
  5. import java.util.ArrayList;  
  6. import java.util.HashMap;  
  7.   
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.http.HttpServlet;  
  10. import javax.servlet.http.HttpServletRequest;  
  11. import javax.servlet.http.HttpServletResponse;  
  12.   
  13. import org.json.JSONException;  
  14. import org.json.JSONObject;  
  15.   
  16. import sun.reflect.generics.reflectiveObjects.NotImplementedException;  
  17.   
  18. import com.szy.web.dao.CommentDAO;  
  19. import com.szy.web.dao.NewsDAO;  
  20. import com.szy.web.model.News;  
  21. import com.szy.web.util.TextUtility;  
  22.   
  23. /** 
  24.  *@author coolszy 
  25.  *@date Feb 19, 2012 
  26.  *@blog http://blog.92coding.com 
  27.  *http://localhost:8080/web/getNews?nid=1 
  28.  */  
  29. public class GetNewsServlet extends HttpServlet  
  30. {  
  31.     private static final long serialVersionUID = -7715894432269979527L;  
  32.   
  33.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  34.             throws ServletException, IOException  
  35.     {  
  36.   
  37.         response.setContentType("text/html;charset=UTF-8");  
  38.         String nidStr= request.getParameter("nid");  
  39.         int nid = 0;  
  40.         nid = TextUtility.String2Int(nidStr);  
  41.         JSONObject jObject = new JSONObject();  
  42.         try  
  43.         {  
  44.             CommentDAO commentDAO = new CommentDAO();  
  45.             long commentCount = commentDAO.getSpecifyNewsCommentsCount(nid);  
  46.             NewsDAO newsDAO = new NewsDAO();  
  47.             News news = newsDAO.getNews(nid);  
  48.             JSONObject jObject2 = new JSONObject();  
  49.             if (!TextUtility.isNull(news.getTitle()))  
  50.             {  
  51.                 HashMap<String, Object> hashMap = new HashMap<String, Object>();  
  52.                   
  53.                   
  54.                 /***************后期增加代码,主要用于测试TextView显示图片功能********************/  
  55.                 String newsbody = news.getBody();  
  56.                 ArrayList<HashMap<String, Object>> list = new ArrayList<HashMap<String,Object>>();  
  57.                 HashMap<String, Object> hashMap1 = new HashMap<String, Object>();  
  58.                 hashMap1.put("index"0);  
  59.                 hashMap1.put("type""image");  
  60.                 hashMap1.put("value""http://www.eportfolio.wtuc.edu.tw/blog/attach/35/16035/95/bf_22696_7751198_66497_4.jpg");  
  61.                   
  62.                 HashMap<String, Object> hashMap2 = new HashMap<String, Object>();  
  63.                 hashMap2.put("index"1);  
  64.                 hashMap2.put("type""text");  
  65.                 hashMap2.put("value", newsbody);  
  66.                   
  67.                 list.add(hashMap1);  
  68.                 list.add(hashMap2);  
  69.             /********************************************************/  
  70.                   
  71.                 hashMap.put("nid", news.getNid());  
  72.                 hashMap.put("title", news.getTitle());  
  73.                 //hashMap.put("body", news.getBody());  
  74.                 hashMap.put("body", list);  
  75.                 hashMap.put("source", news.getSource());  
  76.                 hashMap.put("replycount", commentCount);  
  77.                 hashMap.put("ptime", news.getPtime());  
  78.                 hashMap.put("imgsrc", news.getImgSrc());  
  79.                 jObject2.put("news", hashMap);  
  80.             }  
  81.             jObject.put("ret"0);  
  82.             jObject.put("msg""ok");  
  83.             jObject.put("data", jObject2);  
  84.         } catch (Exception e)  
  85.         {  
  86.             e.printStackTrace();  
  87.             try  
  88.             {  
  89.                 jObject.put("ret"1);  
  90.                 jObject.put("msg", e.getMessage());  
  91.                 jObject.put("data""");  
  92.             } catch (JSONException ex)  
  93.             {  
  94.                 ex.printStackTrace();  
  95.             }  
  96.         }  
  97.         PrintWriter out = response.getWriter();  
  98.         out.println(jObject);  
  99.         out.flush();  
  100.         out.close();  
  101.     }  
  102.   
  103.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  104.             throws ServletException, IOException  
  105.     {  
  106.         throw new NotImplementedException();  
  107.     }  
  108. }  
package com.szy.web.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONException;
import org.json.JSONObject;

import sun.reflect.generics.reflectiveObjects.NotImplementedException;

import com.szy.web.dao.CommentDAO;
import com.szy.web.dao.NewsDAO;
import com.szy.web.model.News;
import com.szy.web.util.TextUtility;

/**
 *@author coolszy
 *@date Feb 19, 2012
 *@blog http://blog.92coding.com
 *http://localhost:8080/web/getNews?nid=1
 */
public class GetNewsServlet extends HttpServlet
{
	private static final long serialVersionUID = -7715894432269979527L;

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException
	{

		response.setContentType("text/html;charset=UTF-8");
		String nidStr= request.getParameter("nid");
		int nid = 0;
		nid = TextUtility.String2Int(nidStr);
		JSONObject jObject = new JSONObject();
		try
		{
			CommentDAO commentDAO = new CommentDAO();
			long commentCount = commentDAO.getSpecifyNewsCommentsCount(nid);
			NewsDAO newsDAO = new NewsDAO();
			News news = newsDAO.getNews(nid);
			JSONObject jObject2 = new JSONObject();
			if (!TextUtility.isNull(news.getTitle()))
			{
				HashMap<String, Object> hashMap = new HashMap<String, Object>();
				
				
				/***************后期增加代码,主要用于测试TextView显示图片功能********************/
				String newsbody = news.getBody();
				ArrayList<HashMap<String, Object>> list = new ArrayList<HashMap<String,Object>>();
				HashMap<String, Object> hashMap1 = new HashMap<String, Object>();
				hashMap1.put("index", 0);
				hashMap1.put("type", "image");
				hashMap1.put("value", "http://www.eportfolio.wtuc.edu.tw/blog/attach/35/16035/95/bf_22696_7751198_66497_4.jpg");
				
				HashMap<String, Object> hashMap2 = new HashMap<String, Object>();
				hashMap2.put("index", 1);
				hashMap2.put("type", "text");
				hashMap2.put("value", newsbody);
				
				list.add(hashMap1);
				list.add(hashMap2);
			/********************************************************/
				
				hashMap.put("nid", news.getNid());
				hashMap.put("title", news.getTitle());
				//hashMap.put("body", news.getBody());
				hashMap.put("body", list);
				hashMap.put("source", news.getSource());
				hashMap.put("replycount", commentCount);
				hashMap.put("ptime", news.getPtime());
				hashMap.put("imgsrc", news.getImgSrc());
				jObject2.put("news", hashMap);
			}
			jObject.put("ret", 0);
			jObject.put("msg", "ok");
			jObject.put("data", jObject2);
		} catch (Exception e)
		{
			e.printStackTrace();
			try
			{
				jObject.put("ret", 1);
				jObject.put("msg", e.getMessage());
				jObject.put("data", "");
			} catch (JSONException ex)
			{
				ex.printStackTrace();
			}
		}
		PrintWriter out = response.getWriter();
		out.println(jObject);
		out.flush();
		out.close();
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException
	{
		throw new NotImplementedException();
	}
}

 

 

这就是服务端从数据库获取新闻详细内容的Servlet,当然这只是Servlet的代码,查询数据库的代码需要到web项目查看。

在浏览器敲入如下URL:http://localhost:8080/web/getNews?nid=2

就会得到数据nid为2的新闻内容如下:

{"ret":0,"data":{"news":{"body":[{"index":0,"value":"http://www.eportfolio.wtuc.edu.tw/blog/attach/35/16035/95/bf_22696_7751198_66497_4.jpg","type":"image"},{"index":1,"value":"

新华网十八大快讯:党的十八届一中全会选举习近平、李克强、张德江、俞正声、刘云山、王岐山、张高丽为中央政治局常委。<\/p>","type":"text"}],"title":"党的十八届一中全会选举习近平、李克强、张德江、俞正声、刘云山、王岐山、张高丽为中央政治局常委 ","source":"来源: 新华网","nid":2,"replycount":1,"ptime":"2012年11月15日 11:45:36"}},"msg":"ok"}

 

这样看是比较乱的,需要将这些数据进行一下格式化,看起来比较舒服。

[html] view plain copy print ?
  1. {  
  2.   "ret": 0,   
  3.   "data": {  
  4.     "news": {  
  5.       "body": [  
  6.         {  
  7.           "index": 0,   
  8.           "value": "http://www.eportfolio.wtuc.edu.tw/blog/attach/35/16035/95/bf_22696_7751198_66497_4.jpg",   
  9.           "type": "image"  
  10.         },   
  11.         {  
  12.           "index": 1,   
  13.           "value": " <p>新华网十八大快讯:党的十八届一中全会选举习近平、李克强、张德江、俞正声、刘云山、王岐山、张高丽为中央政治局常委。</p>",   
  14.           "type": "text"  
  15.         }  
  16.       ],   
  17.       "title": "党的十八届一中全会选举习近平、李克强、张德江、俞正声、刘云山、王岐山、张高丽为中央政治局常委 ",   
  18.       "source": "来源: 新华网",   
  19.       "nid": 2,   
  20.       "replycount": 1,   
  21.       "ptime": "2012年11月15日 11:45:36"  
  22.     }  
  23.   },   
  24.   "msg": "ok"  
  25. }  
{
  "ret": 0, 
  "data": {
    "news": {
      "body": [
        {
          "index": 0, 
          "value": "http://www.eportfolio.wtuc.edu.tw/blog/attach/35/16035/95/bf_22696_7751198_66497_4.jpg", 
          "type": "image"
        }, 
        {
          "index": 1, 
          "value": " <p>新华网十八大快讯:党的十八届一中全会选举习近平、李克强、张德江、俞正声、刘云山、王岐山、张高丽为中央政治局常委。</p>", 
          "type": "text"
        }
      ], 
      "title": "党的十八届一中全会选举习近平、李克强、张德江、俞正声、刘云山、王岐山、张高丽为中央政治局常委 ", 
      "source": "来源: 新华网", 
      "nid": 2, 
      "replycount": 1, 
      "ptime": "2012年11月15日 11:45:36"
    }
  }, 
  "msg": "ok"
}


 

那好,关于JSON数据的明细,就说到这里。从格式化的JSON数据是可以很清楚得到新闻的组成结构的,接下来就是要在客户端解析这些数据,并把它们显示到手机界面上,这才是我们花那么大功夫去解析JSON数据的原因。

 

贴上代码之前,当然需要看一下最终需要实现的效果图:

基于Android的小巫新闻客户端开发---显示新闻详细内容业务逻辑实现_第1张图片    基于Android的小巫新闻客户端开发---显示新闻详细内容业务逻辑实现_第2张图片

 

关于这个界面我就不做过多的说明了,最重要的是具体实现。

[java] view plain copy print ?
  1. package com.xiaowu.news;  
  2.   
  3. import java.io.Serializable;  
  4. import java.util.ArrayList;  
  5. import java.util.HashMap;  
  6.   
  7. import org.json.JSONArray;  
  8. import org.json.JSONObject;  
  9.   
  10. import android.app.Activity;  
  11. import android.content.Context;  
  12. import android.content.Intent;  
  13. import android.os.Bundle;  
  14. import android.os.Handler;  
  15. import android.os.Message;  
  16. import android.view.LayoutInflater;  
  17. import android.view.Menu;  
  18. import android.view.MenuItem;  
  19. import android.view.MotionEvent;  
  20. import android.view.View;  
  21. import android.view.View.OnClickListener;  
  22. import android.view.View.OnTouchListener;  
  23. import android.view.inputmethod.InputMethodManager;  
  24. import android.widget.Button;  
  25. import android.widget.EditText;  
  26. import android.widget.ImageButton;  
  27. import android.widget.LinearLayout;  
  28. import android.widget.TextView;  
  29. import android.widget.Toast;  
  30. import android.widget.ViewFlipper;  
  31.   
  32. import com.xiaowu.news.service.SyncHttp;  
  33. import com.xiaowu.news.thread.PostCommentsThread;  
  34.   
  35. public class NewsDetailActivity extends Activity {  
  36.   
  37.     private final int FINISH = 0;               //代表线程的状态的结束  
  38.     private LayoutInflater mNewsbodyLayoutInflater;  
  39.     private ViewFlipper mNewsBodyFlipper;       //屏幕切换控件  
  40.     private ArrayList<HashMap<String, Object>> mNewsData;  
  41.     private float mStartX;                      //手指按下的开始位置  
  42.     private int mPosition = 0;                  //点击新闻位置          
  43.     private int mCursor = 0;                    //用来标记新闻点击的位置  
  44.     private int mNid;                           //新闻编号  
  45.     private Button mNewsDetailTitleBarComm;     //显示评论条数的按钮  
  46.     private ConstomTextView mNewsBodyDetail;    //新闻详细内容  
  47.     private LinearLayout mNewsReplyEditLayout;  //新闻回复的布局  
  48.     private LinearLayout mNewsReplyImgLayout;   //新闻图片回复的布局  
  49.     private EditText mNewsReplyEditText;        //新闻回复的文本框  
  50.     private ImageButton mShareNewsButton;       //分享新闻的按钮  
  51.     private ImageButton mFavoritesButton;       //收藏新闻的按钮  
  52.     private boolean keyboardShow;               //键盘是否显示  
  53.     private Handler mHandler = new Handler() {  
  54.   
  55.         @SuppressWarnings("unchecked")  
  56.         @Override  
  57.         public void handleMessage(Message msg) {  
  58.             // TODO Auto-generated method stub  
  59.             switch (msg.arg1) {  
  60.             case FINISH:  
  61.                 //把获取到的新闻显示到界面上  
  62.                 ArrayList<HashMap<String, Object>> bodyList = (ArrayList<HashMap<String, Object>>) msg.obj;  
  63.                 mNewsBodyDetail.setText(bodyList);  
  64.                 break;  
  65.             }  
  66.         }  
  67.     };  
  68.   
  69.     @SuppressWarnings("unchecked")  
  70.     @Override  
  71.     protected void onCreate(Bundle savedInstanceState) {  
  72.         // TODO Auto-generated method stub  
  73.         super.onCreate(savedInstanceState);  
  74.         setContentView(R.layout.newsdetails_layout);  
  75.   
  76.         mNewsReplyEditLayout = (LinearLayout) findViewById(R.id.news_reply_edit_layout);  
  77.         mNewsReplyImgLayout = (LinearLayout) findViewById(R.id.news_reply_img_layout);  
  78.           
  79.         Button newsDetailPrev = (Button) findViewById(R.id.newsdetail_titlebar_previous);  
  80.         Button newsDetailNext = (Button) findViewById(R.id.newsdetail_titlebar_next);  
  81.         mNewsDetailTitleBarComm = (Button) findViewById(R.id.newsdetail_titlebar_comments);  
  82.         mNewsReplyEditText = (EditText) findViewById(R.id.news_reply_edittext);  
  83.         mShareNewsButton = (ImageButton) findViewById(R.id.news_share_btn);  
  84.         mFavoritesButton = (ImageButton) findViewById(R.id.news_favorites_btn);  
  85.           
  86.           
  87.         NewsDetailOnClickListener newsDetailOnClickListener = new NewsDetailOnClickListener();  
  88.           
  89.         newsDetailPrev.setOnClickListener(newsDetailOnClickListener);  
  90.         newsDetailNext.setOnClickListener(newsDetailOnClickListener);  
  91.         mNewsDetailTitleBarComm.setOnClickListener(newsDetailOnClickListener);  
  92.         mShareNewsButton.setOnClickListener(newsDetailOnClickListener);  
  93.         mFavoritesButton.setOnClickListener(newsDetailOnClickListener);  
  94.           
  95.         Button newsReplyPost = (Button) findViewById(R.id.news_reply_post);  
  96.         newsReplyPost.setOnClickListener(newsDetailOnClickListener);  
  97.         ImageButton newsReplyImgBtn = (ImageButton) findViewById(R.id.news_reply_img_btn);  
  98.         newsReplyImgBtn.setOnClickListener(newsDetailOnClickListener);  
  99.           
  100.           
  101.         //获取传送的数据  
  102.         Intent intent = getIntent();  
  103.         Bundle bundle = intent.getExtras();  
  104.         String categoryName = bundle.getString("categoryTitle");  
  105.         TextView titleBarTitle = (TextView) findViewById(R.id.newsdetail_titlebar_title);  
  106.         //设置标题栏的标题  
  107.         titleBarTitle.setText(categoryName);  
  108.         //获取新闻集合  
  109.         Serializable serializable = bundle.getSerializable("newsData");  
  110.         mNewsData = (ArrayList<HashMap<String, Object>>) serializable;  
  111.   
  112.         //获取点击位置  
  113.         mCursor = mPosition = bundle.getInt("position");  
  114.           
  115.         mNewsBodyFlipper = (ViewFlipper) findViewById(R.id.news_body_flipper);  
  116.         // 获取LayoutInflater对象  
  117.         mNewsbodyLayoutInflater = getLayoutInflater();  
  118.           
  119.         inflateView(0);  
  120.         //启动线程  
  121.         new UpdateNewsThread().start();  
  122.     }  
  123.   
  124.     /** 
  125.      * 显示上一条新闻 
  126.      */  
  127.     private void showPrevious() {  
  128.         if(mPosition > 0) {  
  129.             mPosition--;  
  130.             //记录当前新闻编号  
  131.             HashMap<String, Object> hashMap = mNewsData.get(mPosition);  
  132.             mNid = (Integer) hashMap.get("nid");  
  133.             if(mCursor > mPosition){  
  134.                 mCursor = mPosition;  
  135.                 inflateView(0);  
  136.                 mNewsBodyFlipper.showNext();  
  137.             }  
  138.             mNewsBodyFlipper.setInAnimation(this, R.anim.push_right_in);    //设置下一页进来时的动画  
  139.             mNewsBodyFlipper.setOutAnimation(this, R.anim.push_right_out);  //设置当前页出去的动画  
  140.             mNewsBodyFlipper.showPrevious();  
  141.         }  
  142.         else {  
  143.             Toast.makeText(NewsDetailActivity.this"没有上一篇新闻", Toast.LENGTH_SHORT).show();  
  144.         }  
  145.     }  
  146.   
  147.     /** 
  148.      * 显示下一条新闻 
  149.      */  
  150.     private void showNext() {  
  151.         if(mPosition < mNewsData.size() - 1){  
  152.             // 设置下一屏动画  
  153.             mNewsBodyFlipper.setInAnimation(this, R.anim.push_left_in);  
  154.             mNewsBodyFlipper.setOutAnimation(this, R.anim.push_left_out);  
  155.             mPosition++;  
  156.             //记录当前新闻编号  
  157.             HashMap<String, Object> hashMap = mNewsData.get(mPosition);  
  158.             mNid = (Integer) hashMap.get("nid");  
  159.             if(mPosition >= mNewsBodyFlipper.getChildCount()){  
  160.                 inflateView(mNewsBodyFlipper.getChildCount());  
  161.             }  
  162.             mNewsBodyFlipper.showNext();  
  163.         } else {  
  164.             Toast.makeText(NewsDetailActivity.this"没有下篇新闻", Toast.LENGTH_SHORT).show();  
  165.         }  
  166.     }  
  167.   
  168.     private void inflateView(int index) {  
  169.         //获取点击新闻信息  
  170.         HashMap<String, Object> hashMap = mNewsData.get(mPosition);  
  171.         mNid = (Integer) hashMap.get("nid");  
  172.   
  173.         View mNewsBodyView = mNewsbodyLayoutInflater.inflate(  
  174.                 R.layout.newsbody_layout, null);  
  175.         mNewsDetailTitleBarComm.setText(hashMap.get("newslist_item_comments").toString() + "跟帖");  
  176.         //新闻标题  
  177.         TextView newsTitle = (TextView) mNewsBodyView  
  178.                 .findViewById(R.id.news_body_title);  
  179.         newsTitle.setText(hashMap.get("newslist_item_title").toString());  
  180.         //新闻的出处和发布时间  
  181.         TextView newsPtimeAndSource = (TextView) mNewsBodyView  
  182.                 .findViewById(R.id.news_body_ptime_source);  
  183.         newsPtimeAndSource.setText(hashMap.get("newslist_item_source").toString()   
  184.                 + "     " + hashMap.get("newslist_item_ptime").toString());  
  185.         mNewsBodyDetail = (ConstomTextView) mNewsBodyView  
  186.                 .findViewById(R.id.news_body_details);  
  187.         mNewsBodyDetail.setText(getNewsBody());  
  188.         mNewsBodyFlipper.addView(mNewsBodyView, index);  
  189.         mNewsBodyDetail.setOnTouchListener(new NewsBodyOntouchListener());  
  190.     }  
  191.   
  192.     // 定义内部类--用于处理标题栏的按钮的触发事件  
  193.     private class NewsDetailOnClickListener implements OnClickListener {  
  194.   
  195.         @Override  
  196.         public void onClick(View v) {  
  197.             InputMethodManager m = (InputMethodManager) mNewsReplyEditText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);  
  198.             // TODO Auto-generated method stub  
  199.             switch (v.getId()) {  
  200.             //上一篇  
  201.             case R.id.newsdetail_titlebar_previous:  
  202.                 showPrevious();  
  203.                 break;  
  204.             //下一篇  
  205.             case R.id.newsdetail_titlebar_next:  
  206.                 showNext();  
  207.                 break;  
  208.             //跟帖  
  209.             case R.id.newsdetail_titlebar_comments:  
  210.                 Intent intent = new Intent(NewsDetailActivity.this,  
  211.                         CommentsActivity.class);  
  212.                 intent.putExtra("nid", mNid);  
  213.                 startActivity(intent);  
  214.                 break;  
  215.             //“写跟帖”图片  
  216.             case R.id.news_reply_img_btn:  
  217.                 mNewsReplyEditLayout.setVisibility(View.VISIBLE);  
  218.                 mNewsReplyImgLayout.setVisibility(View.GONE);  
  219.                 mNewsReplyEditText.requestFocus();  
  220.                 //显示输入法  
  221.                 m.toggleSoftInput(0, InputMethodManager.SHOW_IMPLICIT);  
  222.                 keyboardShow = true;  
  223.                 break;  
  224.             //分享按钮  
  225.             case R.id.news_share_btn:  
  226.                 Intent shareIntent = new Intent(Intent.ACTION_SEND);  
  227.                 //纯文本  
  228.                 shareIntent.setType("text/plain");  
  229.                 shareIntent.putExtra(Intent.EXTRA_SUBJECT, "分享");  
  230.                 shareIntent.putExtra(Intent.EXTRA_TEXT, "我想将这个分享给你...."+ getTitle());  
  231.                 startActivity(Intent.createChooser(shareIntent, getTitle()));  
  232.                 break;  
  233.             //收藏按钮  
  234.             case R.id.news_favorites_btn:  
  235.                 Toast.makeText(NewsDetailActivity.this"收藏成功", Toast.LENGTH_SHORT).show();  
  236.                 break;  
  237.             //发表按钮  
  238.             case R.id.news_reply_post:  
  239.                 //隐藏输入法  
  240.                 m.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);  
  241.                 String str = mNewsReplyEditText.getText().toString();  
  242.                 if(str.equals("")){  
  243.                     Toast.makeText(NewsDetailActivity.this"不能为空",  
  244.                             Toast.LENGTH_SHORT).show();  
  245.                 }  
  246.                 else {  
  247.                     mNewsReplyEditLayout.post(new PostCommentsThread(mNid, "广州市",  
  248.                             str + "",  
  249.                             new NewsDetailActivity()));  
  250.                     mNewsReplyEditLayout.setVisibility(View.GONE);  
  251.                     mNewsReplyImgLayout.setVisibility(View.VISIBLE);  
  252.                 }  
  253.                 break;  
  254.             }  
  255.         }  
  256.     }  
  257.   
  258.     private class NewsBodyOntouchListener implements OnTouchListener {  
  259.   
  260.         @Override  
  261.         public boolean onTouch(View v, MotionEvent event) {  
  262.             // TODO Auto-generated method stub  
  263.             switch (event.getAction()) {  
  264.                 //手指按下  
  265.             case MotionEvent.ACTION_DOWN:  
  266.                 if(keyboardShow){  
  267.                     mNewsReplyEditLayout.setVisibility(View.GONE);  
  268.                     mNewsReplyImgLayout.setVisibility(View.VISIBLE);  
  269.                     //隐藏输入法  
  270.                     InputMethodManager m = (InputMethodManager) mNewsReplyEditText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);  
  271.                     m.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);  
  272.                     keyboardShow = false;  
  273.                 }  
  274.                 //得到按下的横坐标的位置  
  275.                 mStartX = event.getX();  
  276.                 break;  
  277.             case MotionEvent.ACTION_UP:  
  278.                 // 往左滑动  
  279.                 if (event.getX() < mStartX) {  
  280.                     showNext();  
  281.                 }  
  282.                 // 往右滑动  
  283.                 else if (event.getX() > mStartX) {  
  284.                     showPrevious();  
  285.                 }  
  286.                 break;  
  287.             }  
  288.             return true;  
  289.         }  
  290.     }  
  291.       
  292.     /** 
  293.      * 定义一个线程类,用来更新获取到新闻的信息 
  294.      * @author Administrator 
  295.      * 
  296.      */  
  297.     private class UpdateNewsThread extends Thread {  
  298.         @Override  
  299.         public void run() {  
  300.             // TODO Auto-generated method stub  
  301.             ArrayList<HashMap<String, Object>> newsStr = getNewsBody();  
  302.             Message msg = mHandler.obtainMessage(); //获取msg  
  303.             msg.arg1 = FINISH;            
  304.             msg.obj = newsStr;  
  305.             mHandler.sendMessage(msg);  //给Handler发送信息  
  306.         }  
  307.     }  
  308.       
  309.       
  310.     /** 
  311.      * 获取新闻详细信息 
  312.      * @return 
  313.      */  
  314.     private ArrayList<HashMap<String, Object>> getNewsBody(){  
  315.         //String retStr = "网络连接失败,请稍后再试";  
  316.         ArrayList<HashMap<String, Object>> bodylist = new ArrayList<HashMap<String,Object>>();  
  317.           
  318.         SyncHttp syncHttp = new SyncHttp();  
  319.         //模拟器:url = "http://10.0.2.2:8080/web/getNews";  
  320.         //本机:http://127.0.0.1:8080  
  321.         //wifi局域网:http://192.168.220.1:8080  
  322.         String url = "http://10.0.2.2:8080/web/getNews";  
  323.         String params = "nid=" + mNid;  
  324.         try {  
  325.             String retString = syncHttp.httpGet(url, params);  
  326.             JSONObject  jsonObject = new JSONObject(retString);  
  327.             //获取返回码,0表示成功  
  328.             int retCode = jsonObject.getInt("ret");  
  329.             if(retCode == 0) {  
  330.                 JSONObject dataObject = jsonObject.getJSONObject("data");  
  331.                 JSONObject newsObject = dataObject.getJSONObject("news");  
  332.                 //retStr = newsObject.getString("body");  
  333.                 JSONArray bodyArray = newsObject.getJSONArray("body");  
  334.                 for(int i = 0; i < bodyArray.length(); i++) {  
  335.                     JSONObject object = (JSONObject) bodyArray.opt(i);  
  336.                     HashMap<String, Object> hashMap = new HashMap<String, Object>();  
  337.                     hashMap.put("index", object.get("index"));  
  338.                     hashMap.put("type", object.get("type"));  
  339.                     hashMap.put("value", object.get("value"));  
  340.                     bodylist.add(hashMap);  
  341.                 }  
  342.             }  
  343.         } catch (Exception e) {  
  344.             // TODO: handle exception  
  345.             e.printStackTrace();  
  346.         }  
  347.         return bodylist;  
  348.     }  
  349.       
  350.       
  351.     @Override  
  352.     public boolean onCreatePanelMenu(int featureId, Menu menu) {  
  353.         // TODO Auto-generated method stub  
  354.         menu.add(000"分享");  
  355.         return true;  
  356.     }  
  357.       
  358.     @Override  
  359.     public boolean onOptionsItemSelected(MenuItem item) {  
  360.         // TODO Auto-generated method stub  
  361.         switch(item.getItemId()) {  
  362.         case 0:  
  363.             Intent shareIntent = new Intent(Intent.ACTION_SEND);  
  364.             //纯文本  
  365.             shareIntent.setType("text/plain");  
  366.             shareIntent.putExtra(Intent.EXTRA_SUBJECT, "分享");  
  367.             shareIntent.putExtra(Intent.EXTRA_TEXT, "我想把这个分享给你:" + getTitle());  
  368.             shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  369.             startActivity(Intent.createChooser(shareIntent, getTitle()));  
  370.             System.out.println(getTitle());  
  371.             break;  
  372.               
  373.         }  
  374.         return super.onOptionsItemSelected(item);  
  375.     }  
  376. }  
package com.xiaowu.news;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;

import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewFlipper;

import com.xiaowu.news.service.SyncHttp;
import com.xiaowu.news.thread.PostCommentsThread;

public class NewsDetailActivity extends Activity {

	private final int FINISH = 0;				//代表线程的状态的结束
	private LayoutInflater mNewsbodyLayoutInflater;
	private ViewFlipper mNewsBodyFlipper;		//屏幕切换控件
	private ArrayList<HashMap<String, Object>> mNewsData;
	private float mStartX;						//手指按下的开始位置
	private int mPosition = 0;					//点击新闻位置		
	private int mCursor = 0;					//用来标记新闻点击的位置
	private int mNid;							//新闻编号
	private Button mNewsDetailTitleBarComm;		//显示评论条数的按钮
	private ConstomTextView mNewsBodyDetail;	//新闻详细内容
	private LinearLayout mNewsReplyEditLayout;	//新闻回复的布局
	private LinearLayout mNewsReplyImgLayout;	//新闻图片回复的布局
	private EditText mNewsReplyEditText;		//新闻回复的文本框
	private ImageButton mShareNewsButton;		//分享新闻的按钮
	private ImageButton mFavoritesButton;		//收藏新闻的按钮
	private boolean keyboardShow;				//键盘是否显示
	private Handler mHandler = new Handler() {

		@SuppressWarnings("unchecked")
		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			switch (msg.arg1) {
			case FINISH:
				//把获取到的新闻显示到界面上
				ArrayList<HashMap<String, Object>> bodyList = (ArrayList<HashMap<String, Object>>) msg.obj;
				mNewsBodyDetail.setText(bodyList);
				break;
			}
		}
	};

	@SuppressWarnings("unchecked")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.newsdetails_layout);

		mNewsReplyEditLayout = (LinearLayout) findViewById(R.id.news_reply_edit_layout);
		mNewsReplyImgLayout = (LinearLayout) findViewById(R.id.news_reply_img_layout);
		
		Button newsDetailPrev = (Button) findViewById(R.id.newsdetail_titlebar_previous);
		Button newsDetailNext = (Button) findViewById(R.id.newsdetail_titlebar_next);
		mNewsDetailTitleBarComm = (Button) findViewById(R.id.newsdetail_titlebar_comments);
		mNewsReplyEditText = (EditText) findViewById(R.id.news_reply_edittext);
		mShareNewsButton = (ImageButton) findViewById(R.id.news_share_btn);
		mFavoritesButton = (ImageButton) findViewById(R.id.news_favorites_btn);
		
		
		NewsDetailOnClickListener newsDetailOnClickListener = new NewsDetailOnClickListener();
		
		newsDetailPrev.setOnClickListener(newsDetailOnClickListener);
		newsDetailNext.setOnClickListener(newsDetailOnClickListener);
		mNewsDetailTitleBarComm.setOnClickListener(newsDetailOnClickListener);
		mShareNewsButton.setOnClickListener(newsDetailOnClickListener);
		mFavoritesButton.setOnClickListener(newsDetailOnClickListener);
		
		Button newsReplyPost = (Button) findViewById(R.id.news_reply_post);
		newsReplyPost.setOnClickListener(newsDetailOnClickListener);
		ImageButton newsReplyImgBtn = (ImageButton) findViewById(R.id.news_reply_img_btn);
		newsReplyImgBtn.setOnClickListener(newsDetailOnClickListener);
		
		
		//获取传送的数据
		Intent intent = getIntent();
		Bundle bundle = intent.getExtras();
		String categoryName = bundle.getString("categoryTitle");
		TextView titleBarTitle = (TextView) findViewById(R.id.newsdetail_titlebar_title);
		//设置标题栏的标题
		titleBarTitle.setText(categoryName);
		//获取新闻集合
		Serializable serializable = bundle.getSerializable("newsData");
		mNewsData = (ArrayList<HashMap<String, Object>>) serializable;

		//获取点击位置
		mCursor = mPosition = bundle.getInt("position");
		
		mNewsBodyFlipper = (ViewFlipper) findViewById(R.id.news_body_flipper);
		// 获取LayoutInflater对象
		mNewsbodyLayoutInflater = getLayoutInflater();
		
		inflateView(0);
		//启动线程
		new UpdateNewsThread().start();
	}

	/**
	 * 显示上一条新闻
	 */
	private void showPrevious() {
		if(mPosition > 0) {
			mPosition--;
			//记录当前新闻编号
			HashMap<String, Object> hashMap = mNewsData.get(mPosition);
			mNid = (Integer) hashMap.get("nid");
			if(mCursor > mPosition){
				mCursor = mPosition;
				inflateView(0);
				mNewsBodyFlipper.showNext();
			}
			mNewsBodyFlipper.setInAnimation(this, R.anim.push_right_in);	//设置下一页进来时的动画
			mNewsBodyFlipper.setOutAnimation(this, R.anim.push_right_out);	//设置当前页出去的动画
			mNewsBodyFlipper.showPrevious();
		}
		else {
			Toast.makeText(NewsDetailActivity.this, "没有上一篇新闻", Toast.LENGTH_SHORT).show();
		}
	}

	/**
	 * 显示下一条新闻
	 */
	private void showNext() {
		if(mPosition < mNewsData.size() - 1){
			// 设置下一屏动画
			mNewsBodyFlipper.setInAnimation(this, R.anim.push_left_in);
			mNewsBodyFlipper.setOutAnimation(this, R.anim.push_left_out);
			mPosition++;
			//记录当前新闻编号
			HashMap<String, Object> hashMap = mNewsData.get(mPosition);
			mNid = (Integer) hashMap.get("nid");
			if(mPosition >= mNewsBodyFlipper.getChildCount()){
				inflateView(mNewsBodyFlipper.getChildCount());
			}
			mNewsBodyFlipper.showNext();
		} else {
			Toast.makeText(NewsDetailActivity.this, "没有下篇新闻", Toast.LENGTH_SHORT).show();
		}
	}

	private void inflateView(int index) {
		//获取点击新闻信息
		HashMap<String, Object> hashMap = mNewsData.get(mPosition);
		mNid = (Integer) hashMap.get("nid");

		View mNewsBodyView = mNewsbodyLayoutInflater.inflate(
				R.layout.newsbody_layout, null);
		mNewsDetailTitleBarComm.setText(hashMap.get("newslist_item_comments").toString() + "跟帖");
		//新闻标题
		TextView newsTitle = (TextView) mNewsBodyView
				.findViewById(R.id.news_body_title);
		newsTitle.setText(hashMap.get("newslist_item_title").toString());
		//新闻的出处和发布时间
		TextView newsPtimeAndSource = (TextView) mNewsBodyView
				.findViewById(R.id.news_body_ptime_source);
		newsPtimeAndSource.setText(hashMap.get("newslist_item_source").toString() 
				+ "		" + hashMap.get("newslist_item_ptime").toString());
		mNewsBodyDetail = (ConstomTextView) mNewsBodyView
				.findViewById(R.id.news_body_details);
		mNewsBodyDetail.setText(getNewsBody());
		mNewsBodyFlipper.addView(mNewsBodyView, index);
		mNewsBodyDetail.setOnTouchListener(new NewsBodyOntouchListener());
	}

	// 定义内部类--用于处理标题栏的按钮的触发事件
	private class NewsDetailOnClickListener implements OnClickListener {

		@Override
		public void onClick(View v) {
			InputMethodManager m = (InputMethodManager) mNewsReplyEditText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
			// TODO Auto-generated method stub
			switch (v.getId()) {
			//上一篇
			case R.id.newsdetail_titlebar_previous:
				showPrevious();
				break;
			//下一篇
			case R.id.newsdetail_titlebar_next:
				showNext();
				break;
			//跟帖
			case R.id.newsdetail_titlebar_comments:
				Intent intent = new Intent(NewsDetailActivity.this,
						CommentsActivity.class);
				intent.putExtra("nid", mNid);
				startActivity(intent);
				break;
			//“写跟帖”图片
			case R.id.news_reply_img_btn:
				mNewsReplyEditLayout.setVisibility(View.VISIBLE);
				mNewsReplyImgLayout.setVisibility(View.GONE);
				mNewsReplyEditText.requestFocus();
				//显示输入法
				m.toggleSoftInput(0, InputMethodManager.SHOW_IMPLICIT);
				keyboardShow = true;
				break;
			//分享按钮
			case R.id.news_share_btn:
				Intent shareIntent = new Intent(Intent.ACTION_SEND);
				//纯文本
				shareIntent.setType("text/plain");
				shareIntent.putExtra(Intent.EXTRA_SUBJECT, "分享");
				shareIntent.putExtra(Intent.EXTRA_TEXT, "我想将这个分享给你...."+ getTitle());
				startActivity(Intent.createChooser(shareIntent, getTitle()));
				break;
			//收藏按钮
			case R.id.news_favorites_btn:
				Toast.makeText(NewsDetailActivity.this, "收藏成功", Toast.LENGTH_SHORT).show();
				break;
			//发表按钮
			case R.id.news_reply_post:
				//隐藏输入法
				m.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
				String str = mNewsReplyEditText.getText().toString();
				if(str.equals("")){
					Toast.makeText(NewsDetailActivity.this, "不能为空",
							Toast.LENGTH_SHORT).show();
				}
				else {
					mNewsReplyEditLayout.post(new PostCommentsThread(mNid, "广州市",
							str + "",
							new NewsDetailActivity()));
					mNewsReplyEditLayout.setVisibility(View.GONE);
					mNewsReplyImgLayout.setVisibility(View.VISIBLE);
				}
				break;
			}
		}
	}

	private class NewsBodyOntouchListener implements OnTouchListener {

		@Override
		public boolean onTouch(View v, MotionEvent event) {
			// TODO Auto-generated method stub
			switch (event.getAction()) {
				//手指按下
			case MotionEvent.ACTION_DOWN:
				if(keyboardShow){
					mNewsReplyEditLayout.setVisibility(View.GONE);
					mNewsReplyImgLayout.setVisibility(View.VISIBLE);
					//隐藏输入法
					InputMethodManager m = (InputMethodManager) mNewsReplyEditText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
					m.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
					keyboardShow = false;
				}
				//得到按下的横坐标的位置
				mStartX = event.getX();
				break;
			case MotionEvent.ACTION_UP:
				// 往左滑动
				if (event.getX() < mStartX) {
					showNext();
				}
				// 往右滑动
				else if (event.getX() > mStartX) {
					showPrevious();
				}
				break;
			}
			return true;
		}
	}
	
	/**
	 * 定义一个线程类,用来更新获取到新闻的信息
	 * @author Administrator
	 *
	 */
	private class UpdateNewsThread extends Thread {
		@Override
		public void run() {
			// TODO Auto-generated method stub
			ArrayList<HashMap<String, Object>> newsStr = getNewsBody();
			Message msg = mHandler.obtainMessage();	//获取msg
			msg.arg1 = FINISH;			
			msg.obj = newsStr;
			mHandler.sendMessage(msg);	//给Handler发送信息
		}
	}
	
	
	/**
	 * 获取新闻详细信息
	 * @return
	 */
	private ArrayList<HashMap<String, Object>> getNewsBody(){
		//String retStr = "网络连接失败,请稍后再试";
		ArrayList<HashMap<String, Object>> bodylist = new ArrayList<HashMap<String,Object>>();
		
		SyncHttp syncHttp = new SyncHttp();
		//模拟器:url = "http://10.0.2.2:8080/web/getNews";
		//本机:http://127.0.0.1:8080
		//wifi局域网:http://192.168.220.1:8080
		String url = "http://10.0.2.2:8080/web/getNews";
		String params = "nid=" + mNid;
		try {
			String retString = syncHttp.httpGet(url, params);
			JSONObject  jsonObject = new JSONObject(retString);
			//获取返回码,0表示成功
			int retCode = jsonObject.getInt("ret");
			if(retCode == 0) {
				JSONObject dataObject = jsonObject.getJSONObject("data");
				JSONObject newsObject = dataObject.getJSONObject("news");
				//retStr = newsObject.getString("body");
				JSONArray bodyArray = newsObject.getJSONArray("body");
				for(int i = 0; i < bodyArray.length(); i++) {
					JSONObject object = (JSONObject) bodyArray.opt(i);
					HashMap<String, Object> hashMap = new HashMap<String, Object>();
					hashMap.put("index", object.get("index"));
					hashMap.put("type", object.get("type"));
					hashMap.put("value", object.get("value"));
					bodylist.add(hashMap);
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return bodylist;
	}
	
	
	@Override
	public boolean onCreatePanelMenu(int featureId, Menu menu) {
		// TODO Auto-generated method stub
		menu.add(0, 0, 0, "分享");
		return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// TODO Auto-generated method stub
		switch(item.getItemId()) {
		case 0:
			Intent shareIntent = new Intent(Intent.ACTION_SEND);
			//纯文本
			shareIntent.setType("text/plain");
			shareIntent.putExtra(Intent.EXTRA_SUBJECT, "分享");
			shareIntent.putExtra(Intent.EXTRA_TEXT, "我想把这个分享给你:" + getTitle());
			shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			startActivity(Intent.createChooser(shareIntent, getTitle()));
			System.out.println(getTitle());
			break;
			
		}
		return super.onOptionsItemSelected(item);
	}
}


 

 

这段代码设计到以下几个关键点:

1.异步更新新闻详细内容。 这里是用Handler来实现线程异步。

2.实现上下篇新闻切换的功能。

3.自定义TextView的实现类ConstomTextView。

 

 

关于上面的代码已经实现得比较完善了,不知道是否还可以进行优化。

那么关于新闻详细内容显示的业务逻辑实现就写到这里,然后关于小巫新闻客户端开发的系列博客就暂时记录到这里,感谢网友们的支持。因为新闻回复的内容具体实现没什么可说的,只要把前面的业务逻辑实现弄懂了,新闻回复的业务逻辑也就没什么难的。

  如果网友们对小巫新闻客户端那部分有疑问,可以给我留言,小巫会把自己知道的东西都写出来。

你可能感兴趣的:(基于Android的小巫新闻客户端开发---显示新闻详细内容业务逻辑实现)