## 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处理事件的拦截:
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);//隐藏头布局
}
}