1 首先重写Viewpager,实现循环、定时滑动。
package com.example.fullviewpagerdemo;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
/**
* 全能Viewpager,自动滚动,循环滑动、分页指示器 更新数据必须调用getMyPagerAdapter,方法获取到的PagerAdapter
*
*
*
* 2014-4-24 上午9:46:00
*/
public class HeadViewPager extends ViewPager implements Runnable {
private PagerAdapter pagerAdapter;
private static final int POST_DELAYED_TIME = 1000 * 2;
// 手指是否放在上面
private boolean touching;
// 更新数据需要获得myPagerAdapter
private PagerAdapter myPagerAdapter;
public HeadViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
postDelayed(this, POST_DELAYED_TIME);
}
// 对setAdapter的数据进行包装
private class MyPagerAdapter extends PagerAdapter {
private PagerAdapter pa;
public MyPagerAdapter(PagerAdapter pa) {
this.pa = pa;
}
@Override
// 关键之一:修改Count长度
public int getCount() {
return pa.getCount() > 1 ? pa.getCount() + 2 : pa.getCount();
}
@Override
// 这里是关键之二:修改索引(如果不考虑内容问题可以全部加载进数组然后操作更简单)
public Object instantiateItem(ViewGroup container, int position) {
if (position == 0) {
return pa.instantiateItem(container, pa.getCount() - 1);
} else if (position == pa.getCount() + 1) {
return pa.instantiateItem(container, 0);
} else {
return pa.instantiateItem(container, position - 1);
}
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
pa.destroyItem(container, position, object);
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return pa.isViewFromObject(arg0, arg1);
}
}
// 包装setOnPageChangeListener的数据
private class MyOnPageChangeListener implements OnPageChangeListener {
private OnPageChangeListener listener;
// 是否已经提前触发了OnPageSelected事件
private boolean alreadyTriggerOnPageSelected;
public MyOnPageChangeListener(OnPageChangeListener listener) {
this.listener = listener;
}
@Override
// 关键之三:
public void onPageScrollStateChanged(int arg0) {
if (arg0 == SCROLL_STATE_IDLE) {
if (getCurrentItem() + 1 == 0) {
setCurrentItem(pagerAdapter.getCount() - 1, false);
} else if (getCurrentItem() + 1 == pagerAdapter.getCount() + 1) {
setCurrentItem(0, false);
}
}
listener.onPageScrollStateChanged(arg0);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
listener.onPageScrolled(arg0, arg1, arg2);
}
@Override
// 关键四:
public void onPageSelected(int arg0) {
if (arg0 == 0) {
listener.onPageSelected(pagerAdapter.getCount() - 1);
alreadyTriggerOnPageSelected = true;
} else if (arg0 == pagerAdapter.getCount() + 1) {
listener.onPageSelected(0);
alreadyTriggerOnPageSelected = true;
} else {
if (!alreadyTriggerOnPageSelected) {
listener.onPageSelected(arg0 - 1);
}
alreadyTriggerOnPageSelected = false;
}
}
}
@Override
public void setOnPageChangeListener(OnPageChangeListener listener) {
super.setOnPageChangeListener(listener == null ? null
: new MyOnPageChangeListener(listener));
}
@Override
public void setAdapter(PagerAdapter arg0) {
myPagerAdapter = arg0 == null ? null : new MyPagerAdapter(arg0);
super.setAdapter(myPagerAdapter);
if (arg0 != null && arg0.getCount() != 0) {
setCurrentItem(0, false);
}
this.pagerAdapter = arg0;
}
@Override
// 兼容PageIndicator
public PagerAdapter getAdapter() {
return pagerAdapter;
}
public PagerAdapter getMyPagerAdapter() {
return myPagerAdapter;
}
@Override
public int getCurrentItem() {
return super.getCurrentItem() - 1;
}
@Override
public void setCurrentItem(int item) {
setCurrentItem(item, true);
}
@Override
public void setCurrentItem(int item, boolean smoothScroll) {
super.setCurrentItem(item + 1, smoothScroll);
}
@Override
// 自动滚动关键
public void run() {
if (getAdapter() != null && getAdapter().getCount() > 1 && !touching) {
setCurrentItem(getCurrentItem() + 1, true);
}
postDelayed(this, POST_DELAYED_TIME);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
this.touching = true;
} else if (event.getAction() == MotionEvent.ACTION_UP
|| event.getAction() == MotionEvent.ACTION_CANCEL) {
this.touching = false;
}
return super.onTouchEvent(event);
}
}
2、分页指示器,从viewpagerindicator开源项目中拷贝出来两个文件,LinePageIndicator、PageIndicator(代码无变化)
/*
* Copyright (C) 2012 Jake Wharton
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.viewpagerindicator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.ViewConfigurationCompat;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
/**
* Draws a line for each page. The current page line is colored differently than
* the unselected page lines.
*/
public class LinePageIndicator extends View implements PageIndicator {
private static final int INVALID_POINTER = -1;
// ============================================
// ===================Config===================
// ============================================
// 线条粗细,单位dp
private static final int STROKE_WIDTH = 2;
// 线条长度,单位dp
private static final int LINE_WIDTH = 12;
// 线条间隔,单位dp
private static final int GAP_WIDTH = 4;
// 选中的时候线条颜色
private static final int SELECTED_COLOR = Color.parseColor("#FF33B5E5");
// 没有选中的时候线条颜色
private static final int UN_SELECTED_COLOR = Color.parseColor("#FFBBBBBB");
// ============================================
// =================Config End=================
// ============================================
// 没有选中的时候的画笔
private final Paint mPaintUnselected = new Paint(Paint.ANTI_ALIAS_FLAG);
// 选中的时候的画笔
private final Paint mPaintSelected = new Paint(Paint.ANTI_ALIAS_FLAG);
private ViewPager mViewPager;
private ViewPager.OnPageChangeListener mListener;
// 当前页面
private int mCurrentPage;
// 是否居中
private boolean mCentered = true;
// 线条长度,单位px
private float mLineWidth;
// 线条之间的间隔,单位px
private float mGapWidth;
private int mTouchSlop;
private float mLastMotionX = -1;
private int mActivePointerId = INVALID_POINTER;
private boolean mIsDragging;
public LinePageIndicator(Context context) {
this(context, null);
}
/**
* dp转px
*
* @param res
* android.content.res.Resources
* @param dp
* @return
*/
public static int dpToPx(Resources res, int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics());
}
public LinePageIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
if (isInEditMode())
return;
final Resources res = getResources();
mLineWidth = dpToPx(res, LINE_WIDTH);
mGapWidth = dpToPx(res, GAP_WIDTH);
setStrokeWidth(dpToPx(res, STROKE_WIDTH));
mPaintUnselected.setColor(UN_SELECTED_COLOR);
mPaintSelected.setColor(SELECTED_COLOR);
final ViewConfiguration configuration = ViewConfiguration.get(context);
mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
}
public void setCentered(boolean centered) {
mCentered = centered;
invalidate();
}
public boolean isCentered() {
return mCentered;
}
public void setUnselectedColor(int unselectedColor) {
mPaintUnselected.setColor(unselectedColor);
invalidate();
}
public int getUnselectedColor() {
return mPaintUnselected.getColor();
}
public void setSelectedColor(int selectedColor) {
mPaintSelected.setColor(selectedColor);
invalidate();
}
public int getSelectedColor() {
return mPaintSelected.getColor();
}
public void setLineWidth(float lineWidth) {
mLineWidth = lineWidth;
invalidate();
}
public float getLineWidth() {
return mLineWidth;
}
public void setStrokeWidth(float lineHeight) {
mPaintSelected.setStrokeWidth(lineHeight);
mPaintUnselected.setStrokeWidth(lineHeight);
invalidate();
}
public float getStrokeWidth() {
return mPaintSelected.getStrokeWidth();
}
public void setGapWidth(float gapWidth) {
mGapWidth = gapWidth;
invalidate();
}
public float getGapWidth() {
return mGapWidth;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mViewPager == null) {
return;
}
final int count = mViewPager.getAdapter().getCount();
if (count == 0) {
return;
}
if (mCurrentPage >= count) {
setCurrentItem(count - 1);
return;
}
final float lineWidthAndGap = mLineWidth + mGapWidth;
final float indicatorWidth = (count * lineWidthAndGap) - mGapWidth;
final float paddingTop = getPaddingTop();
final float paddingLeft = getPaddingLeft();
final float paddingRight = getPaddingRight();
float verticalOffset = paddingTop + ((getHeight() - paddingTop - getPaddingBottom()) / 2.0f);
float horizontalOffset = paddingLeft;
if (mCentered) {
horizontalOffset += ((getWidth() - paddingLeft - paddingRight) / 2.0f) - (indicatorWidth / 2.0f);
}
// Draw stroked circles
for (int i = 0; i < count; i++) {
float dx1 = horizontalOffset + (i * lineWidthAndGap);
float dx2 = dx1 + mLineWidth;
canvas.drawLine(dx1, verticalOffset, dx2, verticalOffset, (i == mCurrentPage) ? mPaintSelected : mPaintUnselected);
}
}
public boolean onTouchEvent(android.view.MotionEvent ev) {
if (super.onTouchEvent(ev)) {
return true;
}
if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) {
return false;
}
final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
switch (action) {
case MotionEvent.ACTION_DOWN:
mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
mLastMotionX = ev.getX();
break;
case MotionEvent.ACTION_MOVE: {
final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
final float x = MotionEventCompat.getX(ev, activePointerIndex);
final float deltaX = x - mLastMotionX;
if (!mIsDragging) {
if (Math.abs(deltaX) > mTouchSlop) {
mIsDragging = true;
}
}
if (mIsDragging) {
mLastMotionX = x;
if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) {
mViewPager.fakeDragBy(deltaX);
}
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (!mIsDragging) {
final int count = mViewPager.getAdapter().getCount();
final int width = getWidth();
final float halfWidth = width / 2f;
final float sixthWidth = width / 6f;
if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) {
if (action != MotionEvent.ACTION_CANCEL) {
mViewPager.setCurrentItem(mCurrentPage - 1);
}
return true;
} else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) {
if (action != MotionEvent.ACTION_CANCEL) {
mViewPager.setCurrentItem(mCurrentPage + 1);
}
return true;
}
}
mIsDragging = false;
mActivePointerId = INVALID_POINTER;
if (mViewPager.isFakeDragging())
mViewPager.endFakeDrag();
break;
case MotionEventCompat.ACTION_POINTER_DOWN: {
final int index = MotionEventCompat.getActionIndex(ev);
mLastMotionX = MotionEventCompat.getX(ev, index);
mActivePointerId = MotionEventCompat.getPointerId(ev, index);
break;
}
case MotionEventCompat.ACTION_POINTER_UP:
final int pointerIndex = MotionEventCompat.getActionIndex(ev);
final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
if (pointerId == mActivePointerId) {
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
}
mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId));
break;
}
return true;
}
@Override
public void setViewPager(ViewPager viewPager) {
if (mViewPager == viewPager) {
return;
}
if (mViewPager != null) {
// Clear us from the old pager.
mViewPager.setOnPageChangeListener(null);
}
if (viewPager.getAdapter() == null) {
throw new IllegalStateException("ViewPager does not have adapter instance.");
}
mViewPager = viewPager;
mViewPager.setOnPageChangeListener(this);
mCurrentPage = mViewPager.getCurrentItem();
invalidate();
}
@Override
public void setViewPager(ViewPager view, int initialPosition) {
setViewPager(view);
setCurrentItem(initialPosition);
}
@Override
public void setCurrentItem(int item) {
if (mViewPager == null) {
throw new IllegalStateException("ViewPager has not been bound.");
}
mViewPager.setCurrentItem(item);
mCurrentPage = item;
invalidate();
}
@Override
public void notifyDataSetChanged() {
invalidate();
}
@Override
public void onPageScrollStateChanged(int state) {
if (mListener != null) {
mListener.onPageScrollStateChanged(state);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (mListener != null) {
mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
}
}
@Override
public void onPageSelected(int position) {
mCurrentPage = position;
invalidate();
if (mListener != null) {
mListener.onPageSelected(position);
}
}
@Override
public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
mListener = listener;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}
/**
* Determines the width of this view
*
* @param measureSpec
* A measureSpec packed into an int
* @return The width of the view, honoring constraints from measureSpec
*/
private int measureWidth(int measureSpec) {
float result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if ((specMode == MeasureSpec.EXACTLY) || (mViewPager == null)) {
// We were told how big to be
result = specSize;
} else {
// Calculate the width according the views count
final int count = mViewPager.getAdapter().getCount();
result = getPaddingLeft() + getPaddingRight() + (count * mLineWidth) + ((count - 1) * mGapWidth);
// Respect AT_MOST value if that was what is called for by
// measureSpec
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return (int) Math.ceil(result);
}
/**
* Determines the height of this view
*
* @param measureSpec
* A measureSpec packed into an int
* @return The height of the view, honoring constraints from measureSpec
*/
private int measureHeight(int measureSpec) {
float result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the height
result = mPaintSelected.getStrokeWidth() + getPaddingTop() + getPaddingBottom();
// Respect AT_MOST value if that was what is called for by
// measureSpec
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return (int) Math.ceil(result);
}
@Override
public void onRestoreInstanceState(Parcelable state) {
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
mCurrentPage = savedState.currentPage;
requestLayout();
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.currentPage = mCurrentPage;
return savedState;
}
static class SavedState extends BaseSavedState {
int currentPage;
public SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
currentPage = in.readInt();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(currentPage);
}
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}
此时,完成能达到所说效果。
代码出处:http://www.cnblogs.com/moqi2013/p/3547816.html