## ViewPagerIndicator ## 使用導入ViewPagerIndicator庫的方式至關於能夠改源碼,打包編譯Eclips能夠自動完成。 ViewPager指針項目,在使用ViewPager的時候可以指示ViewPager所在的位置,就像Google Play中切換的效果同樣,還能使用在應用初始化的介紹頁面 1. 引入ViewPagerIndicator庫 2. 編寫佈局文件 <com.viewpagerindicator.TabPageIndicator android:id="@+id/indicator" android:layout_width="fill_parent" android:layout_height="wrap_content" /> 3. mIndicator.setViewPager(mViewPager);//將viewpager和mIndicator關聯起來,必須在viewpager設置完adapter後才能調用 4. 重寫PagerAdapter方法,返回頁面標題 /** * 重寫此方法,返回頁面標題,用於viewpagerIndicator的頁籤顯示 */ @Override public CharSequence getPageTitle(int position) { return mNewsTabData.get(position).title; } 5. 自定義樣式修改 清單文件: <activity android: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; } @Override public 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" > <LinearLayout android: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.ViewPager android: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; } @Override public 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的頁籤顯示 @Override public CharSequence getPageTitle(int position) { return mNewsTabData.get(position).title; } @Override public int getCount() { return mPagerList.size(); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public Object instantiateItem(ViewGroup container, int position) { TabDetailPager pager = mPagerList.get(position);//新聞的11個子頁面 container.addView(pager.mRootView); pager.initData(); return pager.mRootView; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } } @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public 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處理事件的攔截:java
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. 上下滑動, 須要父控件攔截 */ @Override public 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; } @Override public 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.TopNewsViewPager android:id="@+id/vp_news" android:layout_width="match_parent" android:layout_height="200dp" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="#a000" android:padding="3dp" > <TextView android: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裏面的控件就能夠支持註解了。 // 將頭條新聞以頭佈局的形式加給listview lvList.addHeaderView(headerView);//後加載的HeaderView在下面。 return view; } @Override public void initData() { getDataFromServer(); } private void getDataFromServer() { HttpUtils utils = new HttpUtils(); utils.send(HttpMethod.GET, mUrl, new RequestCallBack<String>() { @Override public void onSuccess(ResponseInfo<String> responseInfo) { String result = (String) responseInfo.result; System.out.println("頁籤詳情頁返回結果:" + result); parseData(result); } @Override public 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);// 設置默認圖片,下載圖片的時候要等待,等待的時候顯示這個圖片。 } @Override public int getCount() { return mTabDetailData.data.topnews.size(); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public 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; } @Override public 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);//設置默認的圖片 } @Override public int getCount() { return mNewsList.size(); } @Override public TabNewsData getItem(int position) { return mNewsList.get(position); } @Override public long getItemId(int position) { return position; } @Override public 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" > <ImageView android: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" /> <TextView android: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" /> <TextView android: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; } @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public 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" > <ImageView android: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> 箭頭旁邊的文字 <LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center" android:gravity="center" android:orientation="vertical" > <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下拉刷新" android:textColor="#f00" android:textSize="20sp" /> <TextView android: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);//隱藏頭佈局 } }