Banner 要实现的功能
1.创建Banner (自定义Banner)
2.创建IBannerData 接口
3.创建BannerAdapter (适配器)
4.创建Indicator 接口 (定义指示器要实现的方法)
5.创建CircleIndicator (自定义指示器)
6.创建ScrollSpeedManger(改变LinearLayoutManager的切换速度)
1.创建IBannerData 接口:
创建契约类:通过接口回调的方式获取title 和url
public interface IBannerData {
String getUrl();
String getTitle();
}
2.创建BannerAdapter(banner适配器)
创建适配器:继承RecyclerView.Adapter 给ViewPager2添加item
public class BannerAdapter extends RecyclerView.Adapter<BannerAdapter.ViewHolder> {
private static int mCount =0;
private ArrayList<? extends IBannerData> mData;
public BannerAdapter(ArrayList<? extends IBannerData> mData) {
this.mData = mData;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ImageView imageView = new ImageView(parent.getContext());
imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
imageView.setTag(mCount);
return new ViewHolder(imageView);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
position=position%mData.size();
if (position==0){
holder.setData(R.drawable.ee);
}else if (position==1){
holder.setData(R.drawable.dd);
}else if (position==2){
holder.setData(R.drawable.ff);
}else if (position==3){
holder.setData(R.drawable.gg);
}
}
@Override
public int getItemCount() {
return mData==null?0:Integer.MAX_VALUE;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
}
private void setData(int id){
itemView.setBackgroundResource(id);
}
}
}
3.创建Banner(自定义banner)
1.首先创建类继承ConstraintLayout (约束布局)
2.通过new 的方式得到控件放到onFinishInflate 方法中。
3.使用ConstraintSet 的对象将得到的控件克隆(clone)到父布局(ConstraintLayout )上。连接(connect)约束条件 ,并且设置控件的宽和高,适用于(applyTo)ConstraintLayout 布局中。至此完成了控件的创建。
4.将dp 转换成px 应用于控件的高度 或与父容器的距离。
public class Banner extends ConstraintLayout {
private static final int DEFAULT_INTERVAL = 3000;//时间间隔
private static final int DEFAULT_TIME = 3000;//时间间隔
private ViewPager2 viewPager2;
private TextView title;
private Indicator mIndicator;
private static int mIds=0x1000;//变量
private ArrayList<? extends IBannerData> mData;//适配器使用
private int mIndicatorEndMargin;//指示器端部边距
private boolean isAutoLoop = true; // 是否自动循环
private int mScrollTime ;// 轮播切换时间
private int mInterval; // 切换间隔时间
private int mScrollMode;//切换模式
private int mMarginTitleStart;//间距
private int mTitleTextSize;//title 字体大小
private int mTitleTextColor;//title 高度
private int mTitleBgViewHeight;//title 的背景高度
private int mIndicatorRadio;//半径
private int mIndicatorSelectColor;//背景
private int mIndicatorUnSelectColor;
public Banner(Context context) {
super(context);
}
public Banner(Context context, AttributeSet attrs) {
super(context, attrs);
}
public Banner(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
initValue();
initView();
}
private void initValue() {
mIndicatorEndMargin= dip2px(15);
mInterval=DEFAULT_INTERVAL;
mScrollTime=DEFAULT_TIME;
}
public ViewPager2 getViewPager2() {
return viewPager2;
}
public int getScrollTime() {
return mScrollTime;
}
public Banner setScrollTime(int mScrollTime) {
this.mScrollTime = mScrollTime;
return this;
}
private void initView() {
//添加一个viewPager2
viewPager2 = new ViewPager2(getContext());
//创建id
viewPager2.setId(mIds++);
//view Page2 监听
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
title.setText(mData.get(position % mData.size()).getTitle());
mIndicator.setCurrent(position % mData.size());
}
});
//添加
addView(viewPager2);
//创建约束集
ConstraintSet constraintSet = new ConstraintSet();
//克隆约束集
constraintSet.clone(this);
constraintSet.connect(viewPager2.getId(),ConstraintSet.START,ConstraintSet.PARENT_ID,ConstraintSet.START);
constraintSet.connect(viewPager2.getId(),ConstraintSet.END,ConstraintSet.PARENT_ID,ConstraintSet.END);
constraintSet.connect(viewPager2.getId(),ConstraintSet.BOTTOM,ConstraintSet.PARENT_ID,ConstraintSet.BOTTOM);
constraintSet.connect(viewPager2.getId(),ConstraintSet.TOP,ConstraintSet.PARENT_ID,ConstraintSet.TOP);
constraintSet.constrainWidth(viewPager2.getId(),ConstraintSet.MATCH_CONSTRAINT);
constraintSet.constrainHeight(viewPager2.getId(),ConstraintSet.MATCH_CONSTRAINT);
//添加一个title 半透明背景
ImageView background = new ImageView(getContext());
background.setBackgroundColor(Color.parseColor("#40000000"));
background.setId(mIds++);
addView(background);
constraintSet.connect(background.getId(),ConstraintSet.START,ConstraintSet.PARENT_ID,ConstraintSet.START);
constraintSet.connect(background.getId(),ConstraintSet.END,ConstraintSet.PARENT_ID,ConstraintSet.END);
constraintSet.connect(background.getId(),ConstraintSet.BOTTOM,ConstraintSet.PARENT_ID,ConstraintSet.BOTTOM);
constraintSet.constrainWidth(background.getId(),ConstraintSet.MATCH_CONSTRAINT);
constraintSet.constrainHeight(background.getId(),dip2px(30));
//添加一个圆点容器
mIndicator=new CircleIndicator(getContext());
mIndicator.setRadio(10);
mIndicator.setMargin(10);
mIndicator.setSelectColor(Color.BLACK);
mIndicator.setUnSelectColor(Color.WHITE);
mIndicator.setId(mIds++);
addView((View) mIndicator);
constraintSet.connect(mIndicator.getId(),ConstraintSet.END,ConstraintSet.PARENT_ID,ConstraintSet.END,mIndicatorEndMargin);
constraintSet.connect(mIndicator.getId(),ConstraintSet.BOTTOM,background.getId(),ConstraintSet.BOTTOM);
constraintSet.connect(mIndicator.getId(),ConstraintSet.TOP,background.getId(),ConstraintSet.TOP);
constraintSet.constrainWidth(mIndicator.getId(),ConstraintSet.MATCH_CONSTRAINT);
constraintSet.constrainHeight(mIndicator.getId(),ConstraintSet.MATCH_CONSTRAINT);
//添加一个title
title = new TextView(getContext());
title.setId(mIds++);
title.setTextColor(Color.WHITE);
title.setEllipsize(TextUtils.TruncateAt.MARQUEE);
title.setSelected(true);
title.setSingleLine(true);
title.setMarqueeRepeatLimit(-1);
addView(title);
constraintSet.connect(title.getId(),ConstraintSet.START,ConstraintSet.PARENT_ID,ConstraintSet.START);
constraintSet.connect(title.getId(),ConstraintSet.END,mIndicator.getId(),ConstraintSet.END,mIndicatorEndMargin);
constraintSet.connect(title.getId(),ConstraintSet.BOTTOM,background.getId(),ConstraintSet.BOTTOM);
constraintSet.connect(title.getId(),ConstraintSet.TOP,background.getId(),ConstraintSet.TOP);
constraintSet.constrainWidth(title.getId(),ConstraintSet.MATCH_CONSTRAINT);
constraintSet.constrainHeight(title.getId(),ConstraintSet.MATCH_CONSTRAINT);
constraintSet.applyTo(this);
}
//触摸停止 dispatchTouchEvent
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:{
stopLoop();
break;
}
case MotionEvent.ACTION_UP:{
startLoop();
}
}
return super.dispatchTouchEvent(ev);
}
public void setData(ArrayList<? extends IBannerData> bannerData){
mData = bannerData;
viewPager2.setAdapter(new BannerAdapter(bannerData));
viewPager2.setUserInputEnabled(true);
//viewPager2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);//横向
viewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);//竖向
ScrollSpeedManger.reflectLayoutManager(this);
//取中间数来作为起始位置
int index = (Integer.MAX_VALUE / 2) - (Integer.MAX_VALUE / 2 % bannerData.size());
viewPager2.setCurrentItem(index,false);
mIndicator.setCount(bannerData.size());
mIndicator.setCurrent(index % mData.size());
mIndicator.setCurrent(index%mData.size());
}
//事件分发 的可见性改变 如果能见度为 可见 就开始启动循环 否则就暂停循环 返回销毁
@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
if(visibility == VISIBLE){
startLoop();
}else{
stopLoop();
}
}
private Runnable mLoopTask = new Runnable() {//创建多线程
@Override
public void run() {
//获取当前项目item
int currentItem = viewPager2.getCurrentItem();
//给当前项目 传入item .和 smoothScroll 是否平滑滚动
viewPager2.setCurrentItem(++currentItem, true);
//getHandler()使用PostDelayed方法,切换间隔时间后调用此Runnable对象
getHandler().postDelayed(mLoopTask,mInterval);
}
};
private void startLoop(){
if (isAutoLoop&&mData.size()>0&&mData!=null){
getHandler().postDelayed(mLoopTask,mInterval);
}
}
private void stopLoop(){
//删除回调mLoopTask
getHandler().removeCallbacks(mLoopTask);
}
//dp 转px
public int dip2px(float dpValue) {
final float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
4.创建Indicator 接口 (定义指示器要实现的方法)
//创建接口指示符 指示器的接口
public interface Indicator {
void setRadio(int radio);
//数量
void setCount(int count);
void setCurrent(int index);
void setUnSelectColor(int color);
void setSelectColor(int color);
void setMargin(int margin);
void setId(int id);
int getId();
}
5.创建CircleIndicator (自定义指示器)
public class CircleIndicator extends View implements Indicator{
private static final int MAX_COUNT = 10;//最大显示个数
private int mCurrentIndex;
private int unSelectColor;//颜色
private int selectColor;//颜色
private int mRadio;//半径
private int mCount;// 最终显示个数
private int mCurrent; // 实际个数
private int mMargin;//间距
private int mHeight;
private int mWidth;
private Paint mPaint;
public CircleIndicator(Context context) {
super(context);
initPain();
}
public CircleIndicator(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initPain();
}
public CircleIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPain();
}
//创建画笔
private void initPain(){
mPaint = new Paint();
mPaint.setAntiAlias(true);//图片去锯齿
mPaint.setStyle(Paint.Style.FILL);//填充样式
mPaint.setColor(Color.WHITE);//默认白色
}
//计算圆点的高和宽
private void calculation(){
//获取高度
mHeight = mRadio * 2;
//最终显示个数 如果定了显示个数,或最大显示个数,找最小的为最终显示个数。
mCount = Math.min(mCurrent,MAX_COUNT);
//获取宽度
mWidth = (mCount * mRadio * 2) + (mCount - 1) * mMargin;
invalidate(); // 刷新页面,重新onMeasure onLayout,onDraw
}
//测量
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//测量的尺寸为 规格 宽 mWidth 高 mHeight
setMeasuredDimension(MeasureSpec.makeMeasureSpec(mWidth,MeasureSpec.EXACTLY),MeasureSpec.makeMeasureSpec(mHeight,MeasureSpec.EXACTLY));
}
//绘制
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//显示的个数 for循环 绘制圆点
for (int i = 0; i < mCount; i++) {
if (i==mCurrentIndex){
mPaint.setColor(selectColor);
}else{
mPaint.setColor(unSelectColor);
}
//宽,高,半径,画笔
canvas.drawCircle((i*(mRadio*2)+(i*mMargin)+mRadio),mRadio,mRadio,mPaint);
}
}
@Override
public void setRadio(int radio) {
mRadio =radio;
}
@Override
public void setMargin(int margin) {
mMargin=margin;
}
@Override
public void setCount(int count) {
//如果实际个数不等于显示的个数就复值 并计算圆点容器的高和宽
if (mCurrent!=count){
mCurrent=count;
calculation();
}
}
@Override
public void setCurrent(int index) {
//传入的数与mCurrentIndex 不同复值,并刷新页面
if (mCurrentIndex!=index){
mCurrentIndex=index;
invalidate(); // 刷新页面,重新onMeasure onLayout,onDraw
}
}
@Override
public void setUnSelectColor(int color) {
unSelectColor=color;
}
@Override
public void setSelectColor(int color) {
selectColor=color;
}
}
6.创建ScrollSpeedManger(改变LinearLayoutManager的切换速度)
要在Banner 中创建get方法 获取ViewPager2
/**
* 改变LinearLayoutManager的切换速度
*/
public class ScrollSpeedManger extends LinearLayoutManager {
private Banner banner;
public ScrollSpeedManger(Banner banner, LinearLayoutManager linearLayoutManager) {
super(banner.getContext(), linearLayoutManager.getOrientation(), false);
this.banner = banner;
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
@Override
protected int calculateTimeForDeceleration(int dx) {
return banner.getScrollTime();
}
};
linearSmoothScroller.setTargetPosition(position);
startSmoothScroll(linearSmoothScroller);
}
public static void reflectLayoutManager(Banner banner) {
if (banner.getScrollTime() < 100) return;
try {
ViewPager2 viewPager2 = banner.getViewPager2();
RecyclerView recyclerView = (RecyclerView) viewPager2.getChildAt(0);
recyclerView.setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER);
ScrollSpeedManger speedManger = new ScrollSpeedManger(banner, (LinearLayoutManager) recyclerView.getLayoutManager());
recyclerView.setLayoutManager(speedManger);
Field LayoutMangerField = ViewPager2.class.getDeclaredField("mLayoutManager");
LayoutMangerField.setAccessible(true);
LayoutMangerField.set(viewPager2, speedManger);
Field pageTransformerAdapterField = ViewPager2.class.getDeclaredField("mPageTransformerAdapter");
pageTransformerAdapterField.setAccessible(true);
Object mPageTransformerAdapter = pageTransformerAdapterField.get(viewPager2);
if (mPageTransformerAdapter != null) {
Class<?> aClass = mPageTransformerAdapter.getClass();
Field layoutManager = aClass.getDeclaredField("mLayoutManager");
layoutManager.setAccessible(true);
layoutManager.set(mPageTransformerAdapter, speedManger);
}
Field scrollEventAdapterField = ViewPager2.class.getDeclaredField("mScrollEventAdapter");
scrollEventAdapterField.setAccessible(true);
Object mScrollEventAdapter = scrollEventAdapterField.get(viewPager2);
if (mScrollEventAdapter != null) {
Class<?> aClass = mScrollEventAdapter.getClass();
Field layoutManager = aClass.getDeclaredField("mLayoutManager");
layoutManager.setAccessible(true);
layoutManager.set(mScrollEventAdapter, speedManger);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
网友评论