## ViewPagerIndicator ## 使用导入ViewPagerIndicator库的方式相当于可以改源码,打包编译Eclips可以自动完成。ViewPager指针项目,在使用ViewPager的时候能够指示ViewPager所在的位置,就像Google Play中切换的效果一样,还能使用在应用初始化的介绍页面1. 引入ViewPagerIndicator库 2. 编写布局文件<com.viewpagerindicator.TabPageIndicatorandroid:id="@+id/indicator"android:layout_width="fill_parent"android:layout_height="wrap_content" />3. mIndicator.setViewPager(mViewPager);//将viewpager和mIndicator关联起来,必须在viewpager设置完adapter后才能调用4. 重写PagerAdapter方法,返回页面标题/*** 重写此方法,返回页面标题,用于viewpagerIndicator的页签显示*/@Overridepublic CharSequence getPageTitle(int position) {return mNewsTabData.get(position).title;}5. 自定义样式修改 清单文件:<activityandroid:name=".MainActivity"android:theme="@style/Theme.PageIndicatorDefaults" /> 然后修改Theme.PageIndicatorDefaults这个样式文件。
package com.itheima.zhbj52.base.menudetail;import java.util.ArrayList;import android.app.Activity; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.View; import android.view.ViewGroup;import com.itheima.zhbj52.MainActivity; import com.itheima.zhbj52.R; import com.itheima.zhbj52.base.BaseMenuDetailPager; import com.itheima.zhbj52.base.TabDetailPager; import com.itheima.zhbj52.domain.NewsData.NewsTabData; import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu; import com.lidroid.xutils.ViewUtils; import com.lidroid.xutils.view.annotation.event.OnClick; import com.viewpagerindicator.TabPageIndicator;/*** 新闻中心-新闻*/ public class NewsMenuDetailPager extends BaseMenuDetailPager implements OnPageChangeListener {/*public abstract class BaseMenuDetailPager {public Activity mActivity;public View mRootView;public BaseMenuDetailPager(Activity activity) {mActivity = activity;mRootView = initViews();}public abstract View initViews();public void initData() {}}*/private ViewPager mViewPager;//11个标签页的适配器private ArrayList<TabDetailPager> mPagerList;//11个标签页private ArrayList<NewsTabData> mNewsTabData;// 页签网络数据private TabPageIndicator mIndicator;//viewpagerindicator实现的标签头public NewsMenuDetailPager(Activity activity,ArrayList<NewsTabData> children) {super(activity);mNewsTabData = children;}@Overridepublic View initViews() {View view = View.inflate(mActivity, R.layout.news_menu_detail, null);//返回给上层flContent的页面View对象。/*<?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"android:orientation="vertical" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><com.viewpagerindicator.TabPageIndicator ViewPager页标签的固定写法android:id="@+id/indicator"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1" /><ImageButton 可以切换页标签的按钮android:id="@+id/btn_next"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:background="@android:color/transparent"android:padding="5dp"android:src="@drawable/news_cate_arr" 图片/> </LinearLayout><android.support.v4.view.ViewPagerandroid:id="@+id/vp_menu_detail"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout>*/mViewPager = (ViewPager) view.findViewById(R.id.vp_menu_detail);ViewUtils.inject(this, view);mIndicator = (TabPageIndicator) view.findViewById(R.id.indicator);// mViewPager.setOnPageChangeListener(this);//注意:当viewpager和Indicator绑定时,// 滑动监听需要设置给Indicator而不是viewpager,这样滑动viewpager的时候上面的标签就能够跟着下面的viewpager一起滑动。mIndicator.setOnPageChangeListener(this);return view;}@Overridepublic void initData() {mPagerList = new ArrayList<TabDetailPager>();// 初始化页签数据for (int i = 0; i < mNewsTabData.size(); i++) {TabDetailPager pager = new TabDetailPager(mActivity,mNewsTabData.get(i));mPagerList.add(pager);}mViewPager.setAdapter(new MenuDetailAdapter());mIndicator.setViewPager(mViewPager);// 将viewpager和mIndicator关联起来,这样每个ViewPager就有标签头了,必须在viewpager设置完adapter后才能调用 }// 按钮的监听事件 @OnClick(R.id.btn_next)public void nextPage(View view) {int currentItem = mViewPager.getCurrentItem();mViewPager.setCurrentItem(++currentItem);}class MenuDetailAdapter extends PagerAdapter {//重写此方法,返回页面标题,用于viewpagerIndicator的页签显示 @Overridepublic CharSequence getPageTitle(int position) {return mNewsTabData.get(position).title;}@Overridepublic int getCount() {return mPagerList.size();}@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0 == arg1;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {TabDetailPager pager = mPagerList.get(position);//新闻的11个子页面 container.addView(pager.mRootView);pager.initData();return pager.mRootView;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView((View) object);}}@Overridepublic void onPageScrollStateChanged(int arg0) {}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {}@Overridepublic void onPageSelected(int arg0) {System.out.println("onPageSelected:" + arg0);MainActivity mainUi = (MainActivity) mActivity;SlidingMenu slidingMenu = mainUi.getSlidingMenu();if (arg0 == 0) {//只有在第一个页面(北京), 侧边栏才允许出来 slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);} else {slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_NONE);}}}
自定义ViewPager处理事件的拦截:
package com.itheima.zhbj52.view;import android.content.Context; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent;/*** 头条新闻的Viewpager*/ public class TopNewsViewPager extends ViewPager {int startX;int startY;public TopNewsViewPager(Context context, AttributeSet attrs) {super(context, attrs);}public TopNewsViewPager(Context context) {super(context);}/*** ViewPager嵌套的时候,父子的滑动事件处理:* 事件分发, 请求父控件及祖宗控件是否拦截事件,请求父控件及祖宗控件不要拦截则事件就可以传到这个控件来,dispatchTouchEvent()方法里面重写。* 1. 右划, 而且是第一个页面, 需要父控件拦截 ,此时父控件可以滑动。* 2. 左划, 而且是最后一个页面, 需要父控件拦截 ,此时父控件可以滑动。* 3. 上下滑动, 需要父控件拦截*/@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:getParent().requestDisallowInterceptTouchEvent(true);// 请求父控件不要拦截,所有的父控件都不拦截。startX = (int) ev.getRawX();startY = (int) ev.getRawY();//.getX()是获取基于父控件的位置,getRawX()是获取基于屏幕的位置。break;case MotionEvent.ACTION_MOVE:int endX = (int) ev.getRawX();int endY = (int) ev.getRawY();if (Math.abs(endX - startX) > Math.abs(endY - startY)) {// 左右滑动if (endX > startX) {// 右划if (getCurrentItem() == 0) {// 第一个页面, 需要父控件拦截getParent().requestDisallowInterceptTouchEvent(false);}} else {// 左划if (getCurrentItem() == getAdapter().getCount() - 1) {// 最后一个页面,// 需要拦截getParent().requestDisallowInterceptTouchEvent(false);}}} else {// 上下滑动getParent().requestDisallowInterceptTouchEvent(false);}break;default:break;}return super.dispatchTouchEvent(ev);} }
package com.itheima.zhbj52.base;import java.util.ArrayList;import android.app.Activity; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ImageView.ScaleType; import android.widget.TextView; import android.widget.Toast;import com.google.gson.Gson; import com.itheima.zhbj52.R; import com.itheima.zhbj52.domain.NewsData.NewsTabData; import com.itheima.zhbj52.domain.TabData; import com.itheima.zhbj52.domain.TabData.TabNewsData; import com.itheima.zhbj52.domain.TabData.TopNewsData; import com.itheima.zhbj52.global.GlobalContants; import com.itheima.zhbj52.view.RefreshListView; import com.lidroid.xutils.BitmapUtils; import com.lidroid.xutils.HttpUtils; import com.lidroid.xutils.ViewUtils; import com.lidroid.xutils.exception.HttpException; import com.lidroid.xutils.http.ResponseInfo; import com.lidroid.xutils.http.callback.RequestCallBack; import com.lidroid.xutils.http.client.HttpRequest.HttpMethod; import com.lidroid.xutils.view.annotation.ViewInject; import com.viewpagerindicator.CirclePageIndicator;/*** 新闻中心-新闻-北京 页签详情页*/ public class TabDetailPager extends BaseMenuDetailPager implements OnPageChangeListener {NewsTabData mTabData;private TextView tvText;private String mUrl;private TabData mTabDetailData;@ViewInject(R.id.vp_news)private ViewPager mViewPager;@ViewInject(R.id.tv_title)private TextView tvTitle;// 头条新闻的标题private ArrayList<TopNewsData> mTopNewsList;// 头条新闻数据集合 @ViewInject(R.id.indicator)private CirclePageIndicator mIndicator;// 头条新闻位置指示器,安卓自带的(4个黑色的指示位置的圆点,还支持点击) @ViewInject(R.id.lv_list)private RefreshListView lvList;// 新闻列表private ArrayList<TabNewsData> mNewsList; // 新闻数据集合private NewsAdapter mNewsAdapter;public TabDetailPager(Activity activity, NewsTabData newsTabData) {super(activity);mTabData = newsTabData;mUrl = GlobalContants.SERVER_URL + mTabData.url;}@Overridepublic View initViews() {View view = View.inflate(mActivity, R.layout.tab_detail_pager, null);//tab_detail_pager.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"android:orientation="vertical" ><com.itheima.zhbj52.view.RefreshListView 下拉刷新的文字和箭头部分,这也是一个ListView。android:id="@+id/lv_list"android:layout_width="match_parent"android:layout_height="0dp"android:cacheColorHint="#fff"android:layout_weight="1" ></com.itheima.zhbj52.view.RefreshListView></LinearLayout>*/// 加载头布局(图片滑动的viewPaer),整体作为一个头view加载进ListView(下面的滑动新闻列表),这样headerView就会在listView里面一起滑动。View headerView = View.inflate(mActivity, R.layout.list_header_topnews,null);//list_header_topnews.xml/*<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="wrap_content" ><com.itheima.zhbj52.view.TopNewsViewPagerandroid:id="@+id/vp_news"android:layout_width="match_parent"android:layout_height="200dp" /><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:background="#a000"android:padding="3dp" ><TextViewandroid:id="@+id/tv_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#fff"android:textSize="16sp" /> <com.viewpagerindicator.CirclePageIndicator 安卓自带的(4个黑色的指示位置的圆点,还支持点击)android:id="@+id/indicator" android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:padding="10dip"app:fillColor="#f00"app:pageColor="@android:color/darker_gray"app:radius="3dp"app:strokeWidth="0dp" /></RelativeLayout></RelativeLayout>*/ViewUtils.inject(this, view);//view里面的控件就可以支持注解了。ViewUtils.inject(this, headerView);//headerView里面的控件就可以支持注解了。// 将头条新闻以头布局的形式加给listviewlvList.addHeaderView(headerView);//后加载的HeaderView在下面。return view;}@Overridepublic void initData() {getDataFromServer();}private void getDataFromServer() {HttpUtils utils = new HttpUtils();utils.send(HttpMethod.GET, mUrl, new RequestCallBack<String>() {@Overridepublic void onSuccess(ResponseInfo<String> responseInfo) {String result = (String) responseInfo.result;System.out.println("页签详情页返回结果:" + result);parseData(result);}@Overridepublic void onFailure(HttpException error, String msg) {Toast.makeText(mActivity, msg, Toast.LENGTH_SHORT).show();error.printStackTrace();}});}protected void parseData(String result) {Gson gson = new Gson();mTabDetailData = gson.fromJson(result, TabData.class);System.out.println("页签详情解析:" + mTabDetailData);mTopNewsList = mTabDetailData.data.topnews;mNewsList = mTabDetailData.data.news;if (mTopNewsList != null) {mViewPager.setAdapter(new TopNewsAdapter());mIndicator.setViewPager(mViewPager);mIndicator.setSnap(true);// 支持快照显示mIndicator.setOnPageChangeListener(this);mIndicator.onPageSelected(0);// 让指示器重新定位到第一个点 tvTitle.setText(mTopNewsList.get(0).title);}if (mNewsList != null) {mNewsAdapter = new NewsAdapter();lvList.setAdapter(mNewsAdapter);}}/*** 头条新闻适配器,ViewPager的适配器*/class TopNewsAdapter extends PagerAdapter {private BitmapUtils utils;public TopNewsAdapter() {utils = new BitmapUtils(mActivity);utils.configDefaultLoadingImage(R.drawable.topnews_item_default);// 设置默认图片,下载图片的时候要等待,等待的时候显示这个图片。 }@Overridepublic int getCount() {return mTabDetailData.data.topnews.size();}@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0 == arg1;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {ImageView image = new ImageView(mActivity);image.setScaleType(ScaleType.FIT_XY);// 基于控件大小填充图片 TopNewsData topNewsData = mTopNewsList.get(position);utils.display(image, topNewsData.topimage);// 传递imagView对象和图片地址,从url加载图片。图片多了就会内存溢出。 container.addView(image);System.out.println("instantiateItem....." + position);return image;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView((View) object);}}/*** 新闻列表的适配器,ListView的适配器。*/class NewsAdapter extends BaseAdapter {private BitmapUtils utils;public NewsAdapter() {utils = new BitmapUtils(mActivity);utils.configDefaultLoadingImage(R.drawable.pic_item_list_default);//设置默认的图片 }@Overridepublic int getCount() {return mNewsList.size();}@Overridepublic TabNewsData getItem(int position) {return mNewsList.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if (convertView == null) {convertView = View.inflate(mActivity, R.layout.list_news_item,null);//list_news_item.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="wrap_content" android:padding="10dp"><ImageViewandroid:id="@+id/iv_pic"android:layout_width="110dp" 图片大小写死android:layout_height="70dp"android:scaleType="fitXY" 小了的话填满android:padding="1dp"android:background="@android:color/darker_gray" 背景是黑颜色,并且设置padding=1dp,这样就实现了图片周围有黑框。android:layout_alignParentLeft="true"android:layout_alignParentTop="true"android:src="@drawable/image_demo" /><TextViewandroid:id="@+id/tv_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentTop="true"android:layout_marginLeft="20dp"android:layout_toRightOf="@+id/iv_pic"android:text="新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题新闻标题"android:textColor="#000"android:maxLines="2"android:ellipsize="end" 多余文字在末尾加......android:textSize="20sp" /><TextViewandroid:id="@+id/tv_date"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@id/tv_title"android:text="2015-03-16 16:20"android:layout_alignBottom="@id/iv_pic"android:textColor="@android:color/darker_gray"android:textSize="16sp" /></RelativeLayout>*/holder = new ViewHolder();holder.ivPic = (ImageView) convertView.findViewById(R.id.iv_pic);holder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);holder.tvDate = (TextView) convertView.findViewById(R.id.tv_date);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}TabNewsData item = getItem(position);holder.tvTitle.setText(item.title);holder.tvDate.setText(item.pubdate);utils.display(holder.ivPic, item.listimage);return convertView;}}static class ViewHolder {public TextView tvTitle;public TextView tvDate;public ImageView ivPic;}@Overridepublic void onPageScrollStateChanged(int arg0) {}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {}@Overridepublic void onPageSelected(int arg0) {TopNewsData topNewsData = mTopNewsList.get(arg0);tvTitle.setText(topNewsData.title);} }
package com.itheima.zhbj52.view;import com.itheima.zhbj52.R;import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.widget.ListView;/*** 下拉刷新的ListView*/ public class RefreshListView extends ListView {private View mHeaderView;public RefreshListView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);initHeaderView();}public RefreshListView(Context context, AttributeSet attrs) {super(context, attrs);initHeaderView();}public RefreshListView(Context context) {super(context);initHeaderView();}/*** 初始化头布局*/private void initHeaderView() {mHeaderView = View.inflate(getContext(), R.layout.refresh_header, null);//refresh_header.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="wrap_content"android:orientation="horizontal" ><FrameLayout 帧布局,叠加在一起android:layout_width="wrap_content"android:layout_height="wrap_content"android:paddingLeft="10dp"android:paddingRight="10dp"android:paddingTop="10dp" ><ImageViewandroid:id="@+id/iv_arr"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:src="@drawable/common_listview_headview_red_arrow" /> 向下箭头<ProgressBar 转圈的进度条android:id="@+id/pb_progress"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:visibility="invisible" /></FrameLayout>箭头旁边的文字<LinearLayoutandroid:layout_width="wrap_content"android:layout_height="match_parent"android:layout_gravity="center"android:gravity="center"android:orientation="vertical" ><TextViewandroid:id="@+id/tv_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="下拉刷新"android:textColor="#f00"android:textSize="20sp" /><TextViewandroid:id="@+id/tv_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="2015-03-10 17:07:07"android:textColor="@android:color/darker_gray"android:textSize="16sp" /></LinearLayout></LinearLayout>*/this.addHeaderView(mHeaderView);//listView加多个HeaderView的时候,先加的在上面。 mHeaderView.measure(0, 0);int mHeaderViewHeight = mHeaderView.getMeasuredHeight();mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);//隐藏头布局 } }