最外层使用ViewPager,将定义的Fragment放入ViewPager中adapter为
MyFrageStatePagerAdapter:
<span style="font-size:18px;">package cn.bj.dxh.carclues.adapter;
import java.util.List;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.view.ViewGroup;
public class MyFrageStatePagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragmentList;
public MyFrageStatePagerAdapter(FragmentManager fm, List<Fragment> fragmentList) {
super(fm);
// TODO Auto-generated constructor stub
this.fragmentList = fragmentList;
}
@Override
public Fragment getItem(int arg0) {
// TODO Auto-generated method stub
return fragmentList.get(arg0);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return fragmentList.size();
}
/**
* 每次更新完成ViewPager的内容后,调用该接口,此处复写主要是为了让导航按钮上层的覆盖层能够动态的移动
*/
// @Override
// public void finishUpdate(ViewGroup container)
// {
// super.finishUpdate(container);//这句话要放在最前面,否则会报错
// //获取当前的视图是位于ViewGroup的第几个位置,用来更新对应的覆盖层所在的位置
// int currentItem=mViewPager.getCurrentItem();
// if (currentItem==currenttab)
// {
// return ;
// }
// imageMove(mViewPager.getCurrentItem());
// currenttab=mViewPager.getCurrentItem();
// }
}</span>
Fragment实例:
TestOneFragment
package cn.bj.dxh.carclues.fragment;
import java.util.ArrayList;
import java.util.List;
import cn.bj.dxh.carclues.R;
import cn.bj.dxh.carclues.activity.CalculatorActivity;
import cn.bj.dxh.carclues.activity.MapTestActivity;
import cn.bj.dxh.carclues.activity.CalculationActivity;
import cn.bj.dxh.carclues.adapter.HeaderAdapter;
import cn.bj.dxh.carclues.adapter.ImagePagerAdapter;
import cn.bj.dxh.carclues.bean.Header;
import cn.bj.dxh.carclues.controler.ServerCallBack;
import cn.bj.dxh.carclues.controler.ServerDataControler;
import cn.bj.dxh.carclues.db.DBUtil;
import cn.bj.dxh.carclues.utils.MyDialog;
import cn.bj.dxh.carclues.utils.NetUtils;
import cn.bj.dxh.carclues.utils.SharedPreferencesUtils;
import cn.bj.dxh.carclues.view.AutoScrollViewPager;
import cn.bj.dxh.carclues.view.XListView;
import cn.bj.dxh.carclues.view.XListView.IXListViewListener;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class TestOneFragment extends BaseFragment implements OnClickListener, IXListViewListener{
private String TAG = "TestOneFragment";
private Context context;
private List<String> imageIdList;
private List<Header> dataList;
private MyDialog myDialog;
private AutoScrollViewPager autoScrollviewPager;
private XListView xListView;
private HeaderAdapter headerAdpter;
private LayoutInflater layoutInflater;
/** 标志位,标志已经初始化完成。然后在我们所需要的初始化操作完成之后调用,这样的避免了未初始化完成就使用而带来的问题。*/
private boolean isPrepared;
/** 是否已被加载过一次,第二次就不再去请求数据了 */
private boolean mHasLoadedOnce;
/**分页请求数据时的当前页数**/
private int pageIndex;
/**分页数据个数**/
private int pageSiza = 10;
/**标记ViewPager的当前页浮动点*/
private LinearLayout ll_point;
/**显示ViewPager*/
private FrameLayout frameLayout;
/**浮动点集合*/
private ArrayList<ImageView> imageViews;
private ImagePagerAdapter viewPagerAdapter;
/**
* 第二个header
* */
private LinearLayout city, carModle, price, screen;
/**
* 接受消息,处理消息 ,此Handler会与当前主线程一块运行
* */
Handler MyHandler = new Handler() {
// 子类必须重写此方法,接受数据
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
viewPagerAdapter.notifyDataSetChanged();
break;
}
super.handleMessage(msg);
}
};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
context = getActivity();
Log.i(TAG, "TestOneFragment:onCreateView()");
View view = inflater.inflate(R.layout.fragment_test_one, container, false);
getView(view);
// initScrollViewPager();
initView();
initXListView();
setListener();
lazyLoad();
return view;
}
/**
* 初始化界面布局
* 为XlistView添加两个Header*/
private void initView() {
// TODO Auto-generated method stub
initHeaderOne();
MyThead myThead = new MyThead();
Thread thread = new Thread(myThead);
thread.start();
}
/**
* 模拟请求数据
* */
class MyThead implements Runnable
{
public void run()
{
System.out.println("我休息了!");
try{
Thread.sleep(5000);
imageIdList.clear();
ArrayList<String> imageIdLists = new ArrayList<String>();
imageIdLists.add("http://h.hiphotos.baidu.com/image/h%3D200/sign=89d6d10699510fb367197097e932c893/a8014c086e061d956560a8877cf40ad162d9ca6f.jpg");
imageIdLists.add("http://img2.imgtn.bdimg.com/it/u=1320686180,3651175792&fm=21&gp=0.jpg");
imageIdLists.add("http://img5.imgtn.bdimg.com/it/u=3359423044,1740868973&fm=21&gp=0.jpg");
imageIdLists.add("http://img5.imgtn.bdimg.com/it/u=3665975929,833801300&fm=21&gp=0.jpg");
imageIdList.addAll(imageIdLists);
Message message = new Message();
message.what = 1;
MyHandler.sendMessage(message);
}catch (InterruptedException e){
}
}
}
/***
* 初始化 HeadImage
*/
private void initHeaderOne() {
imageIdList = new ArrayList<String>();
imageIdList.add("http://img2.imgtn.bdimg.com/it/u=3506241565,1609808105&fm=15&gp=0.jpg");
imageIdList.add("https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=36335986,2705259205&fm=116&gp=0.jpg");
imageIdList.add("http://img3.3lian.com/2013/c2/87/d/46.jpg");
imageIdList.add("http://img.51ztzj.com/upload/image/20140213/dn201402134017_321x200.jpg");
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View headview = layoutInflater.inflate(R.layout.header_one, null);
autoScrollviewPager = (AutoScrollViewPager) headview.findViewById(R.id.scroll_view_pager);
ll_point = (LinearLayout) headview.findViewById(R.id.ll_point);
frameLayout = (FrameLayout) headview.findViewById(R.id.fl_main);
initPoint();
LayoutParams layoutParams = autoScrollviewPager.getLayoutParams();
xListView.setHeaderViewHeight(layoutParams.height);
// layoutParams.height = /*context.getResources().getDimension(R.dimen.auto_viewpage_height)*/450;
// frameLayout.setLayoutParams(layoutParams);
autoScrollviewPager.setInterval(2000);//设置自动翻滚时间
autoScrollviewPager.startAutoScroll();//启动自动翻滚
viewPagerAdapter = new ImagePagerAdapter(context, imageIdList).setInfiniteLoop(true);
autoScrollviewPager.setAdapter(viewPagerAdapter);
xListView.setViewPager(autoScrollviewPager);
draw_Point(0);// 默认首次进入
xListView.addHeaderView(headview);// 要写在setAdapter前面
initSecondHead();
}
/**
* 初始化第二个View
* */
private void initSecondHead() {
// TODO Auto-generated method stub
View viewSecond = layoutInflater.inflate(R.layout.header_second, null);
city = (LinearLayout)viewSecond.findViewById(R.id.header_second_city);
price = (LinearLayout)viewSecond.findViewById(R.id.header_second_price);
carModle = (LinearLayout)viewSecond.findViewById(R.id.header_second_car_modle);
screen = (LinearLayout)viewSecond.findViewById(R.id.header_second_screen);
xListView.addHeaderView(viewSecond);
city.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Toast.makeText(context, "city", Toast.LENGTH_SHORT).show();
}
});
carModle.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Toast.makeText(context, "carModle", Toast.LENGTH_SHORT).show();
}
});
price.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Toast.makeText(context, "price", Toast.LENGTH_SHORT).show();
}
});
screen.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Toast.makeText(context, "screen", Toast.LENGTH_SHORT).show();
}
});
}
/**
* 初始化ViewPage的标记点
* */
private void initPoint() {
imageViews = new ArrayList<ImageView>();
ImageView imageView;
for (int i = 0; i < imageIdList.size(); i++) {
imageView = new ImageView(context);
imageView.setBackgroundResource(R.drawable.dark_dot);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
layoutParams.leftMargin = 10;
layoutParams.rightMargin = 10;
ll_point.addView(imageView, layoutParams);
imageViews.add(imageView);
}
}
/***
* 更新选中点
*
* @param index
*/
private void draw_Point(int index) {
for (int i = 0; i < imageViews.size(); i++) {
imageViews.get(i).setImageResource(R.drawable.dark_dot);
}
imageViews.get(index%imageViews.size()).setImageResource(R.drawable.white_dot);
}
/**
* 初始化XlistView
* */
private void initXListView() {
// TODO Auto-generated method stub
dataList = new ArrayList<Header>();
dataList.addAll(DBUtil.getHeader(context));
headerAdpter = new HeaderAdapter(context, dataList);
xListView.setPullLoadEnable(true);// 加载更多
xListView.setPullRefreshEnable(true);
xListView.setRefreshTime(SharedPreferencesUtils.getRefreshTime(context));
xListView.setXListViewListener(TestOneFragment.this);
xListView.setAdapter(headerAdpter);
}
private void getView(View view) {
// TODO Auto-generated method stub
myDialog = new MyDialog(context);
isPrepared = true;
xListView = (XListView)view.findViewById(R.id.one_xlistview);
}
private void setListener() {
// TODO Auto-generated method stub
autoScrollviewPager.setOnPageChangeListener(new OnPageChangeListener(){
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
@Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
draw_Point(arg0);
}
});
xListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
// TODO Auto-generated method stub
Toast.makeText(context, "第" + arg2 + "行", Toast.LENGTH_SHORT).show();
}
});
}
// /**
// * AutoScrollViewPager滚动监听
// * */
// public class MyOnPageChangeListener implements OnPageChangeListener {
//
// @Override
// public void onPageSelected(int position) {
// }
//
// @Override
// public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
//
// @Override
// public void onPageScrollStateChanged(int arg0) {}
// }
/**
* 初始化自动翻滚的ViewPage
* */
// private void initScrollViewPager() {
// TODO Auto-generated method stub
// imageIdList = new ArrayList<Integer>();
// imageIdList.add(R.drawable.back_image);
// imageIdList.add(R.drawable.repassworld_image);
// imageIdList.add(R.drawable.phone_image);
// imageIdList.add(R.drawable.icon);
//
// autoScrollviewPager.setInterval(2000);//设置自动翻滚时间
// autoScrollviewPager.startAutoScroll();//启动自动翻滚
// autoScrollviewPager.setAdapter(new ImagePagerAdapter(context, imageIdList).setInfiniteLoop(true));//使用ImagePagerAdapter适配viewPager并且设置循环翻滚
// autoScrollviewPager.setOnPageChangeListener(new MyOnPageChangeListener());
// }
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
default:
break;
}
}
@Override
protected void lazyLoad() {
// TODO Auto-generated method stub
if (!isPrepared || !isVisible || mHasLoadedOnce) {
return;
}
getData(true);
}
/**
* 获取数据
* @param isShowDialog是否显示加载框
* */
private void getData(final boolean isShowDialog) {
// TODO Auto-generated method stub
if (NetUtils.isNetworkAvailable(context)) {
if(isShowDialog)
myDialog.show(true);
ServerDataControler.getCarModels("", new ServerCallBack() {
@Override
public void onSuccess(Object response) {
// TODO Auto-generated method stub
mHasLoadedOnce = true;
List<Header> headerList = new ArrayList<Header>();
List<String> list = (List<String>) response;
Header header = new Header();
Header header1 = new Header();
header.setTitle(list.get(0));
header.setContent(list.get(1));
header.setImageUrl(list.get(2));
header1.setTitle(list.get(3));
header1.setContent(list.get(4));
header1.setImageUrl(list.get(5));
// header.setTitle("我是标题1");
// header.setContent("我是内容1");
// header.setImageUrl("我是图片地址1");
// header1.setTitle("我是标题2");
// header1.setContent("我是内容2");
// header1.setImageUrl("我是图片地址2");
headerList.add(header1);
headerList.add(header);
DBUtil.addHeader(context, headerList);
dataList.clear();
dataList.addAll(DBUtil.getHeader(context));
headerAdpter.notifyDataSetChanged();
xListView.stopLoadMore();
xListView.stopRefresh();
if(isShowDialog)
myDialog.dismiss();
}
@Override
public void onFail(String response) {
// TODO Auto-generated method stub
xListView.stopLoadMore();
xListView.stopRefresh();
if(isShowDialog)
myDialog.dismiss();
}
});
} else {
xListView.stopLoadMore();
xListView.stopRefresh();
Toast.makeText(context, R.string.network_error, Toast.LENGTH_SHORT)
.show();
}
}
@Override
public void onRefresh() {
// TODO Auto-generated method stub
dataList.clear();
pageIndex = 0;
getData(false);
}
@Override
public void onLoadMore() {
// TODO Auto-generated method stub
++pageIndex;
getData(false);
}
}
initHeaderOne()和initSecondHead()方法是向XListView中添加自定义布局,headerOne是初始化ViewPager的注意initHeaderOne()方法中的xListView.setHeaderViewHeight(layoutParams.height);此方法是为了解决添加两个View在XListView手势监听的冲突问题。
fragment_test_one.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/bg_color" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<cn.bj.dxh.carclues.view.XListView
android:id="@+id/one_xlistview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@color/list_line_corlor"
android:dividerHeight="1dp"
android:headerDividersEnabled="false"/>
</LinearLayout>
</RelativeLayout>
自定义的XListView:
/**
* @file XListView.java
* @package me.maxwin.view
* @create Mar 18, 2012 6:28:41 PM
* @author Maxwin
* @description An ListView support (a) Pull down to refresh, (b) Pull up to load more.
* Implement IXListViewListener, and see stopRefresh() / stopLoadMore().
*/
package cn.bj.dxh.carclues.view;
import cn.bj.dxh.carclues.R;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.DecelerateInterpolator;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Scroller;
import android.widget.TextView;
import android.widget.Toast;
public class XListView extends ListView implements OnScrollListener {
private float mLastY = -1; // save event y
private Scroller mScroller; // used for scroll back
private OnScrollListener mScrollListener; // user's scroll listener
// the interface to trigger refresh and load more.
private IXListViewListener mListViewListener;
// -- header view
private XListViewHeader mHeaderView;
// header view content, use it to calculate the Header's height. And hide it
// when disable pull refresh.
private RelativeLayout mHeaderViewContent;
private TextView mHeaderTimeView;
private int mHeaderViewHeight; // header view's height
private boolean mEnablePullRefresh = true;
private boolean mPullRefreshing = false; // is refreashing.
// -- footer view
private XListViewFooter mFooterView;
private boolean mEnablePullLoad;
private boolean mPullLoading;
private boolean mIsFooterReady = false;
// total list items, used to detect is at the bottom of listview.
private int mTotalItemCount;
// for mScroller, scroll back from header or footer.
private int mScrollBack;
private final static int SCROLLBACK_HEADER = 0;
private final static int SCROLLBACK_FOOTER = 1;
private final static int SCROLL_DURATION = 400; // scroll back duration
private final static int PULL_LOAD_MORE_DELTA = 50; // when pull up >= 50px
// at bottom, trigger
// load more.
private final static float OFFSET_RADIO = 1.8f; // support iOS like pull
private int headerViewHeight;
private AutoScrollViewPager autoScrollviewPager;
private GestureDetector mGestureDetector;
private Context context;
public void setViewPager(AutoScrollViewPager autoScrollviewPager) {
this.autoScrollviewPager = autoScrollviewPager;
}
class YScrollDetector extends SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
if (Math.abs(distanceY) >= Math.abs(distanceX)) {
return true;
}
Log.e("jj", "左右....");
return false;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
if(e.getY() < headerViewHeight){//对比ViewPager的高度判断点击的headerView
Toast.makeText(context, "图" + autoScrollviewPager.getCurrentItem()%4, Toast.LENGTH_SHORT).show();
}
return super.onSingleTapUp(e);
}
}
/**
* ViewGroup的触摸拦截事件
* return ture事件被拦截,不下发给子View
* return false事件不被拦截,下发给子View*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
super.onInterceptTouchEvent(ev);
return mGestureDetector.onTouchEvent(ev);
}
public void setHeaderViewHeight(int headerViewHeight) {
this.headerViewHeight = headerViewHeight;
}
/**
* @param context
*/
public XListView(Context context) {
super(context);
initWithContext(context);
}
public XListView(Context context, AttributeSet attrs) {
super(context, attrs);
initWithContext(context);
}
public XListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initWithContext(context);
}
private void initWithContext(Context context) {
this.context = context;
mGestureDetector = new GestureDetector(new YScrollDetector());
mScroller = new Scroller(context, new DecelerateInterpolator());
// XListView need the scroll event, and it will dispatch the event to
// user's listener (as a proxy).
super.setOnScrollListener(this);
// init header view
mHeaderView = new XListViewHeader(context);
mHeaderViewContent = (RelativeLayout) mHeaderView
.findViewById(R.id.xlistview_header_content);
mHeaderTimeView = (TextView) mHeaderView
.findViewById(R.id.xlistview_header_time);
addHeaderView(mHeaderView);
// init footer view
mFooterView = new XListViewFooter(context);
// init header height
mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mHeaderViewHeight = mHeaderViewContent.getHeight();
getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
}
});
}
@Override
public void setAdapter(ListAdapter adapter) {
// make sure XListViewFooter is the last footer view, and only add once.
if (mIsFooterReady == false) {
mIsFooterReady = true;
addFooterView(mFooterView);
}
super.setAdapter(adapter);
}
/**
* enable or disable pull down refresh feature.
*
* @param enable
*/
public void setPullRefreshEnable(boolean enable) {
mEnablePullRefresh = enable;
if (!mEnablePullRefresh) { // disable, hide the content
mHeaderViewContent.setVisibility(View.INVISIBLE);
} else {
mHeaderViewContent.setVisibility(View.VISIBLE);
}
}
/**
* enable or disable pull up load more feature.
*
* @param enable
*/
public void setPullLoadEnable(boolean enable) {
mEnablePullLoad = enable;
if (!mEnablePullLoad) {
mFooterView.hide();
mFooterView.setOnClickListener(null);
} else {
mPullLoading = false;
mFooterView.show();
mFooterView.setState(XListViewFooter.STATE_NORMAL);
// both "pull up" and "click" will invoke load more.
mFooterView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startLoadMore();
}
});
}
}
/**
* stop refresh, reset header view.
*/
public void stopRefresh() {
// if (mPullRefreshing == true) {
mPullRefreshing = false;
resetHeaderHeight();
// }
}
/**
* stop load more, reset footer view.
*/
public void stopLoadMore() {
if (mPullLoading == true) {
mPullLoading = false;
mFooterView.setState(XListViewFooter.STATE_NORMAL);
}
}
/**
* set last refresh time
*
* @param time
*/
public void setRefreshTime(String time) {
mHeaderTimeView.setText(time);
}
private void invokeOnScrolling() {
if (mScrollListener instanceof OnXScrollListener) {
OnXScrollListener l = (OnXScrollListener) mScrollListener;
l.onXScrolling(this);
}
}
private void updateHeaderHeight(float delta) {
mHeaderView.setVisiableHeight((int) delta
+ mHeaderView.getVisiableHeight());
if (mEnablePullRefresh && !mPullRefreshing) { // 未处于刷新状态,更新箭头
if (mHeaderView.getVisiableHeight() > mHeaderViewHeight) {
mHeaderView.setState(XListViewHeader.STATE_READY);
} else {
mHeaderView.setState(XListViewHeader.STATE_NORMAL);
}
}
setSelection(0); // scroll to top each time
}
/**
* reset header view's height.
*/
private void resetHeaderHeight() {
int height = mHeaderView.getVisiableHeight();
if (height == 0) // not visible.
return;
// refreshing and header isn't shown fully. do nothing.
if (mPullRefreshing && height <= mHeaderViewHeight) {
return;
}
int finalHeight = 0; // default: scroll back to dismiss header.
// is refreshing, just scroll back to show all the header.
if (mPullRefreshing && height > mHeaderViewHeight) {
finalHeight = mHeaderViewHeight;
}
mScrollBack = SCROLLBACK_HEADER;
mScroller.startScroll(0, height, 0, finalHeight - height,
SCROLL_DURATION);
// trigger computeScroll
invalidate();
}
private void updateFooterHeight(float delta) {
int height = mFooterView.getBottomMargin() + (int) delta;
if (mEnablePullLoad && !mPullLoading) {
if (height > PULL_LOAD_MORE_DELTA) { // height enough to invoke load
// more.
mFooterView.setState(XListViewFooter.STATE_READY);
} else {
mFooterView.setState(XListViewFooter.STATE_NORMAL);
}
}
mFooterView.setBottomMargin(height);
// setSelection(mTotalItemCount - 1); // scroll to bottom
}
private void resetFooterHeight() {
int bottomMargin = mFooterView.getBottomMargin();
if (bottomMargin > 0) {
mScrollBack = SCROLLBACK_FOOTER;
mScroller.startScroll(0, bottomMargin, 0, -bottomMargin,
SCROLL_DURATION);
invalidate();
}
}
private void startLoadMore() {
mPullLoading = true;
mFooterView.setState(XListViewFooter.STATE_LOADING);
if (mListViewListener != null) {
mListViewListener.onLoadMore();
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (mLastY == -1) {
mLastY = ev.getRawY();
}
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastY = ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
final float deltaY = ev.getRawY() - mLastY;
mLastY = ev.getRawY();
if (getFirstVisiblePosition() == 0
&& (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) {
// the first item is showing, header has shown or pull down.
updateHeaderHeight(deltaY / OFFSET_RADIO);
invokeOnScrolling();
} else if (getLastVisiblePosition() == mTotalItemCount - 1
&& (mFooterView.getBottomMargin() > 0 || deltaY < 0)) {
// last item, already pulled up or want to pull up.
updateFooterHeight(-deltaY / OFFSET_RADIO);
}
break;
default:
mLastY = -1; // reset
// if (getFirstVisiblePosition() == 0) {
// invoke refresh
if (mEnablePullRefresh
&& mHeaderView.getVisiableHeight() > mHeaderViewHeight) {
mPullRefreshing = true;
mHeaderView.setState(XListViewHeader.STATE_REFRESHING);
if (mListViewListener != null) {
mListViewListener.onRefresh();
}
resetHeaderHeight();
}else{
stopRefresh();
}
// } else
if (getLastVisiblePosition() == mTotalItemCount - 1) {
// invoke load more.
if (mEnablePullLoad
&& mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA) {
startLoadMore();
}
resetFooterHeight();
}
break;
}
return super.onTouchEvent(ev);
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
if (mScrollBack == SCROLLBACK_HEADER) {
mHeaderView.setVisiableHeight(mScroller.getCurrY());
} else {
mFooterView.setBottomMargin(mScroller.getCurrY());
}
postInvalidate();
invokeOnScrolling();
}
super.computeScroll();
}
@Override
public void setOnScrollListener(OnScrollListener l) {
mScrollListener = l;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (mScrollListener != null) {
mScrollListener.onScrollStateChanged(view, scrollState);
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// send to user's listener
mTotalItemCount = totalItemCount;
if (mScrollListener != null) {
mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount,
totalItemCount);
}
}
public void setXListViewListener(IXListViewListener l) {
mListViewListener = l;
}
/**
* you can listen ListView.OnScrollListener or this one. it will invoke
* onXScrolling when header/footer scroll back.
*/
public interface OnXScrollListener extends OnScrollListener {
public void onXScrolling(View view);
}
/**
* implements this interface to get refresh/load more event.
*/
public interface IXListViewListener {
public void onRefresh();
public void onLoadMore();
}
}
其中YScrollDetector为内部类,起作用是监听手势,onScroll为滑动监听,当上下滑动时返回true使onInterceptTouchEvent拦截事件返回true拦截滑动事件,不下发给子View。左右滑动返回false使
onInterceptTouchEvent拦截事件返回false不拦截滑动事件,下发给子View使其做出反应。
自定义的AutoScrollViewPager:
package cn.bj.dxh.carclues.view;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewParent;
import android.view.animation.Interpolator;
/**
* Auto Scroll View Pager
* <ul>
* <strong>Basic Setting and Usage</strong>
* <li>{@link #startAutoScroll()} start auto scroll, or {@link #startAutoScroll(int)} start auto scroll delayed</li>
* <li>{@link #stopAutoScroll()} stop auto scroll</li>
* <li>{@link #setInterval(long)} set auto scroll time in milliseconds, default is {@link #DEFAULT_INTERVAL}</li>
* </ul>
* <ul>
* <strong>Advanced Settings and Usage</strong>
* <li>{@link #setDirection(int)} set auto scroll direction</li>
* <li>{@link #setCycle(boolean)} set whether automatic cycle when auto scroll reaching the last or first item, default
* is true</li>
* <li>{@link #setSlideBorderMode(int)} set how to process when sliding at the last or first item</li>
* <li>{@link #setStopScrollWhenTouch(boolean)} set whether stop auto scroll when touching, default is true</li>
* </ul>
*
* @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2013-12-30
*/
public class AutoScrollViewPager extends ViewPager {
public static final int DEFAULT_INTERVAL = 1500;
public static final int LEFT = 0;
public static final int RIGHT = 1;
/** do nothing when sliding at the last or first item **/
public static final int SLIDE_BORDER_MODE_NONE = 0;
/** cycle when sliding at the last or first item **/
public static final int SLIDE_BORDER_MODE_CYCLE = 1;
/** deliver event to parent when sliding at the last or first item **/
public static final int SLIDE_BORDER_MODE_TO_PARENT = 2;
/** auto scroll time in milliseconds, default is {@link #DEFAULT_INTERVAL} **/
private long interval = DEFAULT_INTERVAL;
/** auto scroll direction, default is {@link #RIGHT} **/
private int direction = RIGHT;
/** whether automatic cycle when auto scroll reaching the last or first item, default is true **/
private boolean isCycle = true;
/** whether stop auto scroll when touching, default is true **/
private boolean stopScrollWhenTouch = true;
/** how to process when sliding at the last or first item, default is {@link #SLIDE_BORDER_MODE_NONE} **/
private int slideBorderMode = SLIDE_BORDER_MODE_NONE;
/** whether animating when auto scroll at the last or first item **/
private boolean isBorderAnimation = true;
/** scroll factor for auto scroll animation, default is 1.0 **/
private double autoScrollFactor = 1.0;
/** scroll factor for swipe scroll animation, default is 1.0 **/
private double swipeScrollFactor = 1.0;
private Handler handler;
private boolean isAutoScroll = false;
private boolean isStopByTouch = false;
private float touchX = 0f, downX = 0f;
private CustomDurationScroller scroller = null;
public static final int SCROLL_WHAT = 0;
// private float startX, endX;
/** 触摸时按下的点 **/
PointF downP = new PointF();
/** 触摸时当前的点 **/
PointF curP = new PointF();
@Override
public boolean onTouchEvent(MotionEvent arg0) {
//每次进行onTouch事件都记录当前的按下的坐标
curP.x = arg0.getX();
curP.y = arg0.getY();
if(arg0.getAction() == MotionEvent.ACTION_DOWN){
downP.x = arg0.getX();
downP.y = arg0.getY();
}
if(arg0.getAction() == MotionEvent.ACTION_MOVE){
float dx = Math.abs(arg0.getX()-downP.x);
float dy = Math.abs(arg0.getY()-downP.y);
getParent().requestDisallowInterceptTouchEvent(true);
if (dy<dx)
{
//此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰
getParent().requestDisallowInterceptTouchEvent(true);
}
else
{
getParent().requestDisallowInterceptTouchEvent(false);
}
}
if(arg0.getAction() == MotionEvent.ACTION_UP){
getParent().requestDisallowInterceptTouchEvent(false);
}
return super.onTouchEvent(arg0);
}
public AutoScrollViewPager(Context paramContext) {
super(paramContext);
init();
}
public AutoScrollViewPager(Context paramContext, AttributeSet paramAttributeSet) {
super(paramContext, paramAttributeSet);
init();
}
private void init() {
handler = new MyHandler(this);
setViewPagerScroller();
}
/**
* start auto scroll, first scroll delay time is {@link #getInterval()}
*/
public void startAutoScroll() {
isAutoScroll = true;
sendScrollMessage((long)(interval + scroller.getDuration() / autoScrollFactor * swipeScrollFactor));
}
/**
* start auto scroll
*
* @param delayTimeInMills first scroll delay time
*/
public void startAutoScroll(int delayTimeInMills) {
isAutoScroll = true;
sendScrollMessage(delayTimeInMills);
}
/**
* stop auto scroll
*/
public void stopAutoScroll() {
isAutoScroll = false;
handler.removeMessages(SCROLL_WHAT);
}
/**
* set the factor by which the duration of sliding animation will change while swiping
*/
public void setSwipeScrollDurationFactor(double scrollFactor) {
swipeScrollFactor = scrollFactor;
}
/**
* set the factor by which the duration of sliding animation will change while auto scrolling
*/
public void setAutoScrollDurationFactor(double scrollFactor) {
autoScrollFactor = scrollFactor;
}
private void sendScrollMessage(long delayTimeInMills) {
/** remove messages before, keeps one message is running at most **/
handler.removeMessages(SCROLL_WHAT);
handler.sendEmptyMessageDelayed(SCROLL_WHAT, delayTimeInMills);
}
/**
* set ViewPager scroller to change animation duration when sliding
*/
private void setViewPagerScroller() {
try {
Field scrollerField = ViewPager.class.getDeclaredField("mScroller");
scrollerField.setAccessible(true);
Field interpolatorField = ViewPager.class.getDeclaredField("sInterpolator");
interpolatorField.setAccessible(true);
scroller = new CustomDurationScroller(getContext(), (Interpolator)interpolatorField.get(null));
scrollerField.set(this, scroller);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* scroll only once
*/
public void scrollOnce() {
PagerAdapter adapter = getAdapter();
int currentItem = getCurrentItem();
int totalCount;
if (adapter == null || (totalCount = adapter.getCount()) <= 1) {
return;
}
int nextItem = (direction == LEFT) ? --currentItem : ++currentItem;
if (nextItem < 0) {
if (isCycle) {
setCurrentItem(totalCount - 1, isBorderAnimation);
}
} else if (nextItem == totalCount) {
if (isCycle) {
setCurrentItem(0, isBorderAnimation);
}
} else {
setCurrentItem(nextItem, true);
}
}
/**
* <ul>
* if stopScrollWhenTouch is true
* <li>if event is down, stop auto scroll.</li>
* <li>if event is up, start auto scroll again.</li>
* </ul>
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int action = MotionEventCompat.getActionMasked(ev);
if (stopScrollWhenTouch) {
if ((action == MotionEvent.ACTION_DOWN) && isAutoScroll) {
isStopByTouch = true;
stopAutoScroll();
} else if (ev.getAction() == MotionEvent.ACTION_UP && isStopByTouch) {
startAutoScroll();
}
}
if (slideBorderMode == SLIDE_BORDER_MODE_TO_PARENT || slideBorderMode == SLIDE_BORDER_MODE_CYCLE) {
touchX = ev.getX();
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
downX = touchX;
}
int currentItem = getCurrentItem();
PagerAdapter adapter = getAdapter();
int pageCount = adapter == null ? 0 : adapter.getCount();
/**
* current index is first one and slide to right or current index is last one and slide to left.<br/>
* if slide border mode is to parent, then requestDisallowInterceptTouchEvent false.<br/>
* else scroll to last one when current item is first one, scroll to first one when current item is last
* one.
*/
if ((currentItem == 0 && downX <= touchX) || (currentItem == pageCount - 1 && downX >= touchX)) {
if (slideBorderMode == SLIDE_BORDER_MODE_TO_PARENT) {
getParent().requestDisallowInterceptTouchEvent(false);
} else {
if (pageCount > 1) {
setCurrentItem(pageCount - currentItem - 1, isBorderAnimation);
}
getParent().requestDisallowInterceptTouchEvent(true);
}
return super.dispatchTouchEvent(ev);
}
}
// switch(action){
// case MotionEvent.ACTION_DOWN:
// startX = ev.getX();
// break;
// case MotionEvent.ACTION_CANCEL:
// endX = ev.getX();
// if(Math.abs(endX-startX)>50)
// getParent().requestDisallowInterceptTouchEvent(true);
// break;
// }
// getParent().requestDisallowInterceptTouchEvent(true);
return super.dispatchTouchEvent(ev);
}
private static class MyHandler extends Handler {
private final WeakReference<AutoScrollViewPager> autoScrollViewPager;
public MyHandler(AutoScrollViewPager autoScrollViewPager) {
this.autoScrollViewPager = new WeakReference<AutoScrollViewPager>(autoScrollViewPager);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case SCROLL_WHAT:
AutoScrollViewPager pager = this.autoScrollViewPager.get();
if (pager != null) {
pager.scroller.setScrollDurationFactor(pager.autoScrollFactor);
pager.scrollOnce();
pager.scroller.setScrollDurationFactor(pager.swipeScrollFactor);
pager.sendScrollMessage(pager.interval + pager.scroller.getDuration());
}
default:
break;
}
}
}
/**
* get auto scroll time in milliseconds, default is {@link #DEFAULT_INTERVAL}
*
* @return the interval
*/
public long getInterval() {
return interval;
}
/**
* set auto scroll time in milliseconds, default is {@link #DEFAULT_INTERVAL}
*
* @param interval the interval to set
*/
public void setInterval(long interval) {
this.interval = interval;
}
/**
* get auto scroll direction
*
* @return {@link #LEFT} or {@link #RIGHT}, default is {@link #RIGHT}
*/
public int getDirection() {
return (direction == LEFT) ? LEFT : RIGHT;
}
/**
* set auto scroll direction
*
* @param direction {@link #LEFT} or {@link #RIGHT}, default is {@link #RIGHT}
*/
public void setDirection(int direction) {
this.direction = direction;
}
/**
* whether automatic cycle when auto scroll reaching the last or first item, default is true
*
* @return the isCycle
*/
public boolean isCycle() {
return isCycle;
}
/**
* set whether automatic cycle when auto scroll reaching the last or first item, default is true
*
* @param isCycle the isCycle to set
*/
public void setCycle(boolean isCycle) {
this.isCycle = isCycle;
}
/**
* whether stop auto scroll when touching, default is true
*
* @return the stopScrollWhenTouch
*/
public boolean isStopScrollWhenTouch() {
return stopScrollWhenTouch;
}
/**
* set whether stop auto scroll when touching, default is true
*
* @param stopScrollWhenTouch
*/
public void setStopScrollWhenTouch(boolean stopScrollWhenTouch) {
this.stopScrollWhenTouch = stopScrollWhenTouch;
}
/**
* get how to process when sliding at the last or first item
*
* @return the slideBorderMode {@link #SLIDE_BORDER_MODE_NONE}, {@link #SLIDE_BORDER_MODE_TO_PARENT},
* {@link #SLIDE_BORDER_MODE_CYCLE}, default is {@link #SLIDE_BORDER_MODE_NONE}
*/
public int getSlideBorderMode() {
return slideBorderMode;
}
/**
* set how to process when sliding at the last or first item
*
* @param slideBorderMode {@link #SLIDE_BORDER_MODE_NONE}, {@link #SLIDE_BORDER_MODE_TO_PARENT},
* {@link #SLIDE_BORDER_MODE_CYCLE}, default is {@link #SLIDE_BORDER_MODE_NONE}
*/
public void setSlideBorderMode(int slideBorderMode) {
this.slideBorderMode = slideBorderMode;
}
/**
* whether animating when auto scroll at the last or first item, default is true
*
* @return
*/
public boolean isBorderAnimation() {
return isBorderAnimation;
}
/**
* set whether animating when auto scroll at the last or first item, default is true
*
* @param isBorderAnimation
*/
public void setBorderAnimation(boolean isBorderAnimation) {
this.isBorderAnimation = isBorderAnimation;
}
}
此方法中的onTouchEvent作用:当是左右滑动时XListView将滑动事件下发给AutoScrollViewPager,通过getParent().requestDisallowInterceptTouchEvent(true);是ziView
通知他的父XListView现在进行的是本控件的操作,让父类不要对他的操作进行干扰。
CustomDurationScroller
package cn.bj.dxh.carclues.view;
import android.content.Context;
import android.view.animation.Interpolator;
import android.widget.Scroller;
/**
* CustomDurationScroller
*
*/
public class CustomDurationScroller extends Scroller {
private double scrollFactor = 1;
public CustomDurationScroller(Context context) {
super(context);
}
public CustomDurationScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}
/**
* not exist in android 2.3
*
* @param context
* @param interpolator
* @param flywheel
*/
// @SuppressLint("NewApi")
// public CustomDurationScroller(Context context, Interpolator interpolator, boolean flywheel){
// super(context, interpolator, flywheel);
// }
/**
* Set the factor by which the duration will change
*/
public void setScrollDurationFactor(double scrollFactor) {
this.scrollFactor = scrollFactor;
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, (int)(duration * scrollFactor));
}
}
ImagePagerAdapter:
/*
* Copyright 2014 trinea.cn All right reserved. This software is the confidential and proprietary information of
* trinea.cn ("Confidential Information"). You shall not disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into with trinea.cn.
*/
package cn.bj.dxh.carclues.adapter;
import java.util.List;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import cn.bj.dxh.carclues.R;
import cn.bj.dxh.carclues.utils.ImageUtil;
import android.content.Context;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;
import android.graphics.Bitmap;
/**
* ImagePagerAdapter
*
* @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2014-2-23
*/
public class ImagePagerAdapter extends RecyclingPagerAdapter {
private Context context;
private List<String> imageIdList;
private int size;
private boolean isInfiniteLoop;
private DisplayImageOptions options;
public ImagePagerAdapter(Context context, List<String> imageIdList) {
this.context = context;
this.imageIdList = imageIdList;
this.size = imageIdList.size();
isInfiniteLoop = false;
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.load_image)
.showImageForEmptyUri(R.drawable.load_image)
.showImageOnFail(R.drawable.load_image).cacheInMemory(true)
.cacheOnDisk(true).considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565).build();
}
@Override
public int getCount() {
// Infinite loop
return isInfiniteLoop ? Integer.MAX_VALUE : imageIdList.size();
}
/**
* get really position
*
* @param position
* @return
*/
private int getPosition(int position) {
return isInfiniteLoop ? position % size : position;
}
@Override
public View getView(final int position, View view, ViewGroup container) {
ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = holder.imageView = new ImageView(context);
view.setTag(holder);
} else {
holder = (ViewHolder)view.getTag();
}
// holder.imageView.setImageResource(imageIdList.get(getPosition(position)));
loadImage(imageIdList.get(position%(imageIdList.size())), holder.imageView);
// holder.imageView.setOnClickListener(new OnClickListener() {
//
// @Override
// public void onClick(View arg0) {
// // TODO Auto-generated method stub
// Toast.makeText(context, "ImagePagerAdapter图" + position, Toast.LENGTH_SHORT).show();
// }
// });
return view;
}
// @Override
// public Object instantiateItem(View container, int position) {
// View view = imageViews.get(position);
// view.setOnClickListener(new OnClickListener() {
//
// @Override
// public void onClick(View v) {
// // TODO Auto-generated method stub
// Log.e("xl", "xl:arrive here.");
// }
// });
// ViewPager viewPager = (ViewPager) container;
// viewPager.addView(view);
// return imageViews.get(position);
//
// }
/**
* 加载图片
* */
private void loadImage(String url, ImageView imageView){
ImageLoader.getInstance().displayImage(
url,
imageView, options,
new SimpleImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
// holder.progressBar.setVisibility(View.VISIBLE);
// holder.progressBar.setProgress(0);
}
@Override
public void onLoadingFailed(String imageUri, View view,
FailReason failReason) {
// holder.progressBar.setVisibility(View.GONE);
}
@Override
public void onLoadingComplete(String imageUri,
View view, Bitmap loadedImage) {
// holder.progressBar.setVisibility(View.GONE);
}
}, new ImageLoadingProgressListener() {
@Override
public void onProgressUpdate(String imageUri,
View view, int current, int total) {
// holder.progressBar.setProgress(Math.round(100.0f
// * current / total));
}
});
}
private static class ViewHolder {
ImageView imageView;
}
/**
* @return the isInfiniteLoop
*/
public boolean isInfiniteLoop() {
return isInfiniteLoop;
}
/**
* @param isInfiniteLoop the isInfiniteLoop to set
*/
public ImagePagerAdapter setInfiniteLoop(boolean isInfiniteLoop) {
this.isInfiniteLoop = isInfiniteLoop;
return this;
}
}
没有在ImagePagerAdapter中对AutoScrollViewPager子项进行监听,是会使AutoScrollViewPager和外层的ViewPager冲突。