1,列表功能,信息是以列表的形式展示出来的
2,列表要能实现下拉刷新,上拉加载的功能
3,图片与文字并存
4,点击其中一项的不同区域,会跳到不同的详细页面,点击标题会跳动到一个页面,点击下面信息概要又会跳到另一个页面
IndexList.java
/**
* 用于显示在index_fragment中ListView的内容
* Created by cg on 2015/10/29.
*/
public class IndexList {
private int questionID; //问题ID
private String questionTitle; //问题标题
private String questionSize; //问题点在字节数
private String questionContent; //问题内容
private String userPic; //发问者头像
public IndexList() {
}
public IndexList(int questionID, String questionTitle, String questionSize, String questionContent, String userPic) {
this.questionID = questionID;
this.questionTitle = questionTitle;
this.questionSize = questionSize;
this.questionContent = questionContent;
this.userPic = userPic;
}
public int getQuestionID() {
return questionID;
}
public void setQuestionID(int questionID) {
this.questionID = questionID;
}
public String getQuestionTitle() {
return questionTitle;
}
public void setQuestionTitle(String questionTitle) {
this.questionTitle = questionTitle;
}
public String getQuestionSize() {
return questionSize;
}
public void setQuestionSize(String questionSize) {
this.questionSize = questionSize;
}
public String getQuestionContent() {
return questionContent;
}
public void setQuestionContent(String questionContent) {
this.questionContent = questionContent;
}
public String getUserPic() {
return userPic;
}
public void setUserPic(String userPic) {
this.userPic = userPic;
}
}
/**
* 常量信息
* Created by cg on 2015/10/29.
*/
public class configStatic {
/**
* webServies地址的命名空间,域名
*/
public static String WEBSERVIESNAMESPACE = "http://tempuri.org/";
/**
* webServies明确地址
*/
public static String WEBSERVIESURL = "http://192.168.0.163:8090/webServices/questionInfo.asmx";
/**
* webServices的方法名_用来提取10条问题
*/
public static String WEBSERVICES_INDEXLIST = "getQuestionList";
}
这里的地址是我本地的地址,下面是它传回来的数据格式:
[{"questionID":28,"questionTitle":"苍井空老师的个人简介","questionSize":"387","questionContent":"\r\n 苍井空,1983年11月11日出生于日本东京。日本AV女演员、
成人模特,兼电视、电影演员。日本女子组合惠比寿麝香葡萄的初代首领,现成员、OG首领。2010年3月毕业并将组合首领之位交托给麻美由真,同年10月复归。
\r\n 入行前曾是泳装写真女星,2002年进入AliceJapan公司,开始性感影片的拍摄生涯。因为其“童颜巨乳”的特色,开始获得人气,并连续在2003年及2004年蝉联日本
《VideoBoy》杂志年度性感女艺人第一名。[1] 从2003年起,开始参加一般电视戏剧及综艺节目中演出,[2] 2004年11月移籍到S1,成功转型,大牌杂志模特及电影演员。
\r\n","userPic":"http://imgcdn.kdnet.net/UploadSmall/2013/07/21/137438445351976.jpg"},{"questionID":27,"questionTitle":"波多野结衣的故事",
"questionSize":"679","questionContent":"波多野结衣(はたの ゆい),女,1988年5月24日出生于日本京都府,著名日本女演员、AV女优。
2008年,波多野结衣开始从事AV出演,并于11月加入H.M.P公司,成为H.M.P的素人,不久便被H.M.P公司雪藏,随后在BeFree公司发行过两部影片,
又转投ATTACKER公司,后又签约SKY HIGH公司。2012年,波多野结衣出席第九届上海国际成人展开幕和第二届台湾成人博览会。",
"userPic":"http://img1.imgtn.bdimg.com/it/u=1823077414,3028399801\u0026fm=21\u0026gp=0.jpg"}]
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
/**
* webservice 操作类
* Created by cg on 2015/10/29.
*/
public class webservicesUntils {
private static SoapObject rpc = null;
private static SoapSerializationEnvelope envelope = null;
private static HttpTransportSE ht = null;
/**
* 调用问题信息
* @param strWhere 查询条件
* @param orderby 排序字段
* @param startIndex 开始记录数
* @param endIndex 结束记录数
* @return
* @throws Exception
*/
public static String getIndexItemList(final String strWhere,final String orderby,final int startIndex,final int endIndex) throws IOException, XmlPullParserException, IOException, XmlPullParserException {
rpc = new SoapObject(configStatic.WEBSERVIESNAMESPACE, configStatic.WEBSERVICES_INDEXLIST);
// 设置调用方法参数的值
rpc.addProperty("strWhere", strWhere);
rpc.addProperty("orderby", orderby);
rpc.addProperty("startIndex", startIndex);
rpc.addProperty("endIndex",endIndex);
// 生成调用Webservice方法的SOAP请求信息
envelope = new SoapSerializationEnvelope(SoapEnvelope.VER12); //这里要注意,这里是webService的版本号,一般是10,11,12这三个值,如果你不确定,可以每个都试一下
envelope.bodyOut = rpc;
envelope.dotNet = true;
envelope.setOutputSoapObject(rpc);
// 创建HttpTransportSE对象,通过HttpTransportSE类的构造方法可以指定WebService的url
ht = new HttpTransportSE(configStatic.WEBSERVIESURL);
ht.debug = true;
// 使用call方法调用WebService方法
ht.call(null, envelope);
String result = "0";
//检查ht.call是否运行
//Log.e("city", strWhere + startIndex + endIndex);
// 判断取到的值是否为空
if(envelope.getResponse() == null) {
result = "0";
}else{
result = envelope.getResponse().toString();
}
return result;
}
}
public void onPullDownToRefresh(PullToRefreshBase refreshView) {
// 模拟加载任务
}
@Override
public void onPullUpToRefresh(PullToRefreshBase refreshView) {
}
是用来实现上拉加载,下拉刷新的,而且都是要通过异步来进行加载的。好了,我们来修改一下首页的java代码吧
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.Toast;
import com.example.cg.zhihu_one.untils.netUntils;
import com.example.cg.zhihu_one.untils.webservicesUntils;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
/**
* 首页
* Created by cg on 2015/10/27.
*/
public class IndexFragment extends Fragment {
//定义信息等等控件
private ProgressDialog myProgressDialog;
private PullToRefreshListView pullrefresh_index_list; //定义信息列表
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_index,container,false);
initControls(view);
return view;
}
/**
* 对下拉列表控件进行初始化,并初始化进度控件
* @param view
*/
private void initControls(View view) {
pullrefresh_index_list = (PullToRefreshListView)view.findViewById(R.id.pullrefresh_index_list);
//初始化数据
initDatas();
// 设置下拉和上拖监听事件
pullrefresh_index_list
.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener2() {
@Override
public void onPullDownToRefresh(PullToRefreshBase refreshView) {
// 模拟加载任务
//new GetDownDataTask().execute();
}
@Override
public void onPullUpToRefresh(PullToRefreshBase refreshView) {
//Log.e("onPullUpToRefresh","有反应没有啊");
//new GetUpDataTask().execute();
}
});
}
/**
* 初始时,加载10条数据上来
*/
private void initDatas()
{
if(netUntils.isNetworkAvailable(getActivity())) {
// 初始化数据和数据源
myProgressDialog = new ProgressDialog(getActivity());
myProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); //设置风格为圆形进度条
myProgressDialog.setTitle("提示"); //设置标题
myProgressDialog.setMessage("数据加载中,请稍等..."); //设置内容
myProgressDialog.setIndeterminate(false); //设置进度是否为不明确
myProgressDialog.setCancelable(true); //设置进度条是否可以按退回键取消
myProgressDialog.show();
new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
try {
String soapObject = webservicesUntils.getIndexItemList("", "", 1, 10);
Log.e("soapObject",soapObject);
msg.arg1 = 1;
handler.sendMessage(msg);
} catch (Exception ex) {
msg.arg1 = 2;
}
}
}).start();
}else
{
Toast.makeText(getActivity(), "请检查您的网络是否打开!", Toast.LENGTH_LONG).show();
}
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.arg1==1)
{
//Log.e("")
}else
{
Toast.makeText(getActivity(), "数据读取失败!", Toast.LENGTH_LONG).show();
}
myProgressDialog.dismiss();
}
};
}
index_list_item.sizebacground.xml
这里要注意一点的是,我们一般喜欢设置一下默认的背景图片或是颜色,这里一定要把这个默认的值放在最下面,不然上面的所有变化就都不好用。
index_list_item.contexttextcolor.xml
index_list_item_sizetextcolor.xml
好,item布局文件搞定,我们来看一下Adapter的代码:
Index_lv_Adapter.java
import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;
import com.android.volley.toolbox.Volley;
import com.example.cg.zhihu_one.R;
import com.example.cg.zhihu_one.models.IndexList;
import com.example.cg.zhihu_one.untils.imagesUntils;
import java.util.List;
/**
* 首页信息列表Adapter
* Created by cg on 2015/10/30.
*/
public class Index_lv_Adapter extends BaseAdapter {
private List list_index; //定义显示的信息列表
private LayoutInflater inflater;
//定义volley
private RequestQueue mQueue;
private ImageLoader imageLoader;
private Context context;
public Index_lv_Adapter(Context context,List list_index) {
this.context = context;
this.inflater = LayoutInflater.from(context);
this.list_index = list_index;
mQueue = Volley.newRequestQueue(context);
imageLoader = new ImageLoader(mQueue,new imagesUntils.BitmapCache(){
@Override
public Bitmap getBitmap(String s) {
return null;
}
@Override
public void putBitmap(String s, Bitmap bitmap) {
}
});
}
@Override
public int getCount() {
return list_index.size();
}
@Override
public Object getItem(int position) {
return list_index.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final index_list_info listclass;
if(convertView==null)
{
listclass = new index_list_info();
convertView = inflater.inflate(R.layout.fragment_index_list_item,null,false);
listclass.userpic = (NetworkImageView)convertView.findViewById(R.id.netimg_index_item_userpic);
listclass.item_title = (TextView)convertView.findViewById(R.id.txt_index_item_title);
listclass.item_size = (TextView)convertView.findViewById(R.id.txt_index_item_size);
listclass.item_content = (TextView)convertView.findViewById(R.id.txt_index_item_content);
listclass.linear_index_item_title = (LinearLayout)convertView.findViewById(R.id.linear_index_item_title);
listclass.linear_index_item_content = (LinearLayout)convertView.findViewById(R.id.linear_index_item_content);
convertView.setTag(listclass);
}
else
{
listclass = (index_list_info)convertView.getTag();
}
//为图片控件加载图片,采用NetworkImageView控件。
//第一项是加载图片控件的默认图片,一般是图片加载中,这样的图片
//第二项是当发生错误的时候加载的图片,如网络图片路径不对或是加载失败的时候显示的图片
//第三项就是加载网络图片了
listclass.userpic.setDefaultImageResId(R.drawable.img_empty_followers);
listclass.userpic.setErrorImageResId(R.drawable.img_empty_followers);
listclass.userpic.setImageUrl(list_index.get(position).getUserPic(), imageLoader);
listclass.item_title.setText(list_index.get(position).getQuestionTitle());
listclass.item_size.setText(list_index.get(position).getQuestionSize());
listclass.item_content.setText(list_index.get(position).getQuestionContent());
// 只所以在这里添加点击事件,而不是为控件添加onitemclistener事件,
// 是因为,在一个item里,点击上半部分和下半部分将要跳转的页面不同
listclass.linear_index_item_content.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/*Intent cIntent = new Intent();
cIntent.setClass(context, Index_detailActivity.class);
cIntent.putExtra("questionID", list_index.get(position).getQuestionID());
cIntent.putExtra("questionTitle",list_index.get(position).getQuestionTitle());
context.startActivity(cIntent);*/
}
});
return convertView;
}
public class index_list_info
{
NetworkImageView userpic;
TextView item_title;
TextView item_size;
TextView item_content;
LinearLayout linear_index_item_title;
LinearLayout linear_index_item_content;
}
}
imagesUntils.java
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.LruCache;
import com.android.volley.toolbox.ImageLoader;
/**
* 各种对图片进行操作的通用方法
* Created by cg on 2015/10/30.
*/
public class imagesUntils {
/**
* 显示保存在手机中的图片,加入了缩小图片的功能,防止OOM
*
* @param imgPath 文件路径
* @param screenWidth 手机宽
* @param screenHeight 手机高
* @return Bitmap类型
*/
public static Bitmap viewPic(String imgPath,int screenWidth,int screenHeight)
{
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; //不去真的解析图片 获取图片头部信息
Bitmap mitmap = BitmapFactory.decodeFile(imgPath, options); //取得图片的信息
int height = options.outHeight; //图片的高
int width = options.outWidth; //图片的宽
// 得到手机屏幕宽高比
int scaleX=width/screenHeight;
int scaleY=height/screenWidth;
int scale=1; //默认缩小比例是1
// 如果高的比例大,并且比例大于1,也就是图片的高要大于手机的高
if(scaleX>scaleY && scaleY>=1)
{
scale=scaleX;
}
if(scaleY>scaleX && scaleX>=1)
{
scale=scaleY;
}
options.inJustDecodeBounds=false; //真的去解析图片
options.inSampleSize=scale; //按比例缩小图片
Bitmap bm = BitmapFactory.decodeFile(imgPath, options);
return bm;
}
/**
* 对图片进行防OOM处理
*/
public static class BitmapCache implements ImageLoader.ImageCache{
private LruCache mCache;
public BitmapCache(){
int maxSize = 10*1024*1024;
mCache = new LruCache(maxSize){
protected int sizeOf(String key,Bitmap bitmap)
{
return bitmap.getRowBytes() * bitmap.getHeight();
}
};
}
@Override
public Bitmap getBitmap(String url) {
return mCache.get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
mCache.put(url,bitmap);
}
}
}
Adapter程序完成,我们来修改首页的程序,为PullToRefreshListView控件绑定数据。修改后的代码如下:
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.Toast;
import com.example.cg.zhihu_one.Adapters.Index_lv_Adapter;
import com.example.cg.zhihu_one.models.IndexList;
import com.example.cg.zhihu_one.untils.netUntils;
import com.example.cg.zhihu_one.untils.webservicesUntils;
import com.handmark.pulltorefresh.library.PullToRefreshBase;
import com.handmark.pulltorefresh.library.PullToRefreshListView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* 首页
* Created by cg on 2015/10/27.
*/
public class IndexFragment extends Fragment {
//定义信息等等控件
private ProgressDialog myProgressDialog;
private PullToRefreshListView pullrefresh_index_list; //定义信息列表
private List list_index; //定义显示数据的list
private Index_lv_Adapter indexAdapter; //定义Adapter
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_index,container,false);
initControls(view);
return view;
}
/**
* 对下拉列表控件进行初始化,并初始化进度控件
* @param view
*/
private void initControls(View view) {
pullrefresh_index_list = (PullToRefreshListView)view.findViewById(R.id.pullrefresh_index_list);
list_index = new ArrayList<>();
//初始化数据
initDatas();
// 设置下拉和上拖监听事件
pullrefresh_index_list
.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener2() {
@Override
public void onPullDownToRefresh(PullToRefreshBase refreshView) {
// 模拟加载任务
new GetDownDataTask().execute();
}
@Override
public void onPullUpToRefresh(PullToRefreshBase refreshView) {
//Log.e("onPullUpToRefresh","有反应没有啊");
new GetUpDataTask().execute();
}
});
}
/**
* 初始时,加载10条数据上来
*/
private void initDatas()
{
if(netUntils.isNetworkAvailable(getActivity())) {
// 初始化数据和数据源
myProgressDialog = new ProgressDialog(getActivity());
myProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); //设置风格为圆形进度条
myProgressDialog.setTitle("提示"); //设置标题
myProgressDialog.setMessage("数据加载中,请稍等..."); //设置内容
myProgressDialog.setIndeterminate(false); //设置进度是否为不明确
myProgressDialog.setCancelable(true); //设置进度条是否可以按退回键取消
myProgressDialog.show();
new Thread(new Runnable() {
@Override
public void run() {
Message msg = new Message();
try {
//得到数据
String soapObject = webservicesUntils.getIndexItemList("", "", 1, 10);
//判断如果数据返回的不是错误代码0,则对返回的json数据进行解析,将数据存入List中
if (soapObject != "0") {
try {
JSONArray jsonArray = new JSONArray(soapObject);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject2 = (JSONObject) jsonArray.opt(i);
IndexList comm = new IndexList();
comm.setUserPic(jsonObject2.getString("userPic"));
comm.setQuestionTitle(jsonObject2.getString("questionTitle"));
comm.setQuestionSize(jsonObject2.getString("questionSize"));
comm.setQuestionContent(jsonObject2.getString("questionContent"));
comm.setQuestionID(jsonObject2.getInt("questionID"));
list_index.add(comm);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
msg.arg1 = 1;
handler.sendMessage(msg);
} catch (Exception ex) {
msg.arg1 = 2;
}
}
}).start();
}else
{
Toast.makeText(getActivity(), "请检查您的网络是否打开!", Toast.LENGTH_LONG).show();
}
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.arg1==1)
{
if(list_index!=null)
{
//设置适配器
indexAdapter = new Index_lv_Adapter(getActivity(),list_index);
pullrefresh_index_list.setAdapter(indexAdapter);
}else
{
Toast.makeText(getActivity(), "无数据加载!", Toast.LENGTH_LONG).show();
}
}else
{
Toast.makeText(getActivity(), "数据读取失败!", Toast.LENGTH_LONG).show();
}
myProgressDialog.dismiss();
}
};
/**
* 下拉时,更新数据,从list中提取第一条数据也就是最新的一条,传回,以供判断是否有新的数据,如果有,则对listView进行刷新
* 通过return将得到的数据返回给protected void onPostExecute(String result),以便在前台显示
*/
private class GetDownDataTask extends AsyncTask
{
//异步取数据
@Override
protected String doInBackground(Void... params)
{
try
{
//这里调用一个webServices取新添加的数据
//原理:取现在list中最新的数据,去后台数据中进行对比,如果有比这个新的数据,就取,没有则返回0
String soapObject = webservicesUntils.getIndexItemList_refresh(String.valueOf(list_index.get(0).getQuestionID()));
return soapObject;
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "" ;
}
//将数据显示在前台
@Override
protected void onPostExecute(String result)
{
if(!result.equals("0"))
{
try {
//我们采用了.add(location,comm)方法,指定了插入的位置,这样就把新的数据直接插入到前面
//list_index.clear(); //清空List<>中的数据
JSONArray jsonArray = new JSONArray(result);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject2 = (JSONObject) jsonArray.opt(i);
IndexList comm = new IndexList();
comm.setUserPic(jsonObject2.getString("userPic"));
comm.setQuestionTitle(jsonObject2.getString("questionTitle"));
comm.setQuestionSize(jsonObject2.getString("questionSize"));
comm.setQuestionContent(jsonObject2.getString("questionContent"));
comm.setQuestionID(jsonObject2.getInt("questionID"));
list_index.add(0,comm);
}
indexAdapter.notifyDataSetChanged();
//num=1;
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//刷新结束,必须加上此句,不然下面的加载图标一下在
pullrefresh_index_list.onRefreshComplete();
}
}
/**
* 向上刷新加载更多的数据
*/
public class GetUpDataTask extends AsyncTask {
@Override
protected String doInBackground(Void... params) {
try {
String soapObject = webservicesUntils.getIndexItemList("", "", list_index.size() + 1, 10);
return soapObject;
} catch (Exception ex) {
return "0";
}
}
@Override
protected void onPostExecute(String result) {
if (result != "0") {
try {
JSONArray jsonArray = new JSONArray(result);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject2 = (JSONObject) jsonArray.opt(i);
IndexList comm = new IndexList();
comm.setUserPic(jsonObject2.getString("userPic"));
comm.setQuestionTitle(jsonObject2.getString("questionTitle"));
comm.setQuestionSize(jsonObject2.getString("questionSize"));
comm.setQuestionContent(jsonObject2.getString("questionContent"));
comm.setQuestionID(jsonObject2.getInt("questionID"));
list_index.add(comm);
}
indexAdapter.notifyDataSetChanged();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//刷新结束,必须加上此句,不然下面的加载图标一下在
pullrefresh_index_list.onRefreshComplete();
}
}
}
显示的结果图:
在这里,要说明的一点是PullToRefreshListView控件的setOnRefreshListener方法, 它里面有两个实现方法, 一个是我们在程序中所使用的
new PullToRefreshBase.OnRefreshListener2
new PullToRefreshBase.OnRefreshListener
可通过http://blog.csdn.net/lmj623565791/article/details/38238749这个blog了解更细的使用说明