-
项目需要做一个得到APP好友邀请的效果,先上咱们做的效果,如果是你需要请往下看
- 就这样的效果,原理是viewpager添加5个fragment,左边显示的其实是第三个,第四个显示的是第一个,原理网上很多,没有用viewpager返回数量无限大的那种,那种耗费内存。直接上代码吧
- activity ,新建fragment就不说了,非常简单
public class TestViewPagerActivity extends BasesActivity {
private ViewPager viewpager;
private List<Fragment> list;
private boolean mIsChanged = false;
private int mCurrentPagePosition = FIRST_ITEM_INDEX;
private static final int POINT_LENGTH = 3;
private static final int FIRST_ITEM_INDEX = 1;
private PointIndicator point_indicater;
@Override
public void initView() {
AppTitleView appTitleView = getTitleView();
appTitleView.initViewsVisible(true, true, false, false);
appTitleView.setOnLeftButtonClickListener(this);
appTitleView.setAppTitle("测试");
viewpager = findViewById(R.id.viewpager);
point_indicater = findViewById(R.id.point_indicater);
}
@Override
public boolean isShowTitle() {
return true;
}
@Override
public void initData() {
list = new ArrayList<>();
list.add(new InviteThirdFragment());
list.add(new InviteFirstFragment());
list.add(new InviteSecondFragment());
list.add(new InviteThirdFragment());
list.add(new InviteFirstFragment());
viewpager.setAdapter(new InviteFragmentAdapter(getSupportFragmentManager(), list));
viewpager.setCurrentItem(1, false);
viewpager.setOffscreenPageLimit(4);//记数从0开始!!! 设置预加载的个数
viewpager.setPageTransformer(false, new DepthPageTransformer());
viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int pPosition) {
mIsChanged = true;
if (pPosition > POINT_LENGTH) {// 末位之后,跳转到首位(1)
mCurrentPagePosition = FIRST_ITEM_INDEX;
} else if (pPosition < FIRST_ITEM_INDEX) {// 首位之前,跳转到末尾(N)
mCurrentPagePosition = POINT_LENGTH;
} else {
mCurrentPagePosition = pPosition;
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int pState) {
if (ViewPager.SCROLL_STATE_IDLE == pState) {
if (mIsChanged) {
mIsChanged = false;
viewpager.setCurrentItem(mCurrentPagePosition, false);
}
}
}
});
point_indicater.bindViewPager(viewpager);
}
@Override
public int setViewLayout() {
return R.layout.activity_testviewpager;
}
@Override
public void onLeftButtonClick(View v) {
finish();
}
}
- 布局
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:clipChildren="false"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_gravity="center"
android:layout_marginLeft="40dp"
android:layout_marginTop="30dp"
android:layout_marginRight="40dp"
android:clipChildren="false"
android:overScrollMode="never" />
<club.modernedu.lovebook.widget.indicator.PointIndicator
android:id="@+id/point_indicater"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
app:normal_color="#ffcccccc"
app:point_size="8dp"
app:point_space="10dp"
app:select_color="#fffdd63b"/>
</LinearLayout>
- adapter
public class InviteFragmentAdapter extends FragmentPagerAdapter {
private List<Fragment> list;
public InviteFragmentAdapter(FragmentManager fm, List<Fragment> list) {
super(fm);
this.list = list;
}
@Override
public Fragment getItem(int arg0) {
// TODO Auto-generated method stub
return list.get(arg0);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
}
- 中间缩放的viewpager的方法
public class DepthPageTransformer implements ViewPager.PageTransformer {
// private static final float MIN_SCALE = 0.70f;
// private static final float MIN_ALPHA = 0.5f;
//
// @Override
// public void transformPage(View page, float position) {
// if (position < -1 || position > 1) {
// page.setAlpha(MIN_ALPHA);
// page.setScaleX(MIN_SCALE);
// page.setScaleY(MIN_SCALE);
// } else if (position <= 1) { // [-1,1]
// float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
// if (position < 0) {
// float scaleX = 1 + 0.1f * position;
// page.setScaleX(scaleX);
// page.setScaleY(scaleX);
// } else {
// float scaleX = 1 - 0.1f * position;
// page.setScaleX(scaleX);
// page.setScaleY(scaleX);
// }
// page.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA));
// }
// }
private static final float MIN_SCALE = 0.9f;
@Override
public void transformPage(View view, float position) {
/**
* 过滤那些 <-1 或 >1 的值,使它区于【-1,1】之间
*/
if (position < -1) {
position = -1;
} else if (position > 1) {
position = 1;
}
/**
* 判断是前一页 1 + position ,右滑 pos -> -1 变 0
* 判断是后一页 1 - position ,左滑 pos -> 1 变 0
*/
float tempScale = position < 0 ? 1 + position : 1 - position; // [0,1]
float scaleValue = MIN_SCALE + tempScale * 0.1f; // [0,1]
view.setScaleX(scaleValue);
view.setScaleY(scaleValue);
}
}
- 自定义指示器PointIndicator
/**
* 圆点指示器
*/
public class PointIndicator extends View implements OnPageScrollListener {
private Context mContext;
private int mNormalColor;
private int mSelectColor;
private int mPointSize;
private int mPointSpace;
private Paint mNormalPaint;
private Paint mSelectPaint;
private int mCount;
private int enterPosition;
private int leavePosition;
private float percent;
public PointIndicator(Context context) {
this(context, null);
}
public PointIndicator(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PointIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttrs(context, attrs);
initPaint();
}
private void initPaint() {
mNormalPaint = new Paint();
mNormalPaint.setColor(mNormalColor);
mNormalPaint.setAntiAlias(true);
mSelectPaint = new Paint();
mSelectPaint.setColor(mSelectColor);
mSelectPaint.setAntiAlias(true);
mCount = 3;
}
private void initAttrs(Context context, AttributeSet attrs) {
mContext = context;
mNormalColor = 0x66cccccc;
mSelectColor = 0xfffdd63b;
mPointSize = dp2px(3f);
mPointSpace = dp2px(3f);
// 自定义属性
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PointIndicator);
mNormalColor = ta.getColor(R.styleable.PointIndicator_normal_color, mNormalColor);
mSelectColor = ta.getColor(R.styleable.PointIndicator_select_color, mSelectColor);
mPointSize = (int) ta.getDimension(R.styleable.PointIndicator_point_size, mPointSize);
mPointSpace = (int) ta.getDimension(R.styleable.PointIndicator_point_space, mPointSpace);
ta.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}
private int measureWidth(int measureSpec) {
int size = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.EXACTLY:
size = specSize;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.UNSPECIFIED:
size = mCount * mPointSize + (mCount - 1) * mPointSpace;
break;
}
return size;
}
private int measureHeight(int measureSpec) {
int size = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.EXACTLY:
size = specSize;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.UNSPECIFIED:
size = mPointSize;
break;
}
return size;
}
@Override
protected void onDraw(Canvas canvas) {
// 绘制normalPoint
drawNormalPoint(canvas);
// 绘制selectPoint
drawSelectPoint(canvas);
}
private void drawSelectPoint(Canvas canvas) {
float cx;
if (enterPosition > leavePosition) {
cx = (leavePosition + 0.5f) * mPointSize
+ leavePosition * mPointSpace
+ (mPointSize + mPointSpace) * percent;
} else {
cx = (leavePosition + 0.5f) * mPointSize
+ leavePosition * mPointSpace
- (mPointSize + mPointSpace) * percent;
}
float cy = getHeight() / 2;
float radius = mPointSize / 2f;
canvas.drawCircle(cx, cy, radius, mSelectPaint);
}
private void drawNormalPoint(Canvas canvas) {
for (int i = 0; i < mCount; i++) {
float cx = mPointSize / 2f + (mPointSize + mPointSpace) * i;
float cy = getHeight() / 2;
float radius = mPointSize / 2f;
canvas.drawCircle(cx, cy, radius, mNormalPaint);
}
}
public void bindViewPager(ViewPager viewPager) {
if (viewPager != null) {
if (viewPager.getAdapter() != null) {
mCount = viewPager.getAdapter().getCount()-2;
new ViewPagerHelper().bindScrollListener(viewPager, this);
requestLayout(); // 绑定ViewPager后指示器重新布局,因为指示器的数量和宽度可能有变化
}
}
}
@Override
public void onPageScroll(int enterPosition, int leavePosition, float percent) {
this.enterPosition = enterPosition;
this.leavePosition = leavePosition;
this.percent = percent;
postInvalidate();
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
private int dp2px(float dpValue) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpValue,
mContext.getResources().getDisplayMetrics());
}
}
- 所用到的辅助类
/**
* ViewPage的页面滚动监听器
*/
public interface OnPageScrollListener {
/**
* 页面滚动时调用
*
* @param enterPosition 进入页面的位置
* @param leavePosition 离开的页面的位置
* @param percent 滑动百分比
*/
void onPageScroll(int enterPosition, int leavePosition, float percent);
/**
* 页面选中时调用
*
* @param position 选中页面的位置
*/
void onPageSelected(int position);
/**
* 页面滚动状态变化时调用
*
* @param state 页面的滚动状态
*/
void onPageScrollStateChanged(int state);
}
/**
* Created by XiaoJianjun on 2017/1/8.
* ViewPager辅助类
*/
public class ViewPagerHelper implements ViewPager.OnPageChangeListener {
private double mLastPositionOffsetSum; // 上一次滑动总的偏移量
private OnPageScrollListener mOnPageScrollListener;
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// 当前总的偏移量
position = position - 1;
float currentPositionOffsetSum = position + positionOffset;
// 上次滑动的总偏移量大于此次滑动的总偏移量,页面从右向左进入(手指从右向左滑动)
boolean rightToLeft = mLastPositionOffsetSum <= currentPositionOffsetSum;
// 页面正在被拖动或惯性滑动
if (currentPositionOffsetSum == mLastPositionOffsetSum) return;
int enterPosition;
int leavePosition;
float percent;
if (rightToLeft) { // 从右向左滑
enterPosition = (positionOffset == 0.0f) ? position : position + 1;
leavePosition = enterPosition - 1;
percent = (positionOffset == 0.0f) ? 1.0f : positionOffset;
if (enterPosition == 3) {
return;
}
} else { // 从左向右滑
enterPosition = position;
leavePosition = position + 1;
percent = 1 - positionOffset;
if (enterPosition == -1) {
return;
}
}
Logger.d("enterPosition=" + enterPosition + " leavePosition=" + leavePosition + " percent=" + percent);
if (mOnPageScrollListener != null) {
mOnPageScrollListener.onPageScroll(enterPosition, leavePosition, percent);
}
mLastPositionOffsetSum = currentPositionOffsetSum;
}
@Override
public void onPageSelected(int position) {
if (mOnPageScrollListener != null) {
mOnPageScrollListener.onPageSelected(position);
}
}
/**
* @param state 当前滑动状态
* ViewPager.SCROLL_STATE_IDLE 页面处于闲置、稳定状态,即没被拖动也没惯性滑动
* ViewPager.SCROLL_STATE_DRAGGING 页面正在被用户拖动,即手指正在拖动状态
* Viewpager.SCROLL_STATE_SETTLING 页面处于即将到达最终状态的过程,即手指松开后惯性滑动状态
*/
@Override
public void onPageScrollStateChanged(int state) {
if (mOnPageScrollListener != null) {
mOnPageScrollListener.onPageScrollStateChanged(state);
}
}
public void bindScrollListener(ViewPager viewPager, OnPageScrollListener onPageScrollListener) {
mOnPageScrollListener = onPageScrollListener;
viewPager.addOnPageChangeListener(this);
}
}
- 就这几个类,原理网上一大堆就不细述了,需要注意的事设置adapter的顺序,先设置adapter在设置属性才行