## 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);//隱藏頭布局 } }
?