一. MainActivity.java
package androidthree_1509d.MyViewpager; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.view.ViewPager; import android.os.Bundle; import android.view.Window; import android.widget.RadioGroup; import java.util.ArrayList; import java.util.List; import Adapter.MyFragmentPagerAdapter; import Fragment.ShouYe_Fragment; import Fragment.Find_Fragment; import Fragment.Mine_Fragment; public class MainActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); final RadioGroup group = findViewById(R.id.groups); final ViewPager main_viewPager = findViewById(R.id.main_viewPager); //定义集合添加显示的页面数据 List<Fragment> data = new ArrayList<>(); data.add(new ShouYe_Fragment()); data.add(new Find_Fragment()); data.add(new Mine_Fragment()); //设置适配器 MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(getSupportFragmentManager(), data); main_viewPager.setAdapter(adapter); //设置viewpager的监听事件 main_viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { group.check(group.getChildAt(position).getId()); } @Override public void onPageScrollStateChanged(int state) { } }); //RadioGroup的监听事件 group.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup radioGroup, int i) { switch (i){ case R.id.radio_01: main_viewPager.setCurrentItem(0,false); break; case R.id.radio_02: main_viewPager.setCurrentItem(1,false); break; case R.id.radio_03: main_viewPager.setCurrentItem(2,false); break; default: break; } } }); } }
二. 自定义适配器类:
1. MyAdapter.java
package Adapter; import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import com.nostra13.universalimageloader.core.ImageLoader; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import Bean.NewsBean; import Util.ImageLoaderUtil; import androidthree_1509d.MyViewpager.R; public class MyAdapter extends BaseAdapter{ private Context context; private List<NewsBean.DataBean> list; public MyAdapter(Context context, List<NewsBean.DataBean> list) { this.context = context; this.list = list; } @Override public int getCount() { return list.size(); } @Override public Object getItem(int i) { return list.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int i, View view, ViewGroup viewGroup) { ViewHolder holder; if (view == null){ view = View.inflate(context,R.layout.item_layout,null); holder = new ViewHolder(); //查找控件 holder.time = view.findViewById(R.id.time); holder.text = view.findViewById(R.id.text); holder.image = view.findViewById(R.id.image); //绑定数据 view.setTag(holder); }else { //解绑 holder = (ViewHolder) view.getTag(); } //获取数据重新赋值 holder.text.setText("标题:"+list.get(i).getTitle()); //格式化时间 long createTime = list.get(i).getCreateTime(); Date date = new Date(createTime); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); String time = format.format(date); holder.time.setText("时间:"+time); ImageLoader.getInstance().displayImage(list.get(i).getImg(),holder.image, ImageLoaderUtil.getOption()); return view; } static class ViewHolder{ ImageView image; TextView text,time; } }
2. MyPagerAdapter.java
package Adapter; import android.content.Context; import android.os.Handler; import android.support.v4.view.PagerAdapter; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import com.nostra13.universalimageloader.core.ImageLoader; import java.util.List; public class MyPagerAdapter extends PagerAdapter{ private Context context; private List<String> list; public MyPagerAdapter(Context context, List<String> list) { this.context = context; this.list = list; } @Override public int getCount() { return Integer.MAX_VALUE; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public Object instantiateItem(ViewGroup container, int position) { //设置视图 ImageView view = new ImageView(context); view.setScaleType(ImageView.ScaleType.FIT_XY); //加载网络的图片 ImageLoader.getInstance().displayImage(list.get(position%list.size()),view); container.addView(view); return view; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } }
3. MyFragmentPagerAdapter.java
package Adapter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import java.util.List; public class MyFragmentPagerAdapter extends FragmentPagerAdapter{ private List<Fragment> data; public MyFragmentPagerAdapter(FragmentManager fm, List<Fragment> data) { super(fm); this.data = data; } @Override public Fragment getItem(int position) { return data.get(position); } @Override public int getCount() { return data.size(); } }
三. 自定义请求网络数据的Bean封装类
四. 自定义的Fragment类:
1. ShouYe_Fragment.java
package Fragment;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import Adapter.MyAdapter;
import Adapter.MyPagerAdapter;
import Bean.NewsBean;
import androidthree_1509d.MyViewpager.R;
import view.XListView;
public class ShouYe_Fragment extends Fragment implements XListView.IXListViewListener{
private int page = 10; //将page的值写成全局变量,url参数中page代表显示的第几页。
private List<NewsBean.DataBean> bean = new ArrayList<>();
private LinearLayout linearLayout;
private List<ImageView> images;
private ViewPager viewPager;
private MyAdapter adapter;
private XListView xListView;
private List<String> list;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if (msg.what == 0){
int currentItem = viewPager.getCurrentItem();
viewPager.setCurrentItem(currentItem+1);
//延时发送消息
handler.sendEmptyMessageDelayed(0,2888);
}
}
};
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.shouye_layout, container, false);
//查找控件
viewPager = (ViewPager) view.findViewById(R.id.viewPager);
linearLayout = (LinearLayout) view.findViewById(R.id.lineLayout);
xListView = view.findViewById(R.id.xListView);
//设置XListView的上拉刷新功能
xListView.setPullLoadEnable(true);
xListView.setPullRefreshEnable(true);
//XListView的监听事件
xListView.setXListViewListener(this);
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//定义集合,添加网络图片路径
list = new ArrayList<>();
list.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1505240546834&di=8e8e6ad014e4a7761a2a01536ed4a0be&imgtype=0&src=http%3A%2F%2Fdl.bizhi.sogou.com%2Fimages%2F2013%2F01%2F21%2F328891.jpg");
list.add("http://img17.3lian.com/d/file/201701/16/b9dafc9390b51ab2a882526b506079f3.jpg");
list.add("http://img17.3lian.com/d/file/201701/09/5a86ef93b6dff84cca985596e2c47a5f.jpg");
list.add("http://img.ivsky.com/img/bizhi/pre/201701/28/jinchen-025.jpg");
list.add("http://pic1.win4000.com/wallpaper/3/58744d39da779.jpg");
list.add("http://pic1.win4000.com/wallpaper/6/58743b760ff87.jpg");
//初始化小圆点的方法
initCircle();
//设置适配器
MyPagerAdapter adapter = new MyPagerAdapter(getActivity(), list);
viewPager.setAdapter(adapter);
//设置显示视图的位置
viewPager.setCurrentItem(list.size()%100000);
//使用handler类发送延时消息
handler.sendEmptyMessageDelayed(0,2888);
//设置viewpager的监听事件
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
//如果选中了这一页,,,当前小圆点红色,,,否则绿色
for (int i = 0; i<images.size();i++){
//首先显示的是选中的图片
if ( i == position%images.size()){
images.get(i).setImageResource(R.drawable.shape_selected);
}else {
images.get(i).setImageResource(R.drawable.shape_select_no);
}
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
//获取刷新的数据
getDataFromNet();
}
//网络获取刷新的数据
private void getDataFromNet() {
AsyncTask<Void,Void,String> task = new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... voids) {
try {
String path = "http://www.yulin520.com/a2a/impressApi/news/mergeList?pageSize=10&page="+page;
URL url = new URL(path);
//GET方式网络连接,注意HttpURLConnection请求数据,不是HttpsURLConnection类
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
//响应数据
int responseCode = connection.getResponseCode();
if (responseCode == 200){
InputStream inputStream = connection.getInputStream();
//返回数据
String json = streamToString(inputStream,"utf-8");
return json;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String result) {
//解析数据
NewsBean newsBean = new Gson().fromJson(result, NewsBean.class);
//把获取的数据添加到集合中
bean.addAll(newsBean.getData());
//设置适配器
setAdapter();
//停止刷新数据
xListView.stopRefresh();
//设置刷新的时间
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
xListView.setRefreshTime(format.format(date));
}
};
task.execute();
}
//设置适配器的方法
private void setAdapter() {
if (adapter == null){
adapter = new MyAdapter(getActivity(), bean);
xListView.setAdapter(adapter);
}else {
adapter.notifyDataSetChanged();
}
}
//下拉刷新
@Override
public void onRefresh() {
page--;
if (page>0){
//获取数据
refreshData();
}else{
Toast.makeText(getActivity(),"没有最新数据了!",Toast.LENGTH_SHORT).show();
}
}
//刷新数据的方法
private void refreshData() {
AsyncTask<Void,Void,String> task = new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... voids) {
try {
//路径
String path = "http://www.yulin520.com/a2a/impressApi/news/mergeList?pageSize=10&page="+page;
//请求网络数据
URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
//响应数据
int responseCode = connection.getResponseCode();
if (responseCode == 200){
InputStream inputStream = connection.getInputStream();
String json = streamToString(inputStream,"utf-8");
return json;
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
@Override
protected void onPostExecute(String json) {
//解析数据
NewsBean newsBean = new Gson().fromJson(json, NewsBean.class);
//把获取的数据添加到集合中
bean.addAll(newsBean.getData());
setAdapter();
//停止刷新
xListView.stopLoadMore();
//设置本次刷新的时间
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
String time = format.format(date);
xListView.setRefreshTime(time);
}
};
task.execute();
}
//上拉加载
@Override
public void onLoadMore() {
page++;
getDataFromNet(); //加载数据
}
//Json数据解析的自定义方法
private String streamToString(InputStream inputStream, String encode) {
try {
//转换流
InputStreamReader streamReader = new InputStreamReader(inputStream, encode);
//缓冲流
BufferedReader reader = new BufferedReader(streamReader);
//缓冲区
StringBuilder builder = new StringBuilder();
//读取数据
String data = null;
while ((data = reader.readLine())!=null){
builder.append(data);
}
//关流,返回数据
reader.close();
return builder.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void initCircle() {
//首先需要一个集合记录这些小圆点的图片,,,,当页面切换的时候,可以从集合中取出imageView进行显示图片的设置
images = new ArrayList<>();
//先清空移除所有的view
linearLayout.removeAllViews();
//集合数据显示对应的圆点
for (int i = 0; i< list.size(); i++){
ImageView imageView = new ImageView(getActivity());
//首先显示的是选中的图片为红色
if ( i == 0){
imageView.setImageResource(R.drawable.shape_selected);
}else {
imageView.setImageResource(R.drawable.shape_select_no);
}
//把设置的视图添加到集合中
images.add(imageView);
//加入到线性布局中显示
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
params.setMargins(5,0,5,0); //圆点之间的像素间距
linearLayout.addView(imageView,params);
}
}
}
2. Find_Fragment.java
package Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidthree_1509d.MyViewpager.R;
public class Find_Fragment extends Fragment{
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.find_layout, container, false);
return view;
}
}
3. Mine_Fragment.java
package Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidthree_1509d.MyViewpager.R;
public class Mine_Fragment extends Fragment{
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.mine_layout, container, false);
return view;
}
}
五. imageloader类的辅助工具类:
1. BaseApplication.java
package Util;
import android.app.Application;
public class BaseApplacation extends Application{
@Override
public void onCreate() {
super.onCreate();
//自定义配置ImageLoader类
ImageLoaderUtil.initConfig(this);
}
}
2. ImageLoaderUtil.java
package Util;
import android.content.Context;
import android.graphics.Bitmap;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;
import com.nostra13.universalimageloader.cache.disc.naming.HashCodeFileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.decode.BaseImageDecoder;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
import com.nostra13.universalimageloader.utils.StorageUtils;
import java.io.File;
import androidthree_1509d.MyViewpager.R;
/**
* 自定义配置Universal-Image-Loader类数据的工具类
*/
public class ImageLoaderUtil {
//配置Universal-Image-Loader类数据的方法,配置缓存到SD卡的位置
public static void initConfig(Context context) {
File cacheDir = StorageUtils.getCacheDirectory(context); //缓存文件夹路径
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.threadPoolSize(3) // default 线程池内加载的数量
.threadPriority(Thread.NORM_PRIORITY - 2) // default 设置当前线程的优先级
.tasksProcessingOrder(QueueProcessingType.FIFO) // default
.denyCacheImageMultipleSizesInMemory()
.memoryCache(new LruMemoryCache(2 * 1024 * 1024)) //可以通过自己的内存缓存实现
.memoryCacheSize(2 * 1024 * 1024) // 内存缓存的最大值
.memoryCacheSizePercentage(13) // default
.diskCache(new UnlimitedDiscCache(cacheDir)) // default 可以自定义缓存路径
.diskCacheSize(50 * 1024 * 1024) // 50 Mb sd卡(本地)缓存的最大值
.diskCacheFileCount(100) // 可以缓存的文件数量
// default为使用HASHCODE对UIL进行加密命名, 还可以用MD5(new Md5FileNameGenerator())加密
.diskCacheFileNameGenerator(new HashCodeFileNameGenerator())
.imageDownloader(new BaseImageDownloader(context)) // default
.imageDecoder(new BaseImageDecoder(true)) // default
.defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
.writeDebugLogs() // 打印debug log
.build(); //开始构建
ImageLoader.getInstance().init(config);
}
//配置图片加载失败和加载中显示的Android小机器人logo
public static DisplayImageOptions getOption() {
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.mipmap.ic_launcher) // 设置图片下载期间显示的图片
.showImageForEmptyUri(R.mipmap.ic_launcher) // 设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.mipmap.ic_launcher) // 设置图片加载或解码过程中发生错误显示的图片
.resetViewBeforeLoading(true) // default 设置图片在加载前是否重置、复位
.delayBeforeLoading(1000) // 下载前的延迟时间
.cacheInMemory(true) // default 设置下载的图片是否缓存在内存中
.cacheOnDisk(true) // default 设置下载的图片是否缓存在SD卡中
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED) // default 设置图片以如何的编码方式显示
.bitmapConfig(Bitmap.Config.RGB_565) // default 设置图片的解码类型
.build();
return options;
}
}
六. view 包下的 XListView实现类:
1. XListView.java
/** * @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 view; import androidthree_1509d.MyViewpager.R; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; 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; 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 // feature. /** * @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) { 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); //make sure "pull up" don't show a line in bottom when listview with one page setFooterDividersEnabled(false); } else { mPullLoading = false; mFooterView.show(); mFooterView.setState(XListViewFooter.STATE_NORMAL); //make sure "pull up" don't show a line in bottom when listview with one page setFooterDividersEnabled(true); // 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 if (getLastVisiblePosition() == mTotalItemCount - 1) { // invoke load more. if (mEnablePullLoad && mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA && !mPullLoading) { 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(); } }
2. XlistViewHeader.java
/**
* @file XListViewHeader.java
* @create Apr 18, 2012 5:22:27 PM
* @author Maxwin
* @description XListView's header
*/
package view;
import androidthree_1509d.MyViewpager.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
public class XListViewHeader extends LinearLayout {
private LinearLayout mContainer;
private ImageView mArrowImageView;
private ProgressBar mProgressBar;
private TextView mHintTextView;
private int mState = STATE_NORMAL;
private Animation mRotateUpAnim;
private Animation mRotateDownAnim;
private final int ROTATE_ANIM_DURATION = 180;
public final static int STATE_NORMAL = 0;
public final static int STATE_READY = 1;
public final static int STATE_REFRESHING = 2;
public XListViewHeader(Context context) {
super(context);
initView(context);
}
/**
* @param context
* @param attrs
*/
public XListViewHeader(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
private void initView(Context context) {
// 初始情况,设置下拉刷新view高度为0
LayoutParams lp = new LayoutParams(
LayoutParams.FILL_PARENT, 0);
mContainer = (LinearLayout) LayoutInflater.from(context).inflate(
R.layout.xlistview_header, null);
addView(mContainer, lp);
setGravity(Gravity.BOTTOM);
mArrowImageView = (ImageView)findViewById(R.id.xlistview_header_arrow);
mHintTextView = (TextView)findViewById(R.id.xlistview_header_hint_textview);
mProgressBar = (ProgressBar)findViewById(R.id.xlistview_header_progressbar);
mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);
mRotateUpAnim.setFillAfter(true);
mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);
mRotateDownAnim.setFillAfter(true);
}
public void setState(int state) {
if (state == mState) return ;
if (state == STATE_REFRESHING) { // 显示进度
mArrowImageView.clearAnimation();
mArrowImageView.setVisibility(View.INVISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
} else { // 显示箭头图片
mArrowImageView.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.INVISIBLE);
}
switch(state){
case STATE_NORMAL:
if (mState == STATE_READY) {
mArrowImageView.startAnimation(mRotateDownAnim);
}
if (mState == STATE_REFRESHING) {
mArrowImageView.clearAnimation();
}
mHintTextView.setText(R.string.xlistview_header_hint_normal);
break;
case STATE_READY:
if (mState != STATE_READY) {
mArrowImageView.clearAnimation();
mArrowImageView.startAnimation(mRotateUpAnim);
mHintTextView.setText(R.string.xlistview_header_hint_ready);
}
break;
case STATE_REFRESHING:
mHintTextView.setText(R.string.xlistview_header_hint_loading);
break;
default:
}
mState = state;
}
public void setVisiableHeight(int height) {
if (height < 0)
height = 0;
LayoutParams lp = (LayoutParams) mContainer
.getLayoutParams();
lp.height = height;
mContainer.setLayoutParams(lp);
}
public int getVisiableHeight() {
return mContainer.getLayoutParams().height;
}
}
3. XListViewFooter.java
/**
* @file XFooterView.java
* @create Mar 31, 2012 9:33:43 PM
* @author Maxwin
* @description XListView's footer
*/
package view;
import androidthree_1509d.MyViewpager.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
public class XListViewFooter extends LinearLayout {
public final static int STATE_NORMAL = 0;
public final static int STATE_READY = 1;
public final static int STATE_LOADING = 2;
private Context mContext;
private View mContentView;
private View mProgressBar;
private TextView mHintView;
public XListViewFooter(Context context) {
super(context);
initView(context);
}
public XListViewFooter(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public void setState(int state) {
mHintView.setVisibility(View.INVISIBLE);
mProgressBar.setVisibility(View.INVISIBLE);
mHintView.setVisibility(View.INVISIBLE);
if (state == STATE_READY) {
mHintView.setVisibility(View.VISIBLE);
mHintView.setText(R.string.xlistview_footer_hint_ready);
} else if (state == STATE_LOADING) {
mProgressBar.setVisibility(View.VISIBLE);
} else {
mHintView.setVisibility(View.VISIBLE);
mHintView.setText(R.string.xlistview_footer_hint_normal);
}
}
public void setBottomMargin(int height) {
if (height < 0) return ;
LayoutParams lp = (LayoutParams)mContentView.getLayoutParams();
lp.bottomMargin = height;
mContentView.setLayoutParams(lp);
}
public int getBottomMargin() {
LayoutParams lp = (LayoutParams)mContentView.getLayoutParams();
return lp.bottomMargin;
}
/**
* normal status
*/
public void normal() {
mHintView.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
}
/**
* loading status
*/
public void loading() {
mHintView.setVisibility(View.GONE);
mProgressBar.setVisibility(View.VISIBLE);
}
/**
* hide footer when disable pull load more
*/
public void hide() {
LayoutParams lp = (LayoutParams)mContentView.getLayoutParams();
lp.height = 0;
mContentView.setLayoutParams(lp);
}
/**
* show footer
*/
public void show() {
LayoutParams lp = (LayoutParams)mContentView.getLayoutParams();
lp.height = LayoutParams.WRAP_CONTENT;
mContentView.setLayoutParams(lp);
}
private void initView(Context context) {
mContext = context;
LinearLayout moreView = (LinearLayout)LayoutInflater.from(mContext).inflate(R.layout.xlistview_footer, null);
addView(moreView);
moreView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
mContentView = moreView.findViewById(R.id.xlistview_footer_content);
mProgressBar = moreView.findViewById(R.id.xlistview_footer_progressbar);
mHintView = (TextView)moreView.findViewById(R.id.xlistview_footer_hint_textview);
}
}
七. 自定义布局的xml文件
1. 自定义一个 color 文件夹:
color.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="@color/selected"></item>
<item android:state_checked="false" android:color="@color/defaulted"></item>
</selector>
2. 在drawable文件夹下的布局文件:
(1). background_select.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@color/back_checked"></item>
<item android:state_checked="false" android:drawable="@color/back_checked_no"></item>
</selector>
(2). button_select.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 被选中的按钮,文本显示成红色,其他显示成黑色 -->
<item android:state_checked="true" android:drawable="@color/selected"></item>
<item android:state_checked="false" android:drawable="@color/defaulted"></item>
</selector>
(3). shape_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ff0000"></solid>
<corners android:radius="6dp"></corners>
<size android:width="10dp" android:height="10dp"></size>
</shape>
(4). shape_selected_no.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#00FF00"></solid>
<corners android:radius="6dp"></corners>
<size android:width="10dp" android:height="10dp"></size>
</shape>
需在当前drawable文件夹导入xlistview使用的图片
3. layout文件夹下的布局文件:
(1). activity_main.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.support.v4.view.ViewPager
android:id="@+id/main_viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v4.view.ViewPager>
<RadioGroup
android:id="@+id/groups"
android:orientation="horizontal"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<RadioButton
android:text="首页"
android:checked="true"
style="@style/ButtonStyle"
android:layout_weight="1"
android:id="@+id/radio_01"
android:layout_width="0dp"
android:textColor="@color/color"
android:layout_height="wrap_content" />
<RadioButton
android:text="发现"
style="@style/ButtonStyle"
android:layout_weight="1"
android:id="@+id/radio_02"
android:layout_width="0dp"
android:textColor="@color/color"
android:layout_height="wrap_content" />
<RadioButton
android:text=" 我 "
style="@style/ButtonStyle"
android:layout_weight="1"
android:id="@+id/radio_03"
android:layout_width="0dp"
android:textColor="@color/color"
android:layout_height="wrap_content" />
</RadioGroup>
</RelativeLayout>
(2). item_layout.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:paddingTop="5dp" android:paddingBottom="5dp" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/image" android:layout_width="100dp" android:layout_height="100dp" android:layout_marginLeft="3dp"/> <LinearLayout android:orientation="vertical" android:layout_marginLeft="12dp" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:id="@+id/text" android:textSize="18sp" android:layout_marginTop="20dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/time" android:textSize="13sp" android:layout_marginTop="20dp" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout>
(3). shouye_layout.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">
<RelativeLayout
android:id="@+id/relative"
android:layout_height="328dp"
android:layout_width="match_parent" >
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_height="328dp"
android:layout_width="match_parent" />
<LinearLayout
android:id="@+id/lineLayout"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="28dp"
android:layout_centerHorizontal="true"
android:layout_alignBottom="@+id/viewPager"></LinearLayout>
</RelativeLayout>
<view.XListView
android:scrollbars="none"
android:id="@+id/xListView"
android:layout_below="@+id/relative"
android:layout_height="match_parent"
android:layout_width="match_parent"></view.XListView>
</RelativeLayout>
(4). find_layout.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:scaleType="fitXY" android:src="@drawable/girl" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
(5). mine_layout.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:scaleType="fitXY" android:src="@drawable/jinchen1" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
(6). xlistview_header.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="bottom" >
<RelativeLayout
android:id="@+id/xlistview_header_content"
android:layout_width="fill_parent"
android:layout_height="60dp" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:orientation="vertical" android:id="@+id/xlistview_header_text">
<TextView
android:id="@+id/xlistview_header_hint_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/xlistview_header_hint_normal" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/xlistview_header_last_time"
android:textSize="12sp" />
<TextView
android:id="@+id/xlistview_header_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
<ImageView
android:id="@+id/xlistview_header_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/xlistview_header_text"
android:layout_centerVertical="true"
android:layout_marginLeft="-35dp"
android:src="@drawable/xlistview_arrow" />
<ProgressBar
android:id="@+id/xlistview_header_progressbar"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignLeft="@id/xlistview_header_text"
android:layout_centerVertical="true"
android:layout_marginLeft="-40dp"
android:visibility="invisible" />
</RelativeLayout>
</LinearLayout>
(7). xlistview_footer.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<RelativeLayout
android:id="@+id/xlistview_footer_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dp" >
<ProgressBar
android:id="@+id/xlistview_footer_progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="invisible" />
<TextView
android:id="@+id/xlistview_footer_hint_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/xlistview_footer_hint_normal" />
</RelativeLayout>
</LinearLayout>
4. values文件夹下的布局文件:
(1). colors.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <!--字体颜色--> <color name="selected">#FF0000</color> <color name="defaulted">#000000</color> <!--背景颜色--> <color name="back_checked">#00FF7F</color> <color name="back_checked_no">#98FB98</color> </resources>
(2). strings.xml
<resources>
<string name="app_name">ViewPager+XListView+Fragment+ImageLoader</string>
<string name="xlistview_header_hint_normal">下拉刷新</string>
<string name="xlistview_header_hint_ready">松开刷新数据</string>
<string name="xlistview_header_hint_loading">正在加载...</string>
<string name="xlistview_header_last_time">上次更新时间:</string>
<string name="xlistview_footer_hint_normal">查看更多</string>
<string name="xlistview_footer_hint_ready">松开载入更多</string>
</resources>
(3). styles.xml
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="ButtonStyle"> <item name="android:button">@null</item> <item name="android:padding">10dp</item> <item name="android:gravity">center</item> <item name="android:background">@drawable/background_select</item> </style> </resources>
最后在AndroidManifest.xml中加入网络请求权限和ImageLoader类的name属性