您的位置:首页 > 移动开发 > Android开发

带表头 固定列可左右上下滑动的可分页加载的ListView

2014-12-23 10:03 453 查看
随喜结佛缘

          


     

         



                       

项目描述:

        最近做项目,遇到一个问题,就是要求ListView既要有表头,点击表头从能够对特定的列进行排序,并且要求固定第一列,右边的其他列不固定,能够向左滑动的时候,收缩到左侧,向右滑动的时候,显示已经收缩的列,总之就是满足一个需求,一个表里面有很多个列的时候,单个屏幕显示不完所有的列,因此,就做一个可收缩的列表,用于在一个控件里面显示完表中所有的字段。

        


        小的我参考了网上的代码,名字为demoHListView(大家可以到网上搜索下载,或者在我共享的代码中去下载),是用观察者模式来实现的效果,但是我对这个示例做了改造,因为它并不可以支持分页加载以及点击列头按当前列数据排序,还是直接把我的代码贴出来。

         注意:

          1、ListView是用的网上封装好的支持上下拉分页加载的控件(PullToRefreshListView)。这里边儿要注意把封装控件中的ListView对象声明为成员变量,然后通过get()方法返回出来。

          2、返回出来是为了给ListView添加上监听事件,能够监听到手势的左右上下滑动,在ListView左右滑动的时候通知列头也一起滑动。

           改造部分的代码如下:

          


 



      

package com.goodwin.finance.activity.fragment;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.goodwin.finance.R;
import com.goodwin.finance.activity.BaseSlidingFragmentActivity;
import com.goodwin.finance.activity.SearchActivity;
import com.goodwin.finance.activity.TimeShareActivity;
import com.goodwin.finance.bean.HsStockInfo;
import com.goodwin.finance.bean.StockInfo;
import com.goodwin.finance.common.constant.Constants;
import com.goodwin.finance.common.view.HScrollView;
import com.goodwin.finance.common.view.SlidingMenu;
import com.goodwin.finance.comparators.HsStockInfoComparator;
import com.goodwin.finance.database.BaseAppDbHelper;
import com.goodwin.finance.net.socket.response.DataArchitectureBean;
import com.goodwin.finance.net.socket.response.ICSortFastDataBean;
import com.goodwin.finance.net.socket.response.ResponseICSortFastData;
import com.goodwin.finance.pulltorefresh.PullToRefreshBase;
import com.goodwin.finance.pulltorefresh.PullToRefreshBase.Mode;
import com.goodwin.finance.pulltorefresh.PullToRefreshBase.OnRefreshListener2;
import com.goodwin.finance.pulltorefresh.PullToRefreshListView;
import com.goodwin.finance.widget.MarketShenAdapter;

/**
* @author Administrator
*/
public class MarketShenFragment extends BaseFragment implements OnClickListener, OnRefreshListener2<ListView> {

private static final String TAG = "MarketShenFragment";
BaseAppDbHelper<StockInfo> dbHelper = new BaseAppDbHelper<StockInfo>();
// 回退按钮
private ImageView ivImgBack;
// 界面标题
private TextView tvTitle;
// 搜索按钮
private ImageView ivSearch;
// 股票列表控件
private PullToRefreshListView ptrlHsList;
// 适配器
private MarketShenAdapter adapter;
// 股票列表数据对象
private List<HsStockInfo> stockInfoList;
// 缓存股票列表数据
private List<HsStockInfo> cacheStockInfoList;
// 头部布局
private LinearLayout llHead;
// 水平托动隐藏标题控件
private HScrollView hScrollView;
// 水平标题箭头
private ImageView ivZhArrow;
// 根据默认进入为降序,第一次点击变升序,再点变降序;排序在后台计算,前端不做计算,页面刷新时更换;
private LinearLayout llTitleZh;
// 降序或升序的标志
private int sortType = Constants.sort_type.SORT_DESC;
// 意图
private Intent intent;
// 接收数据框架数据
private DataArchitectureBean dataArchitectureBean;
// 报价列表数据
private ResponseICSortFastData responseIcSortFastData;
// 排行股票详细数据
private List<ICSortFastDataBean> icSortFastDataBeanList;
//第几页
private int offset;
//页大小
private int count = 20;
// 报价列表记时器
private Timer priceListTimer;
// 记时器任务
private TimerTask priceListTimerTask;
//请求第一页
private int requestFirst = 1;
//是否是刷新
private boolean refreshState = true;

/**
* 加载界面布局
*/
@Override
protected int getViewId() {
return R.layout.market_shen;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
put("intoHushenTime", 0);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
try {
if (view != null) {
findViews(view);
initCtrl();
setListener();
}
} catch (Exception e) {
Log.i(TAG, "MarketShenFragment的onCreateView()方法异常!", e);
e.printStackTrace();
}
return view;
}

/**
* 初始化控件
*/
private void findViews(View view) {
try {
ivImgBack = (ImageView) view.findViewById(R.id.iv_img_back);
tvTitle = (TextView) view.findViewById(R.id.tv_title);
ivSearch = (ImageView) view.findViewById(R.id.iv_search);
hScrollView = (HScrollView) view.findViewById(R.id.hsl_view);
llTitleZh = (LinearLayout) view.findViewById(R.id.ll_title_zh);
ivZhArrow = (ImageView) view.findViewById(R.id.iv_zh_arrow);
ptrlHsList = (PullToRefreshListView) view.findViewById(R.id.ptrl_hs_list);
llHead = (LinearLayout) view.findViewById(R.id.ll_head);
} catch (Exception e) {
Log.i(TAG, "MarketShenFragment的findViews()方法异常!", e);
e.printStackTrace();
}
}

/**
* 初始化分时图记时器
*/
public void initTimer() {
priceListTimer = new Timer(true);
priceListTimerTask = new PriceListTimerTask();
if (null != priceListTimer) {
priceListTimer.schedule(priceListTimerTask, 6 * 1000);
}
}

/**
* 报价列表计时器任务
*/
public class PriceListTimerTask extends TimerTask {
@Override
public void run() {
refreshState = true;
requestAStockList(offset, count);
priceListTimerTask.cancel();
}
}

/**
* 取消计时器
*/
private void removeTimerTask() {
if (null != priceListTimer && null != priceListTimerTask) {
priceListTimerTask.cancel();
}
}

@Override
public void onResume() {
super.onResume();
int time = Integer.parseInt(get("intoHushenTime").toString());
if (time != 0) {
Log.i(TAG, "================再次开启沪深A股报价列表刷新计时器=================");
initTimer();
}
}

@Override
public void onPause() {
super.onPause();
Log.i(TAG, "================结束计时器=================");
removeTimerTask();
}

@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "================离开界面结束计时器=================");
put("intoHushenTime", 0);
removeTimerTask();
}

/**
* 注册监听事件
*/
private void setListener() {
try {
llHead.setOnTouchListener(new ListViewAndHeadViewTouchLinstener());
if (null != ptrlHsList.getLv()) {
ptrlHsList.getLv().setOnTouchListener(new ListViewAndHeadViewTouchLinstener());
}
ptrlHsList.setOnRefreshListener(this);
ptrlHsList.setMode(Mode.BOTH);

llTitleZh.setOnClickListener(this);
ptrlHsList.setOnItemClickListener(onItemClickListener);
ivSearch.setOnClickListener(this);
ivImgBack.setOnClickListener(this);
} catch (Exception e) {
Log.i(TAG, "MarketShenFragment的setListener()方法异常!", e);
e.printStackTrace();
}
}

/**
* 接收到数据之后更新UI界面
*/
@Override
public void onUpdateUI(int taskId, Object data) {
super.onUpdateUI(taskId, data);
try {
if (null != data) {
switch (taskId) {
case Constants.Hq.RECEIVE_PRICE_LIST_INFO:
bindPriceList(data);
break;
}
}
} catch (Exception e) {
Log.i(TAG, "MarketShenFragment的onUpdateUI()方法异常!", e);
e.printStackTrace();
}
}

/**
* 1、绑定沪深A股报价列表数据
*/
@SuppressWarnings("unchecked")
private void bindPriceList(Object data) {
if (data instanceof ResponseICSortFastData) {
dismissNetProgressBar();
responseIcSortFastData = (ResponseICSortFastData) data;
icSortFastDataBeanList = responseIcSortFastData.getIcSortFastDataBeanList();
if (null != icSortFastDataBeanList && icSortFastDataBeanList.size() > 0) {
//1、遍历获取到的报价列表
//2、根据报价列表的股票代码,去数据框架中查询股票名称
//3、拼装成沪深A股报价新列表对象
HashMap<String, String> codeNameMap = (HashMap<String, String>) get("codeNameMap");
ArrayList<HsStockInfo> stockInfoList = new ArrayList<HsStockInfo>();
for (ICSortFastDataBean icSortFastDataBean : icSortFastDataBeanList) {
if (null != icSortFastDataBean) {
String stockCode = icSortFastDataBean.getPtrStockLabel();//股票代码
int marketType = icSortFastDataBean.getMarketType();//市场类型
String stockName = codeNameMap.get(marketType + stockCode);//股票名称
double hsNew = icSortFastDataBean.getPrice();//最新
double hsZh = icSortFastDataBean.getDeltaPercent() * 100;//涨愊
double hsZd = icSortFastDataBean.getDelta(); //涨跌
double hsZs = icSortFastDataBean.getPreClose();//昨收
double hsCjl = icSortFastDataBean.getTotalVol();//成交量 总手数
double hsCje = icSortFastDataBean.getAmount();//成交额
double hsZg = icSortFastDataBean.getHigh();//最高
double hsZuidi = icSortFastDataBean.getLow();//最低
double hsJk = icSortFastDataBean.getOpen();//今开
double hsLb = icSortFastDataBean.getVolumeRate();//量比
double hsZhenhu = icSortFastDataBean.getSwing() * 100;//振幅
HsStockInfo stockInfo = new HsStockInfo(stockName, stockCode, marketType, hsNew, hsZh, hsZd, hsZs, hsCjl, hsCje, hsZg, hsZuidi, hsJk, hsLb, hsZhenhu);
stockInfoList.add(stockInfo);
}
}

if (null != stockInfoList && stockInfoList.size() > 0) {
//如果是首次请求数据,则初始化适配器,然后填充数据,并且将股票数据填充进缓存列表
if (requestFirst == 1) {
if (null != cacheStockInfoList) {
cacheStockInfoList.clear();
}
cacheStockInfoList = new ArrayList<HsStockInfo>();
cacheStockInfoList.addAll(stockInfoList);
stockInfoList = (ArrayList<HsStockInfo>) HsStockInfoComparator.sortList(stockInfoList, sortType);
adapter.setStockInfoList(stockInfoList);
ptrlHsList.onRefreshComplete();

Log.i(TAG, "第一次请求==========" + stockInfoList.size() + "条");
Log.i(TAG, "第一次请求缓存==========" + cacheStockInfoList.size() + "条");

} else {
if (!refreshState) {
cacheStockInfoList.addAll(stockInfoList);
cacheStockInfoList = HsStockInfoComparator.sortList(cacheStockInfoList, sortType);
adapter.setStockInfoList(cacheStockInfoList);
Log.i(TAG, "分页请求==========" + stockInfoList.size() + "条");
Log.i(TAG, "分页请求缓存==========" + cacheStockInfoList.size() + "条");
}
ptrlHsList.onRefreshComplete();
}
} else {
tips("亲!已经是最后一页了!");
ptrlHsList.onRefreshComplete();
}

//开启沪深A股报价列表刷新计时器
Log.i(TAG, "================开启沪深A股报价列表刷新计时器=================");
initTimer();
}
}
}

/**
* 初始化控件数据
*/
private void initCtrl() {
try {
dataArchitectureBean = (DataArchitectureBean) getGoodWinApplication().getGlobalData().get("dataArchitectureBean");
ivZhArrow.setImageResource(R.drawable.stock_arrow_down);
tvTitle.setText("沪深");
llHead.setFocusable(true);
llHead.setClickable(true);

if (Integer.parseInt(get("intoHushenTime").toString()) == 0) {
showNetProgressBar();
// 查询沪深A股报价列表
this.offset = 0;
requestAStockList(offset, count);
}

adapter = new MarketShenAdapter(getActivity());
adapter.setHeadSrcrollView(hScrollView);
ptrlHsList.setAdapter(adapter);

} catch (Exception e) {
Log.i(TAG, "MarketShenFragment的initCtrl()方法异常!", e);
e.printStackTrace();
}
}

/**
* 1、请求沪深A股报价列表
*/
private void requestAStockList(int offset, int count) {
try {
if (null != dataArchitectureBean) {
requestHqService.sendMessageToServer(getHQIoSession(), requestHqService.requestFeiZiXuanPriceList(dataArchitectureBean, offset, count, Constants.HqMarketType.HSZS,sortType));
}
} catch (Exception e) {
Log.i(TAG, "MarketShenFragment的requestAStockList()方法异常!", e);
e.printStackTrace();
}
}

/**
* ListView 水平托动监听事件
*
* @author Administrator
*/
@SuppressLint("ClickableViewAccessibility")
class ListViewAndHeadViewTouchLinstener implements View.OnTouchListener {
@Override
public boolean onTouch(View v, MotionEvent arg1) {
// 当在列头 和 listView控件上touch时,将这个touch的事件分发给 ScrollView
HorizontalScrollView headSrcrollView = (HorizontalScrollView) llHead.findViewById(R.id.hsl_view);
headSrcrollView.onTouchEvent(arg1);
return false;
}
}

@SuppressLint("ClickableViewAccessibility")
class ViewOnTouchListener implements View.OnTouchListener {

@Override
public boolean onTouch(View v, MotionEvent event) {

return false;
}
}

private OnItemClickListener onItemClickListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
//结束记时器
Log.i(TAG, "================结束沪深A股计时器=================");
put("intoHushenTime", 1);
removeTimerTask();

adapter.setSelectItemPosition(position - 1);
adapter.notifyDataSetInvalidated();
//结束计时器
removeTimerTask();
// 跳转到沪深A股行情分时图界面
HsStockInfo hsStockInfo = adapter.getStockInfoList().get(position - 1);
//保存或更新到数据库中
StockInfo stockInfo = new StockInfo();
stockInfo.setStockCode(hsStockInfo.getStockCode());
stockInfo.setStockName(hsStockInfo.getStockName());
stockInfo.setMarketId(hsStockInfo.getMarketType() + "");
long viewTime = System.currentTimeMillis();
stockInfo.setViewTime(viewTime);
HashMap<String, Object> where = new HashMap<String, Object>();
where.put("stock_code", stockInfo.getStockCode());
where.put("market_id", stockInfo.getMarketId());
dbHelper.createOrExistsUpdate(stockInfo, where, "view_time", viewTime);

intent = new Intent(getActivity(), TimeShareActivity.class);
intent.putExtra("hsStockInfo", hsStockInfo);
getActivity().startActivity(intent);
}
};

@Override
public void onClick(View v) {
try {
switch (v.getId()) {
case R.id.iv_img_back:
BaseSlidingFragmentActivity baseFragment = (BaseSlidingFragmentActivity) getActivity();
SlidingMenu mSlidingMenu = baseFragment.getSlideMenu();
mSlidingMenu.showMenu();
break;
case R.id.iv_search: // 搜索按钮
startActivity(new Intent(getActivity(), SearchActivity.class));
break;
case R.id.ll_title_zh:
if(sortType == Constants.sort_type.SORT_DESC){
sortType = Constants.sort_type.SORT_ASC;
ivZhArrow.setImageResource(R.drawable.stock_arrow_up);
if(null != cacheStockInfoList){
cacheStockInfoList = HsStockInfoComparator.sortList(cacheStockInfoList, sortType);
adapter.setStockInfoList(cacheStockInfoList);
}
requestAStockList(offset, count);

}else{
sortType = Constants.sort_type.SORT_DESC;
ivZhArrow.setImageResource(R.drawable.stock_arrow_down);
if(null != cacheStockInfoList){
cacheStockInfoList = HsStockInfoComparator.sortList(cacheStockInfoList, sortType);
adapter.setStockInfoList(cacheStockInfoList);
}
requestAStockList(offset, count);
}
break;
}
} catch (Exception e) {
Log.i(TAG, "MarketShenFragment的onClick()方法异常!", e);
}
}

@Override
public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
try {
String label = DateUtils.formatDateTime(this.getActivity(), System.currentTimeMillis(), DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL);
refreshView.getLoadingLayoutProxy().setLastUpdatedLabel(label);
requestFirst = 1;
this.offset = 0;
requestAStockList(offset, count);
} catch (Exception e) {
e.printStackTrace();
Log.i(TAG, "MarketShenFragment的onPullDownToRefresh()方法异常!", e);
}
}

@Override
public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
try {
String label = DateUtils.formatDateTime(this.getActivity(), System.currentTimeMillis(), DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL);
refreshView.getLoadingLayoutProxy().setLastUpdatedLabel(label);
refreshState = false;
requestFirst = 2;
this.offset = offset + count;
requestAStockList(offset, count);
} catch (Exception e) {
e.printStackTrace();
Log.i(TAG, "MarketShenFragment的onPullUpToRefresh()方法异常!", e);
}
};

}


         页面布局部分的代码:

         注意布局这部分的代码很关键,要把示例中的最外层控件移除才可以保证点击列头的时候,每一页可以点击,不会抢占列头里层控件的焦点,这也才能保证点击列头排序功能的实现。

       

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_head"
style="@style/s_page_bg" >

<!-- 沪深A股列表界面 -->
<!-- 头部 -->

<LinearLayout
style="@style/s_head_out"
android:baselineAligned="false" >

<LinearLayout style="@style/s_head_left" >

<ImageView
android:id="@+id/iv_img_back"
style="@style/s_head_left_bt"
android:contentDescription="@string/imagedescription" />
</LinearLayout>

<LinearLayout style="@style/s_head_center" >

<TextView
android:id="@+id/tv_title"
style="@style/s_page_head_title"
android:text="@string/s_free_title" />
</LinearLayout>

<LinearLayout style="@style/s_head_right" >

<ImageView
android:id="@+id/iv_search"
style="@style/s_head_right_bt"
android:contentDescription="@string/imagedescription" />
</LinearLayout>
</LinearLayout>

<!-- 可水平托动的标题头部 -->

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="36dip"
android:gravity="center_vertical"
android:orientation="horizontal"
android:background="@drawable/border">

<!-- 沪深A股 -->

<RadioButton
android:id="@+id/rb_stock_type"
style="@style/s_horizontal_list_head_common_first"
android:text="@string/s_hs_astock" />

<com.goodwin.finance.common.view.HScrollView
android:id="@+id/hsl_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="none" >

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginLeft="@dimen/st_hq_layout_marginLeft"
android:gravity="center_vertical"
android:orientation="horizontal" >

<!-- 最新 -->

<RadioButton
android:id="@+id/rb_new"
style="@style/s_horizontal_list_head_common"
android:text="@string/s_hs_new" />

<LinearLayout
android:id="@+id/ll_title_zh"
android:layout_width="@dimen/st_hq_layout_width"
android:layout_height="fill_parent"
android:layout_marginLeft="@dimen/st_hq_layout_marginLeft"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:orientation="horizontal" >

<!-- 涨幅 -->

<TextView
android:id="@+id/tv_zh"
style="@style/s_horizontal_list_head_common_arrow"
android:text="@string/s_hs_zh" />

<ImageView
android:id="@+id/iv_zh_arrow"
android:layout_width="20dip"
android:layout_height="17dip"
android:layout_marginLeft="3dip"
android:contentDescription="@string/imagedescription"
/>
</LinearLayout>

<LinearLayout
android:layout_width="@dimen/st_hq_layout_width"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/st_hq_layout_marginLeft"
android:gravity="center"
android:orientation="horizontal" >

<!-- 涨跌 -->

<RadioButton
style="@style/s_horizontal_list_head_common_arrow"
android:text="@string/s_hs_zd" />

</LinearLayout>

<!-- 昨收 -->

<RadioButton
style="@style/s_horizontal_list_head_common"
android:layout_marginLeft="@dimen/st_hq_layout_marginLeft"
android:text="@string/s_hs_zs" />

<!-- 成交量 -->

<RadioButton
style="@style/s_horizontal_list_head_common"
android:layout_marginLeft="@dimen/st_hq_layout_marginLeft"
android:text="@string/s_hs_cjl" />
<!-- 成交额 -->

<RadioButton
style="@style/s_horizontal_list_head_common"
android:layout_marginLeft="@dimen/st_hq_layout_marginLeft"
android:text="@string/s_hs_cje" />
<!-- 最高 -->

<RadioButton
style="@style/s_horizontal_list_head_common"
android:layout_marginLeft="@dimen/st_hq_layout_marginLeft"
android:text="@string/s_hs_zg" />
<!-- 最低 -->

<RadioButton
style="@style/s_horizontal_list_head_common"
android:layout_marginLeft="@dimen/st_hq_layout_marginLeft"
android:text="@string/s_hs_zuidi" />
<!-- 今开 -->

<RadioButton
style="@style/s_horizontal_list_head_common"
android:layout_marginLeft="@dimen/st_hq_layout_marginLeft"
android:text="@string/s_hs_jk" />
<!-- 量比 -->

<RadioButton
style="@style/s_horizontal_list_head_common"
android:layout_marginLeft="@dimen/st_hq_layout_marginLeft"
android:text="@string/s_hs_lb" />
<!-- 振幅 -->

<RadioButton
style="@style/s_horizontal_list_head_common"
android:layout_marginLeft="@dimen/st_hq_layout_marginLeft"
android:text="@string/s_hs_zhenhu" />

<!-- 解决最后一个无法显示 -->

<RadioButton
style="@style/s_horizontal_list_head_common_last"
android:layout_marginLeft="@dimen/st_hq_layout_marginLeft" />
</LinearLayout>
</com.goodwin.finance.common.view.HScrollView>
</LinearLayout>

<com.goodwin.finance.pulltorefresh.PullToRefreshListView
android:id="@+id/ptrl_hs_list"
style="@style/s_list_view_common" />

</LinearLayout>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息