今天我们准备做一款根据viewpager做改动的自定义圆点,并且更改viewpager原有动画。
思路如下:
1、做到自动化,圆点根据viewpager的大小来订制。有多少个viewpager就有多少个圆点;
2、滑动的时候让圆点也要跟着滑动;
3、去掉viewpager原有动画,加上自己需要的移动动画;
4、设置点击事件,为了不让事件冲突,我这里是用OnTouch来模拟点击做的;
先贴效果:
界面代码如下(代码里面有详细注释):
package com.wyw.viewpageranimationdemo;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
// 切换页控件
private ViewPager viewPager;
// 切换也白点控件
private CircleViewpager circlePager;
// view集合
private ArrayList<View> views;
// 切换页适配器
private ViewPagerAdapter adapter;
//当前轮播下标
public int currentItem = 0;
//按下的X轴
private float downx;
//按下的Y轴
private float downy;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPager);
circlePager = (CircleViewpager) findViewById(R.id.indicator);
initData();
//捕捉页面切换Touch事件
viewPager.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
//按下时关闭轮播
downx = motionEvent.getRawX();
downy = motionEvent.getRawY();
break;
case MotionEvent.ACTION_UP:
//按下的xy轴 - 抬起时的xy轴 < 10 就等于是点击事件
if (Math.abs(downx - motionEvent.getRawX()) < 10 && Math.abs(downy - motionEvent.getRawY()) < 10) {
Toast.makeText(MainActivity.this, currentItem+"", Toast.LENGTH_LONG).show();
}
break;
}
return false;
}
});
}
private void initData() {
views = new ArrayList<View>();
for (int i = 0; i < 4; i++) {
ImageView img = new ImageView(MainActivity.this);
img.setScaleType(ImageView.ScaleType.CENTER_CROP);
img.setTag(i);
switch (i) {
case 0:
img.setBackgroundResource(R.color.ffffaf1a);
break;
case 1:
img.setBackgroundResource(R.color.ffef5088);
break;
case 2:
img.setBackgroundResource(R.color.ff56ae2e);
break;
case 3:
img.setBackgroundResource(R.color.ff3598da);
break;
default:
break;
}
views.add(img);
}
adapter = new ViewPagerAdapter();
viewPager.setAdapter(adapter);
//设置圆点的纵向位置 距上面185dp
circlePager.setDy(DisplayUtil.dip2px(MainActivity.this, 185));
//设置圆点传入viewPager自动算出多少个圆点
circlePager.setViewPager(viewPager, MainActivity.this);
//设置切换动画
viewPager.setPageTransformer(true, new CubeOutTransformer());
}
private class ViewPagerAdapter extends PagerAdapter {
// 获取要滑动的控件的数量,在这里我们以滑动的广告栏为例,那么这里就应该是展示的广告图片的ImageView数量
@Override
public int getCount() {
return views.size();
}
// 来判断显示的是否是同一张图片,这里我们将两个参数相比较返回即可
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
// 当要显示的图片可以进行缓存的时候,会调用这个方法进行显示图片的初始化,我们将要显示的ImageView加入到ViewGroup中,然后作为返回值返回即可
@Override
public Object instantiateItem(ViewGroup view, final int position) {
view.addView(views.get(position));
return views.get(position);
}
// PagerAdapter只缓存三张要显示的图片,如果滑动的图片超出了缓存的范围,就会调用这个方法,将图片销毁
@Override
public void destroyItem(ViewGroup view, int position, Object object) {
view.removeView(views.get(position));
}
}
}
自定义圆点代码:
package com.wyw.viewpageranimationdemo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.View;
/**
* 自动创建圆点viewpager
*/
public class CircleViewpager extends View implements
ViewPager.OnPageChangeListener {
// 上下文
private Context context;
// 切换页面控件
private ViewPager mViewPager;
// 当前滑动状态
private int mScrollState;
// 第几页
private int mCurrentPage;
// 当前页面偏移的百分比
private float mPageOffset;
// 页面总数
private int count;
// 第一个圆点显示的位置
float longOffset;
// 圆点的半径
private float mRadius;
// 第一个圆点的左边x坐标和第二个圆点的左边x坐标相距5个半径(实际第一个和第二个真是相距是3个半径)
public float dX;
// y坐标
private float dy;
// 移动的圆点画笔
private Paint mPaintFill;
// 固定的圆点画笔
private Paint mPaintStroke;
// 车生活fragment
private MainActivity MainActivity;
private int width;
// 设置y坐标
public void setDy(float dy) {
this.dy = dy;
}
public CircleViewpager(Context context) {
super(context);
this.context = context;
init();
}
public CircleViewpager(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public CircleViewpager(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
init();
}
private void init() {
// 默认-1
dy = -1;
//屏幕宽度
width = DisplayUtil.getScreenWidthPx(context);
//圆点的半径 是4dp
mRadius = DisplayUtil.dip2px(context, 4);
//第一个圆点的左边x坐标和第二个圆点的左边x坐标相距4个半径(实际第一个和第二个真是相距是2个半径)
dX = mRadius * 4;
mPaintFill = new Paint();
mPaintFill.setStyle(Paint.Style.FILL);
mPaintFill.setColor(getResources().getColor(R.color.white));
mPaintStroke = new Paint();
mPaintStroke.setStyle(Paint.Style.FILL);
mPaintStroke.setColor(getResources().getColor(R.color.white_30));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mViewPager == null) {
return;
}
// 获取总页数
count = mViewPager.getAdapter().getCount();
if (count == 0) {
return;
}
// 第一个圆点的位置
longOffset = (width / 2.0f) - ((count - 1) * dX / 2.0f);
if (dy != -1) {
for (int i = 0; i < count; i++) {
// 在指定x和y坐标画出默认圆点
canvas.drawCircle(longOffset + (dX * i), dy, mRadius,
mPaintStroke);
}
}
// 在指定x和y坐标画出移动圆点
canvas.drawCircle(
(mCurrentPage * dX) + (dX * mPageOffset) + longOffset, dy,
mRadius, mPaintFill);
}
// 设置viewpager
public void setViewPager(ViewPager view, MainActivity MainActivity) {
if (mViewPager == view) {
if (mViewPager.getAdapter().getCount() == view.getAdapter()
.getCount()) {
return;
}
}
if (view.getAdapter() == null) {
return;
}
if (mViewPager != null) {
mViewPager.setOnPageChangeListener(null);
}
this.MainActivity = MainActivity;
mViewPager = view;
// 设置页面切换监听
mViewPager.setOnPageChangeListener(this);
invalidate();
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
// 获取当前页下标
mCurrentPage = position;
// 获取当前页面偏移的百分比
mPageOffset = positionOffset;
invalidate();
}
@Override
public void onPageSelected(int position) {
// mScrollState ==SCROLL_STATE_DRAGGING
// 表示正在滑动,mScrollState==SCROLL_STATE_SETTLING 表示滑动完毕了,
// mScrollState==SCROLL_STATE_IDLE表示什么都没做
if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
// 获取当前页下标
mCurrentPage = position;
invalidate();
}
MainActivity.currentItem = position;
}
@Override
public void onPageScrollStateChanged(int state) {
// mScrollState ==1表示正在滑动,mScrollState==2表示滑动完毕了,mScrollState==0表示什么都没做
mScrollState = state;
}
}
去除viewpager原有滑动动画改为自定义代码(找的网上开源代码这里就不注释了,调用只需要这一段代码即可viewPager.setPageTransformer(true, new CubeOutTransformer());)。如果需要自己改动画重写CubeOutTransformer这个类里面这个onTransform()这个方法即可;
package com.wyw.viewpageranimationdemo;
import android.annotation.SuppressLint;
import android.support.v4.view.ViewPager.PageTransformer;
import android.view.View;
@SuppressLint("NewApi")
public abstract class ABaseTransformer implements PageTransformer {
/**
* Called each {@link #transformPage(View, float)}.
*
* @param page
* Apply the transformation to this page
* @param position
* Position of page relative to the current front-and-center position of the pager. 0 is front and
* center. 1 is one full page position to the right, and -1 is one page position to the left.
*/
protected abstract void onTransform(View page, float position);
/**
* Apply a property transformation to the given page. For most use cases, this method should not be overridden.
* Instead use {@link #transformPage(View, float)} to perform typical transformations.
*
* @param page
* Apply the transformation to this page
* @param position
* Position of page relative to the current front-and-center position of the pager. 0 is front and
* center. 1 is one full page position to the right, and -1 is one page position to the left.
*/
@Override
public void transformPage(View page, float position) {
onPreTransform(page, position);
onTransform(page, position);
onPostTransform(page, position);
}
/**
* If the position offset of a fragment is less than negative one or greater than one, returning true will set the
* fragment alpha to 0f. Otherwise fragment alpha is always defaulted to 1f.
*
* @return
*/
protected boolean hideOffscreenPages() {
return true;
}
/**
* Indicates if the default animations of the view pager should be used.
*
* @return
*/
protected boolean isPagingEnabled() {
return false;
}
/**
* Called each {@link #transformPage(View, float)} before {{@link #onTransform(View, float)}.
* <p>
* The default implementation attempts to reset all view properties. This is useful when toggling transforms that do
* not modify the same page properties. For instance changing from a transformation that applies rotation to a
* transformation that fades can inadvertently leave a fragment stuck with a rotation or with some degree of applied
* alpha.
*
* @param page
* Apply the transformation to this page
* @param position
* Position of page relative to the current front-and-center position of the pager. 0 is front and
* center. 1 is one full page position to the right, and -1 is one page position to the left.
*/
protected void onPreTransform(View page, float position) {
final float width = page.getWidth();
page.setRotationX(0);
page.setRotationY(0);
page.setRotation(0);
page.setScaleX(1);
page.setScaleY(1);
page.setPivotX(0);
page.setPivotY(0);
page.setTranslationY(0);
page.setTranslationX(isPagingEnabled() ? 0f : -width * position);
if (hideOffscreenPages()) {
page.setAlpha(position <= -1f || position >= 1f ? 0f : 1f);
page.setEnabled(false);
} else {
page.setEnabled(true);
page.setAlpha(1f);
}
}
/**
* Called each {@link #transformPage(View, float)} after {@link #onTransform(View, float)}.
*
* @param page
* Apply the transformation to this page
* @param position
* Position of page relative to the current front-and-center position of the pager. 0 is front and
* center. 1 is one full page position to the right, and -1 is one page position to the left.
*/
protected void onPostTransform(View page, float position) {
}
/**
* Same as {@link Math#min(double, double)} without double casting, zero closest to infinity handling, or NaN support.
*
* @param val
* @param min
* @return
*/
protected static final float min(float val, float min) {
return val < min ? min : val;
}
}
package com.wyw.viewpageranimationdemo;
import android.annotation.SuppressLint;
import android.view.View;
@SuppressLint("NewApi")
public class CubeOutTransformer extends ABaseTransformer {
@Override
protected void onTransform(View view, float position) {
view.setPivotX(position < 0f ? view.getWidth() : 0f);
view.setPivotY(view.getHeight() * 0.5f);
view.setRotationY(90f * position);
}
@Override
public boolean isPagingEnabled() {
return true;
}
}
本篇博客就到这里,如果对viewpager滑动动画有兴趣的朋友可以去尝试重写那个类,改变他的滑动轨迹。
希望大家多多关注我的博客,多多支持我。
如有好意见或更好的方式欢迎留言谈论。
尊重原创转载请注明:(http://blog.csdn.net/u013895206) !
下面是地址传送门:
http://download.csdn.net/detail/u013895206/9344739