先上图:
分析:这里我们用viewpager来实现,圆角效果用cardview来包裹,小圆点用画笔绘制,加上动画就搞定。
第一步:
重写viewpager(AutoScrollViewPager类):
public class AutoScrollViewPager extends ViewPager {
private static final String TAG = "AutoScrollViewPager";
private AutoScrollHandler autoScrollHandler;
private Context mContext;
private int change_anmin;
private int change_duration;
int speed = 500; //默认移动速度
private int indexCount;
private float mXp;
private float mYp;
FixedSpeedScroller mScroller = null;
public AutoScrollViewPager(@NonNull Context context) {
this(context, null);
mContext = context;
}
public AutoScrollViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mContext = context;
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.BannerIndicator);
change_anmin = array.getInteger(R.styleable.AutoScrollViewPager_change_anmin, 1);
change_duration = array.getInteger(R.styleable.AutoScrollViewPager_change_duration, 5000);
autoScrollHandler = new AutoScrollHandler(this, change_duration);
controlViewPagerSpeed();
setPageMargin(20);
}
public AutoScrollViewPager(@NonNull Context context, @Nullable AttributeSet attrs, Context mContext) {
super(context, attrs);
this.mContext = mContext;
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.BannerIndicator);
change_anmin = array.getInteger(R.styleable.AutoScrollViewPager_change_anmin, 1);
change_duration = array.getInteger(R.styleable.AutoScrollViewPager_change_duration, 5);
autoScrollHandler = new AutoScrollHandler(this, change_duration);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
/**
* 根据getAdapter获取外部传递的size是多少,如果为1则不允许移动 只允许点击
* 否则允许滑动和点击切按住时通知轮播,放开时启动轮播
*/
if (indexCount == 1) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mXp = ev.getX();
mYp = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
return false;
case MotionEvent.ACTION_UP:
return super.dispatchTouchEvent(ev);
}
return super.dispatchTouchEvent(ev);
} else {
int action = ev.getAction();
if (action == ACTION_UP || action == ACTION_CANCEL || action == ACTION_OUTSIDE) {
startAutoPlay();
} else if (action == ACTION_DOWN) {
stopAutoPlay();
}
return super.dispatchTouchEvent(ev);
}
}
/**
* 开启轮播 同时获取count
*/
public void startAutoPlay() {
if (autoScrollHandler != null) {
stopAutoPlay();
autoScrollHandler.start();
}
ViewPagerAdapter adapter = (ViewPagerAdapter) getAdapter();
assert adapter != null;
indexCount = adapter.ssss();
}
/**
* 停止轮播 同时获取count
*/
public void stopAutoPlay() {
if (autoScrollHandler != null) {
autoScrollHandler.stop();
autoScrollHandler.removeCallbacksAndMessages(null);
}
ViewPagerAdapter adapter = (ViewPagerAdapter) getAdapter();
assert adapter != null;
indexCount = adapter.ssss();
}
// 传递速度值
public void setSpeed(int speed) {
this.speed = speed;
}
/**
* 修改vp移动速度
*/
private void controlViewPagerSpeed() {
try {
Field mField;
mField = ViewPager.class.getDeclaredField("mScroller");
mField.setAccessible(true);
mScroller = new FixedSpeedScroller(mContext, new AccelerateInterpolator());
mScroller.setmDuration(speed); // 2000ms
mField.set(this, mScroller);
} catch (Exception e) {
e.printStackTrace();
}
}
}
改变vp移动速度继承scroller的重写:
public class FixedSpeedScroller extends Scroller {
private int mDuration = 1000;
public FixedSpeedScroller(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public FixedSpeedScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
// Ignore received duration, use fixed one instead
super.startScroll(startX, startY, dx, dy, mDuration);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy) {
// Ignore received duration, use fixed one instead
super.startScroll(startX, startY, dx, dy, mDuration);
}
public void setmDuration(int time) {
mDuration = time;
}
public int getmDuration() {
return mDuration;
}
}
第二步 构建Handler定时器(AutoScrollHandler类):
public class AutoScrollHandler extends Handler {
private static final String TAG = "AutoScrollHandler";
private WeakReference mBannerRef;
private static final int MSG_CHANGE_SELECTION = 1;
private static int AUTO_SCROLL_TIME = 0;
public AutoScrollHandler(AutoScrollViewPager autoScrollViewPager, int change_duration) {
mBannerRef = new WeakReference<>(autoScrollViewPager);
AUTO_SCROLL_TIME = change_duration;
}
public void start() {
removeMessages(MSG_CHANGE_SELECTION);
sendEmptyMessageDelayed(MSG_CHANGE_SELECTION, AUTO_SCROLL_TIME);
}
public void stop() {
removeMessages(MSG_CHANGE_SELECTION);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == MSG_CHANGE_SELECTION) {
if (mBannerRef == null || mBannerRef.get() == null) {
return;
}
AutoScrollViewPager banner = mBannerRef.get();
int current = banner.getCurrentItem();
/* if (current == banner.getAdapter().getCount() - 1)
current = -1;*/
banner.setCurrentItem(current + 1);
sendEmptyMessageDelayed(MSG_CHANGE_SELECTION, AUTO_SCROLL_TIME);
}
}
}
第三步:绘制indicator(BannerItemView类)
ublic class BannerItemView extends View {
private static final String TAG = "BannerItemView";
private Paint mPaint;
private float rectWidth;
private RectF rectF;
public static final int CENTER = 0;
public static final int LEFT = 1;
public static final int RIGHT = 2;
private int loaction = CENTER;
public BannerItemView(Context context) {
this(context, null);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
rectF = new RectF();
mPaint.setColor(Color.RED);
}
public BannerItemView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
rectF = new RectF();
mPaint.setColor(Color.RED);
}
public BannerItemView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
rectF = new RectF();
mPaint.setColor(Color.RED);
}
public BannerItemView(Context context, int loaction) {
this(context);
this.loaction = loaction;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
switch (loaction) {
case CENTER:
rectF.left = getWidth() / 2 - getHeight() / 2 - rectWidth;
rectF.right = getHeight() / 2 + getWidth() / 2 + rectWidth;
rectF.top = 0;
rectF.bottom = getHeight();
break;
case LEFT:
rectF.left = getWidth() - getHeight() - rectWidth;
rectF.right = getWidth();
rectF.top = 0;
rectF.bottom = getHeight();
break;
case RIGHT:
rectF.left = 0;
rectF.right = getHeight() - rectWidth;
rectF.top = 0;
rectF.bottom = getHeight();
break;
}
canvas.drawRoundRect(rectF, getHeight() / 2, getHeight() / 2, mPaint);
}
public float getRectWidth() {
return rectWidth;
}
public void setColor(int color) {
mPaint.setColor(color);
}
public void setRectWidth(float rectWidth) {
this.rectWidth = rectWidth;
invalidate();
}
public int getLoaction() {
return loaction;
}
public void setLoaction(int loaction) {
this.loaction = loaction;
}
}
第四步:将绘制的Indicator加入布局(BannerIndicator类)
public class BannerIndicator extends LinearLayout {
private static final String TAG = "BannerIndicator";
private int dashGap;
private int position;
private ViewPager viewPager;
private int slider_width;
private int slider_height;
private int sliderAlign;
private int current_color;
private int pasted_color;
private int change_speech = 200;
private List drawableList;
public BannerIndicator(Context context) {
this(context, null);
}
public BannerIndicator(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BannerIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOrientation(HORIZONTAL);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.BannerIndicator);
dashGap = (int) array.getDimension(R.styleable.BannerIndicator_gap, 3);
slider_width = (int) array.getDimension(R.styleable.BannerIndicator_slider_width, 12);
slider_height = (int) array.getDimension(R.styleable.BannerIndicator_slider_height, 4);
sliderAlign = array.getInt(R.styleable.BannerIndicator_slider_align, 1);
current_color = array.getColor(R.styleable.BannerIndicator_current_color, Color.RED); //当前颜色
pasted_color = array.getColor(R.styleable.BannerIndicator_pasted_color, Color.BLACK); //过去亚颜色
change_speech = array.getInt(R.styleable.BannerIndicator_change_speech, 200); //动画时间
array.recycle();
}
public void setUpWidthViewPager(final ViewPager viewPager, final List drawableList1) {
drawableList = new ArrayList<>();
if (this.drawableList != null && drawableList.size() != 0)
this.drawableList.clear();
this.drawableList.addAll(drawableList1);
removeAllViews();
if (viewPager == null || viewPager.getAdapter() == null)
return;
position = 0;
this.viewPager = viewPager;
for (int i = 0; i < drawableList.size(); i++) {
BannerItemView imageView = new BannerItemView(getContext(), sliderAlign);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(slider_width, slider_height);
if (i > 0) {
layoutParams.setMargins(dashGap, 0, 0, 0);
imageView.setAlpha(0.4f);
} else {
layoutParams.setMargins(0, 0, 0, 0);
imageView.setAlpha(1);
}
imageView.setLayoutParams(layoutParams);
addView(imageView);
setLarge(0);
}
viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
try {
if (BannerIndicator.this.position != position % drawableList.size()) {
resetSize(BannerIndicator.this.position, position % drawableList.size());
BannerIndicator.this.position = position % drawableList.size();
}
} catch (Exception e) {
}
}
});
}
private void resetSize(int position, int current) {
setLarge(current);
setSmall(position);
}
//指示器增大同时设置透明度变化
private void setLarge(int position) {
if (getChildAt(position) instanceof BannerItemView) {
AnimatorSet set = new AnimatorSet();
ValueAnimator animator = getEnlarge((BannerItemView) getChildAt(position));
ValueAnimator alpha = ObjectAnimator.ofFloat(getChildAt(position), "alpha", 1f, 1f);
set.play(animator).with(alpha);
set.setDuration(change_speech);
set.start();
try {
for (int i = 0; i < drawableList.size(); i++) {
if (position == i) {
BannerItemView childAt = (BannerItemView) getChildAt(i);
childAt.setColor(current_color);
} else {
BannerItemView childAt = (BannerItemView) getChildAt(i);
childAt.setColor(pasted_color);
}
}
} catch (Exception e) {
}
}
}
//放大动画
private ValueAnimator getEnlarge(BannerItemView roundRectView) {
return ObjectAnimator.ofFloat(roundRectView,
"rectWidth",
0, getOffset(roundRectView));
}
//根据大小变化方向获取指示器大小偏移量
private int getOffset(BannerItemView bannerItemView) {
int offsest = 0;
switch (bannerItemView.getLoaction()) {
case BannerItemView.CENTER:
offsest = (slider_width - slider_height) / 2;
break;
case BannerItemView.LEFT:
offsest = slider_width - slider_height;
break;
case BannerItemView.RIGHT:
offsest = slider_width - slider_height;
break;
}
return offsest;
}
//缩小动画
private ValueAnimator getShrink(BannerItemView roundRectView) {
return ObjectAnimator.ofFloat(roundRectView,
"rectWidth",
getOffset(roundRectView), 0);
}
//缩小动画同事伴随透明度变化
public void setSmall(int small) {
if (getChildAt(small) instanceof BannerItemView) {
AnimatorSet set = new AnimatorSet();
ValueAnimator alpha = ObjectAnimator.ofFloat(getChildAt(position), "alpha", 1, 0.4f);
ValueAnimator animator = getShrink((BannerItemView) getChildAt(small));
set.play(animator).with(alpha);
set.setDuration(618);
set.start();
}
}
}
第五步: viewpager的适配器(ViewPagerAdapter类)
public class ViewPagerAdapter extends PagerAdapter {
private Context mContext;
private List mCache;
List views = new ArrayList<>();
private List drawableList;
private final RequestOptions optionss;
public ViewPagerAdapter(List list, Context context) {
drawableList = new ArrayList<>();
optionss = new RequestOptions();
optionss.placeholder(R.mipmap.pre_img);//图片加载出来前,显示的图片
optionss.fallback(R.mipmap.pre_img); //url为空的时候,显示的图片
optionss.error(R.mipmap.pre_img);//图片加载失败后,显示的图片
if (drawableList.size() != 0)
drawableList.clear();
drawableList.addAll(list);
mContext = context;
mCache = new ArrayList<>();
for (int i = 0; i < drawableList.size(); i++) {
ImageView imageView = new ImageView(mContext);
Glide.with(mContext).load(drawableList.get(i).getPic()).apply(optionss).into(imageView);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
views.add(imageView);
}
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
return view == o;
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, final int position) {
if (drawableList != null && drawableList.size() > 0) {
View imageView = null;
if (mCache.isEmpty()) {
imageView = View.inflate(container.getContext(), R.layout.item_imagess, null);
} else {
imageView = mCache.remove(0);
}
ImageView xxximg_ = (ImageView) imageView.findViewById(R.id.xxximg_);
TextView show_tv_show = (TextView) imageView.findViewById(R.id.show_tv_show);
Glide.with(mContext).load(drawableList.get(position % drawableList.size()).getPic()).into(xxximg_);
show_tv_show.setText(drawableList.get(position % drawableList.size()).getB_name() + "");
xxximg_.setScaleType(ImageView.ScaleType.FIT_XY);
container.addView(imageView);
final View finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
bannerListener.ItemClick(position % drawableList.size(), drawableList.get(position % drawableList.size()));
} catch (Exception e) {
}
}
});
return imageView;
}
return null;
}
/**
* 页面宽度所占ViewPager测量宽度的权重比例,默认为1
*/
@Override
public float getPageWidth(int position) {
return (float) 1;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
View imageView = (View) object;
container.removeView(imageView);
mCache.add(imageView);
}
BannerListener bannerListener = null;
public void setItemClickListener(BannerListener bannerListener) {
this.bannerListener = bannerListener;
}
public interface BannerListener {
void ItemClick(int postion, GetTopBannerBena.ResultBean.DataBean.ListBean.BannerBean data);
}
public int ssss(){
return drawableList.size();
}
}
收尾:用法
xml中:
java代码中: ViewPagerAdapter pagerAdapter = new ViewPagerAdapter(topBannerList, getActivity()); autoScrollViewPager.setAdapter(pagerAdapter); bannerIndicator.setUpWidthViewPager(autoScrollViewPager, topBannerList); if (topBannerList.size() == 1) { autoScrollViewPager.stopAutoPlay(); } else { autoScrollViewPager.startAutoPlay(); }
pagerAdapter.setItemClickListener(new ViewPagerAdapter.BannerListener() {
@Override
public void ItemClick(int postion, GetTopBannerBena.ResultBean.DataBean.ListBean.BannerBean bannerDatas) {
});
结束:如果需要切换动画:可以实现ViewPager.PageTransformer接口 如下
public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 1f;
private static final float MIN_ALPHA = 1f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 1) { // [-1,1]
// Modify the default slide transition to shrink the page as well
float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (position < 0) {
view.setTranslationX(horzMargin - vertMargin / 2);
} else {
view.setTranslationX(-horzMargin + vertMargin / 2);
}
// Scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
// Fade the page relative to its size.
view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}