一.自定义Banner无限轮播图式样
1.效果图:(一屏三页自定义,用RecyclerView实现无限轮播图,有普通版和3d版,包括上下滑动效果)
图一:
图二:
图三:
支持自定义圆形、圆角矩形、椭圆形等指示器(支持所有shape标签的形状显示)
支持无限轮播
支持轮播图点击事件
支持快速活动
支持上下滑动
支持当前图片缩放比列等等
属性
属性名称 | 方法 | 意义 | 类型 | 默认值 |
app:showIndicator | setShowIndicator(boolean showIndicator) | 是否显示指示器 | boolean | true |
app:interval | setAutoPlayDuration(int autoPlayDuration) | 轮播时间间隔 | int | 4000 |
app:isAutoPlaying | setAutoPlaying(boolean isAutoPlaying) | 是否开启自动轮播 | boolean | true |
app:orientation | setOrientation(int orientation) | 轮播图方向 | enum | horizontal |
app:itemSpace | setItemSpace(int itemSpace) | 图片间距 | int | 20 |
app:centerScale | setCenterScale(float centerScale) | 当前图片缩放比列 | float | 1.2 |
app:moveSpeed | setMoveSpeed(float moveSpeed) | 滚动速度,越大越快 | float | 1.0 |
2.主要函数代码:(JAVA)
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;
import com.example.library.banner.BannerLayout;
import com.renny.recyclerbanner.adapter.WebBannerAdapter;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements BannerLayout.OnBannerItemClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BannerLayout recyclerBanner = findViewById(R.id.recycler);
BannerLayout bannerVertical = findViewById(R.id.recycler_ver);
List<String> list = new ArrayList<>();
list.add("http://img0.imgtn.bdimg.com/it/u=1352823040,1166166164&fm=27&gp=0.jpg");
list.add("http://img3.imgtn.bdimg.com/it/u=2293177440,3125900197&fm=27&gp=0.jpg");
list.add("http://img3.imgtn.bdimg.com/it/u=3967183915,4078698000&fm=27&gp=0.jpg");
list.add("http://img0.imgtn.bdimg.com/it/u=3184221534,2238244948&fm=27&gp=0.jpg");
list.add("http://img4.imgtn.bdimg.com/it/u=1794621527,1964098559&fm=27&gp=0.jpg");
list.add("http://img4.imgtn.bdimg.com/it/u=1243617734,335916716&fm=27&gp=0.jpg");
WebBannerAdapter webBannerAdapter=new WebBannerAdapter(this,list);
webBannerAdapter.setOnBannerItemClickListener(new BannerLayout.OnBannerItemClickListener() {
@Override
public void onItemClick(int position) {
Toast.makeText(MainActivity.this, "点击了第 " + position+" 项", Toast.LENGTH_SHORT).show();
}
});
WebBannerAdapter WebBannerAdapter2 =new WebBannerAdapter(this,list);
WebBannerAdapter2.setOnBannerItemClickListener(new BannerLayout.OnBannerItemClickListener() {
@Override
public void onItemClick(int position) {
Toast.makeText(MainActivity.this, "点击了第 " + position+" 项", Toast.LENGTH_SHORT).show();
}
});
recyclerBanner.setAdapter(webBannerAdapter);
bannerVertical.setAdapter(WebBannerAdapter2);
}
public void jump(View view) {
startActivity(new Intent(MainActivity.this, NormalActivity.class));
}
public void jumpOverFlying(View view) {
startActivity(new Intent(MainActivity.this, OverFlyingActivity.class));
}
@Override
public void onItemClick(int position) {
}
}
主要函数代码:(Kotlin)
val webBannerAdapter = WebBannerAdapter(mActivity,it);
webBannerAdapter.setOnBannerItemClickListener(object :
BannerLayout.OnBannerItemClickListener {
override fun onItemClick(position: Int) {
Toast.makeText(mActivity ,"点击了第 " + position+" 项", Toast.LENGTH_SHORT).show();
}
});
binding!!.banner.setAdapter(webBannerAdapter)
3.自定义Banner(图一的两个效果)
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.GravityCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.example.library.R;
import com.example.library.banner.layoutmanager.CenterSnapHelper;
import com.example.library.banner.layoutmanager.BannerLayoutManager;
import static android.view.Gravity.CENTER;
import static android.widget.AbsListView.OnScrollListener.SCROLL_STATE_IDLE;
public class BannerLayout extends FrameLayout {
private int autoPlayDuration;//刷新间隔时间
private boolean showIndicator;//是否显示指示器
private RecyclerView indicatorContainer;
private Drawable mSelectedDrawable;
private Drawable mUnselectedDrawable;
private IndicatorAdapter indicatorAdapter;
private int indicatorMargin;//指示器间距
private RecyclerView mRecyclerView;
private BannerLayoutManager mLayoutManager;
private int WHAT_AUTO_PLAY = 1000;
private boolean hasInit;
private int bannerSize = 1;
private int currentIndex;
private boolean isPlaying = false;
private boolean isAutoPlaying = true;
int itemSpace;
float centerScale;
float moveSpeed;
protected Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.what == WHAT_AUTO_PLAY) {
if (currentIndex == mLayoutManager.getCurrentPosition()) {
++currentIndex;
mRecyclerView.smoothScrollToPosition(currentIndex);
mHandler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration);
refreshIndicator();
}
}
return false;
}
});
public BannerLayout(Context context) {
this(context, null);
}
public BannerLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BannerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context, attrs);
}
protected void initView(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BannerLayout);
showIndicator = a.getBoolean(R.styleable.BannerLayout_showIndicator, true);
autoPlayDuration = a.getInt(R.styleable.BannerLayout_interval, 4000);
isAutoPlaying = a.getBoolean(R.styleable.BannerLayout_autoPlaying, true);
itemSpace = a.getInt(R.styleable.BannerLayout_itemSpace, 20);
centerScale = a.getFloat(R.styleable.BannerLayout_centerScale, 1.2f);
moveSpeed = a.getFloat(R.styleable.BannerLayout_moveSpeed, 1.0f);
if (mSelectedDrawable == null) {
//绘制默认选中状态图形-- 自定义椭圆形指示器,圆角矩形
GradientDrawable drawable = (GradientDrawable) context.getResources().getDrawable(R.drawable.bg52);
// drawable .setColor(Color.parseColor("#ff4400"));
mSelectedDrawable = new LayerDrawable(new Drawable[]{drawable});
//绘制默认选中状态图形 -- 圆形
// GradientDrawable selectedGradientDrawable = new GradientDrawable();
// selectedGradientDrawable.setShape(GradientDrawable.OVAL);
// selectedGradientDrawable.setColor(Color.RED);
// selectedGradientDrawable.setSize(dp2px(5), dp2px(5));
// selectedGradientDrawable.setCornerRadius(dp2px(5) / 2);
// mSelectedDrawable = new LayerDrawable(new Drawable[]{selectedGradientDrawable});
}
if (mUnselectedDrawable == null) {
//绘制默认未选中状态图形 -- 自定义椭圆形指示器,圆角矩形
GradientDrawable drawable = (GradientDrawable) context.getResources().getDrawable(R.drawable.bg53);
// drawable .setColor(Color.parseColor("#ff4400"));
mUnselectedDrawable = new LayerDrawable(new Drawable[]{drawable});
//绘制默认未选中状态图形 -- 圆形
// GradientDrawable unSelectedGradientDrawable = new GradientDrawable();
// unSelectedGradientDrawable.setShape(GradientDrawable.OVAL);
// unSelectedGradientDrawable.setColor(Color.GRAY);
// unSelectedGradientDrawable.setSize(dp2px(5), dp2px(5));
// unSelectedGradientDrawable.setCornerRadius(dp2px(5) / 2);
// mUnselectedDrawable = new LayerDrawable(new Drawable[]{unSelectedGradientDrawable});
}
indicatorMargin = dp2px(4);
int marginLeft = dp2px(16);
int marginRight = dp2px(0);
int marginBottom = dp2px(11);
int gravity = GravityCompat.START;
int o = a.getInt(R.styleable.BannerLayout_orientation, 0);
int orientation = 0;
if (o == 0) {
orientation = OrientationHelper.HORIZONTAL;
} else if (o == 1) {
orientation = OrientationHelper.VERTICAL;
}
a.recycle();
//轮播图部分
mRecyclerView = new RecyclerView(context);
LayoutParams vpLayoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
addView(mRecyclerView, vpLayoutParams);
mLayoutManager = new BannerLayoutManager(getContext(), orientation);
mLayoutManager.setItemSpace(itemSpace);
mLayoutManager.setCenterScale(centerScale);
mLayoutManager.setMoveSpeed(moveSpeed);
mRecyclerView.setLayoutManager(mLayoutManager);
new CenterSnapHelper().attachToRecyclerView(mRecyclerView);
//指示器部分
indicatorContainer = new RecyclerView(context);
LinearLayoutManager indicatorLayoutManager = new LinearLayoutManager(context, orientation, false);
indicatorContainer.setLayoutManager(indicatorLayoutManager);
indicatorAdapter = new IndicatorAdapter();
indicatorContainer.setAdapter(indicatorAdapter);
LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
// params.gravity = Gravity.BOTTOM | gravity;
params.gravity = Gravity.BOTTOM | CENTER;;
// params.setMargins(marginLeft, 0, marginRight, marginBottom);
params.setMargins(0, 0, 0, 0);
addView(indicatorContainer, params);
if (!showIndicator) {
indicatorContainer.setVisibility(GONE);
}
}
// 设置是否禁止滚动播放
public void setAutoPlaying(boolean isAutoPlaying) {
this.isAutoPlaying = isAutoPlaying;
setPlaying(this.isAutoPlaying);
}
public boolean isPlaying() {
return isPlaying;
}
//设置是否显示指示器
public void setShowIndicator(boolean showIndicator) {
this.showIndicator = showIndicator;
indicatorContainer.setVisibility(showIndicator ? VISIBLE : GONE);
}
//设置当前图片缩放系数
public void setCenterScale(float centerScale) {
this.centerScale = centerScale;
mLayoutManager.setCenterScale(centerScale);
}
//设置跟随手指的移动速度
public void setMoveSpeed(float moveSpeed) {
this.moveSpeed = moveSpeed;
mLayoutManager.setMoveSpeed(moveSpeed);
}
//设置图片间距
public void setItemSpace(int itemSpace) {
this.itemSpace = itemSpace;
mLayoutManager.setItemSpace(itemSpace);
}
/**
* 设置轮播间隔时间
*
* @param autoPlayDuration 时间毫秒
*/
public void setAutoPlayDuration(int autoPlayDuration) {
this.autoPlayDuration = autoPlayDuration;
}
public void setOrientation(int orientation) {
mLayoutManager.setOrientation(orientation);
}
/**
* 设置是否自动播放(上锁)
*
* @param playing 开始播放
*/
protected synchronized void setPlaying(boolean playing) {
if (isAutoPlaying && hasInit) {
if (!isPlaying && playing) {
mHandler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration);
isPlaying = true;
} else if (isPlaying && !playing) {
mHandler.removeMessages(WHAT_AUTO_PLAY);
isPlaying = false;
}
}
}
/**
* 设置轮播数据集
*/
public void setAdapter(RecyclerView.Adapter adapter) {
hasInit = false;
mRecyclerView.setAdapter(adapter);
bannerSize = adapter.getItemCount();
mLayoutManager.setInfinite(bannerSize >= 3);
setPlaying(true);
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (dx != 0) {
setPlaying(false);
}
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
int first = mLayoutManager.getCurrentPosition();
Log.d("xxx", "onScrollStateChanged");
if (currentIndex != first) {
currentIndex = first;
}
if (newState == SCROLL_STATE_IDLE) {
setPlaying(true);
}
refreshIndicator();
}
});
hasInit = true;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
setPlaying(false);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
setPlaying(true);
break;
}
return super.dispatchTouchEvent(ev);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setPlaying(true);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
setPlaying(false);
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
if (visibility == VISIBLE) {
setPlaying(true);
} else {
setPlaying(false);
}
}
/**
* 标示点适配器
*/
protected class IndicatorAdapter extends RecyclerView.Adapter {
int currentPosition = 0;
public void setPosition(int currentPosition) {
this.currentPosition = currentPosition;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ImageView bannerPoint = new ImageView(getContext());
RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
lp.setMargins(indicatorMargin, indicatorMargin, indicatorMargin, indicatorMargin);
bannerPoint.setLayoutParams(lp);
return new RecyclerView.ViewHolder(bannerPoint) {
};
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
ImageView bannerPoint = (ImageView) holder.itemView;
bannerPoint.setImageDrawable(currentPosition == position ? mSelectedDrawable : mUnselectedDrawable);
}
@Override
public int getItemCount() {
return bannerSize;
}
}
protected int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
Resources.getSystem().getDisplayMetrics());
}
/**
* 改变导航的指示点
*/
protected synchronized void refreshIndicator() {
if (showIndicator && bannerSize > 1) {
indicatorAdapter.setPosition(currentIndex % bannerSize);
indicatorAdapter.notifyDataSetChanged();
}
}
public interface OnBannerItemClickListener {
void onItemClick(int position);
}
}
图二的第二个效果:
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.GravityCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.example.library.R;
import com.example.library.banner.layoutmanager.BannerLayoutManager;
import com.example.library.banner.layoutmanager.CenterSnapHelper;
import static android.view.Gravity.CENTER;
import static android.widget.AbsListView.OnScrollListener.SCROLL_STATE_IDLE;
public class BannerLayout2 extends FrameLayout {
private int autoPlayDuration;//刷新间隔时间
private boolean showIndicator;//是否显示指示器
private RecyclerView indicatorContainer;
private Drawable mSelectedDrawable;
private Drawable mUnselectedDrawable;
private IndicatorAdapter indicatorAdapter;
private int indicatorMargin;//指示器间距
private RecyclerView mRecyclerView;
private BannerLayoutManager mLayoutManager;
private int WHAT_AUTO_PLAY = 1000;
private boolean hasInit;
private int bannerSize = 1;
private int currentIndex;
private boolean isPlaying = false;
private boolean isAutoPlaying = true;
int itemSpace;
float centerScale;
float moveSpeed;
protected Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.what == WHAT_AUTO_PLAY) {
if (currentIndex == mLayoutManager.getCurrentPosition()) {
++currentIndex;
mRecyclerView.smoothScrollToPosition(currentIndex);
mHandler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration);
refreshIndicator();
}
}
return false;
}
});
public BannerLayout2(Context context) {
this(context, null);
}
public BannerLayout2(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BannerLayout2(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context, attrs);
}
protected void initView(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BannerLayout);
showIndicator = a.getBoolean(R.styleable.BannerLayout_showIndicator, true);
autoPlayDuration = a.getInt(R.styleable.BannerLayout_interval, 4000);
isAutoPlaying = a.getBoolean(R.styleable.BannerLayout_autoPlaying, true);
itemSpace = a.getInt(R.styleable.BannerLayout_itemSpace, 20);
centerScale = a.getFloat(R.styleable.BannerLayout_centerScale, 1.2f);
moveSpeed = a.getFloat(R.styleable.BannerLayout_moveSpeed, 1.0f);
if (mSelectedDrawable == null) {
//绘制默认选中状态图形-- 自定义椭圆形指示器,圆角矩形
GradientDrawable drawable = (GradientDrawable) context.getResources().getDrawable(R.drawable.bg521);
// drawable .setColor(Color.parseColor("#ff4400"));
mSelectedDrawable = new LayerDrawable(new Drawable[]{drawable});
//绘制默认选中状态图形 -- 圆形
// GradientDrawable selectedGradientDrawable = new GradientDrawable();
// selectedGradientDrawable.setShape(GradientDrawable.OVAL);
// selectedGradientDrawable.setColor(Color.RED);
// selectedGradientDrawable.setSize(dp2px(5), dp2px(5));
// selectedGradientDrawable.setCornerRadius(dp2px(5) / 2);
// mSelectedDrawable = new LayerDrawable(new Drawable[]{selectedGradientDrawable});
}
if (mUnselectedDrawable == null) {
//绘制默认未选中状态图形 -- 自定义椭圆形指示器,圆角矩形
GradientDrawable drawable = (GradientDrawable) context.getResources().getDrawable(R.drawable.bg522);
// drawable .setColor(Color.parseColor("#ff4400"));
mUnselectedDrawable = new LayerDrawable(new Drawable[]{drawable});
//绘制默认未选中状态图形 -- 圆形
// GradientDrawable unSelectedGradientDrawable = new GradientDrawable();
// unSelectedGradientDrawable.setShape(GradientDrawable.OVAL);
// unSelectedGradientDrawable.setColor(Color.GRAY);
// unSelectedGradientDrawable.setSize(dp2px(5), dp2px(5));
// unSelectedGradientDrawable.setCornerRadius(dp2px(5) / 2);
// mUnselectedDrawable = new LayerDrawable(new Drawable[]{unSelectedGradientDrawable});
}
// indicatorMargin = dp2px(4);
indicatorMargin = (int) -0.2;
int marginLeft = dp2px(16);
int marginRight = dp2px(0);
int marginBottom = dp2px(11);
int gravity = GravityCompat.START;
int o = a.getInt(R.styleable.BannerLayout_orientation, 0);
int orientation = 0;
if (o == 0) {
orientation = OrientationHelper.HORIZONTAL;
} else if (o == 1) {
orientation = OrientationHelper.VERTICAL;
}
a.recycle();
//轮播图部分
mRecyclerView = new RecyclerView(context);
LayoutParams vpLayoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
addView(mRecyclerView, vpLayoutParams);
mLayoutManager = new BannerLayoutManager(getContext(), orientation);
mLayoutManager.setItemSpace(itemSpace);
mLayoutManager.setCenterScale(centerScale);
mLayoutManager.setMoveSpeed(moveSpeed);
mRecyclerView.setLayoutManager(mLayoutManager);
new CenterSnapHelper().attachToRecyclerView(mRecyclerView);
//指示器部分
indicatorContainer = new RecyclerView(context);
LinearLayoutManager indicatorLayoutManager = new LinearLayoutManager(context, orientation, false);
indicatorContainer.setLayoutManager(indicatorLayoutManager);
indicatorAdapter = new IndicatorAdapter();
indicatorContainer.setAdapter(indicatorAdapter);
LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
// params.gravity = Gravity.BOTTOM | gravity;//指示器位置居左显示,可以设置上下左右的距离
// params.gravity = Gravity.BOTTOM | RIGHT;//设置指示器居右显示
// params.gravity = Gravity.BOTTOM | LEFT;//设置指示器居左显示
params.gravity = Gravity.BOTTOM | CENTER;//设置指示器居中显示
// params.setMargins(marginLeft, 0, marginRight, marginBottom);
params.setMargins(0, 0, 0, marginBottom);
// params.setMargins(0, 0, 0, 0);
addView(indicatorContainer, params);
if (!showIndicator) {
indicatorContainer.setVisibility(GONE);
}
}
// 设置是否禁止滚动播放
public void setAutoPlaying(boolean isAutoPlaying) {
this.isAutoPlaying = isAutoPlaying;
setPlaying(this.isAutoPlaying);
}
public boolean isPlaying() {
return isPlaying;
}
//设置是否显示指示器
public void setShowIndicator(boolean showIndicator) {
this.showIndicator = showIndicator;
indicatorContainer.setVisibility(showIndicator ? VISIBLE : GONE);
}
//设置当前图片缩放系数
public void setCenterScale(float centerScale) {
this.centerScale = centerScale;
mLayoutManager.setCenterScale(centerScale);
}
//设置跟随手指的移动速度
public void setMoveSpeed(float moveSpeed) {
this.moveSpeed = moveSpeed;
mLayoutManager.setMoveSpeed(moveSpeed);
}
//设置图片间距
public void setItemSpace(int itemSpace) {
this.itemSpace = itemSpace;
mLayoutManager.setItemSpace(itemSpace);
}
/**
* 设置轮播间隔时间
*
* @param autoPlayDuration 时间毫秒
*/
public void setAutoPlayDuration(int autoPlayDuration) {
this.autoPlayDuration = autoPlayDuration;
}
public void setOrientation(int orientation) {
mLayoutManager.setOrientation(orientation);
}
/**
* 设置是否自动播放(上锁)
*
* @param playing 开始播放
*/
protected synchronized void setPlaying(boolean playing) {
if (isAutoPlaying && hasInit) {
if (!isPlaying && playing) {
mHandler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration);
isPlaying = true;
} else if (isPlaying && !playing) {
mHandler.removeMessages(WHAT_AUTO_PLAY);
isPlaying = false;
}
}
}
/**
* 设置轮播数据集
*/
public void setAdapter(RecyclerView.Adapter adapter) {
hasInit = false;
mRecyclerView.setAdapter(adapter);
bannerSize = adapter.getItemCount();
mLayoutManager.setInfinite(bannerSize >= 3);
setPlaying(true);
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (dx != 0) {
setPlaying(false);
}
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
int first = mLayoutManager.getCurrentPosition();
Log.d("xxx", "onScrollStateChanged");
if (currentIndex != first) {
currentIndex = first;
}
if (newState == SCROLL_STATE_IDLE) {
setPlaying(true);
}
refreshIndicator();
}
});
hasInit = true;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
setPlaying(false);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
setPlaying(true);
break;
}
return super.dispatchTouchEvent(ev);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setPlaying(true);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
setPlaying(false);
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
if (visibility == VISIBLE) {
setPlaying(true);
} else {
setPlaying(false);
}
}
/**
* 标示点适配器
*/
protected class IndicatorAdapter extends RecyclerView.Adapter {
int currentPosition = 0;
public void setPosition(int currentPosition) {
this.currentPosition = currentPosition;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ImageView bannerPoint = new ImageView(getContext());
RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
// lp.setMargins(indicatorMargin, indicatorMargin, indicatorMargin, indicatorMargin);
lp.setMargins(0, 0, 0, 0);
bannerPoint.setLayoutParams(lp);
return new RecyclerView.ViewHolder(bannerPoint) {
};
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
ImageView bannerPoint = (ImageView) holder.itemView;
bannerPoint.setImageDrawable(currentPosition == position ? mSelectedDrawable : mUnselectedDrawable);
}
@Override
public int getItemCount() {
return bannerSize;
}
}
protected int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
Resources.getSystem().getDisplayMetrics());
}
/**
* 改变导航的指示点
*/
protected synchronized void refreshIndicator() {
if (showIndicator && bannerSize > 1) {
indicatorAdapter.setPosition(currentIndex % bannerSize);
indicatorAdapter.notifyDataSetChanged();
}
}
public interface OnBannerItemClickListener {
void onItemClick(int position);
}
}
bg521.xml:
<?xml version="1.0" encoding="utf-8"?>
<!-- 矩形圆角+左右两边为一个圆弧 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
android:useLevel="true">
<size
android:width="18dp"
android:height="1.1dp" />
<solid android:color="#ff00ff" />
<!-- 圆角半径是高度的一般就是一个圆弧了 -->
<corners android:radius="20dp" />
</shape>
图二的第二个效果的布局:
<com.example.library.banner.BannerLayout2
android:id="@+id/recycler2"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="130dp"
app:autoPlaying="true"
app:centerScale="1.3"
app:itemSpace="20"
app:moveSpeed="1.0"/>
4.布局及属性:
attr.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="interval" format="integer"/>
<attr name="showIndicator" format="boolean"/>
<attr name="orientation" format="enum">
<enum name="horizontal" value="0"/>
<enum name="vertical" value="1"/>
</attr>
<attr name="autoPlaying" format="boolean"/>
<declare-styleable name="RecyclerViewBannerBase">
<attr name="interval"/>
<attr name="showIndicator" />
<attr name="orientation" />
<attr name="autoPlaying"/>
<attr name="indicatorSelectedSrc" format="color|reference"/>
<attr name="indicatorUnselectedSrc" format="color|reference"/>
<attr name="indicatorSpace" format="dimension|reference"/>
<attr name="indicatorMarginLeft" format="dimension|reference"/>
<attr name="indicatorMarginRight" format="dimension|reference"/>
<attr name="indicatorMarginBottom" format="dimension|reference"/>
<attr name="indicatorGravity" format="enum">
<enum name="left" value="0"/>
<enum name="center" value="1"/>
<enum name="right" value="2"/>
</attr>
</declare-styleable>
<declare-styleable name="BannerLayout">
<attr name="interval" />
<attr name="showIndicator" />
<attr name="orientation" />
<attr name="autoPlaying"/>
<attr name="itemSpace" format="integer"/>
<attr name="centerScale" format="float"/>
<attr name="moveSpeed" format="float"/>
</declare-styleable>
</resources>
主布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.renny.recyclerbanner.MainActivity">
<com.example.library.banner.BannerLayout
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="200dp"
app:autoPlaying="true"
app:centerScale="1.3"
app:itemSpace="20"
app:moveSpeed="1.8"/>
<com.example.library.banner.BannerLayout
android:id="@+id/recycler_ver"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginTop="10dp"
app:orientation="vertical"
app:showIndicator="false"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:onClick="jump"
android:text="查看基础版"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:onClick="jumpOverFlying"
android:text="查看层叠版"/>
</LinearLayout>
自定义默认的椭圆形背景xml:
<?xml version="1.0" encoding="utf-8"?>
<!-- 矩形圆角+左右两边为一个圆弧 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
android:useLevel="true">
<size
android:width="8dp"
android:height="3dp" />
<solid android:color="#00ff00" />
<!-- 圆角半径是高度的一般就是一个圆弧了 -->
<corners android:radius="20dp" />
</shape>
自定义选中椭圆形背景xml:
<?xml version="1.0" encoding="utf-8"?>
<!-- 矩形圆角+左右两边为一个圆弧 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
android:useLevel="true">
<size
android:width="8dp"
android:height="3dp" />
<solid android:color="#ff00ff" />
<!-- 圆角半径是高度的一般就是一个圆弧了 -->
<corners android:radius="20dp" />
</shape>
5.适配器:
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.example.library.banner.BannerLayout;
import com.renny.recyclerbanner.R;
import java.util.List;
/**
* Created by test on 2017/11/22.
*/
public class WebBannerAdapter extends RecyclerView.Adapter<WebBannerAdapter.MzViewHolder> {
private Context context;
private List<String> urlList;
private BannerLayout.OnBannerItemClickListener onBannerItemClickListener;
public WebBannerAdapter(Context context, List<String> urlList) {
this.context = context;
this.urlList = urlList;
}
public void setOnBannerItemClickListener(BannerLayout.OnBannerItemClickListener onBannerItemClickListener) {
this.onBannerItemClickListener = onBannerItemClickListener;
}
@Override
public WebBannerAdapter.MzViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new MzViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_image, parent, false));
}
@Override
public void onBindViewHolder(WebBannerAdapter.MzViewHolder holder, final int position) {
if (urlList == null || urlList.isEmpty())
return;
final int P = position % urlList.size();
String url = urlList.get(P);
ImageView img = (ImageView) holder.imageView;
Glide.with(context).load(url).into(img);
img.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onBannerItemClickListener != null) {
onBannerItemClickListener.onItemClick(P);
}
}
});
}
@Override
public int getItemCount() {
if (urlList != null) {
return urlList.size();
}
return 0;
}
class MzViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
MzViewHolder(View itemView) {
super(itemView);
imageView = (ImageView) itemView.findViewById(R.id.image);
}
}
}
适配器布局:(使用CardView来实现轮播图图片圆角效果,注意适配器布局的高度和banner布局的高度是否贴合)
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="250dp"
android:layout_height="100dp"
app:cardCornerRadius="5dp">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"/>
</android.support.v7.widget.CardView>
6.注意:
若需要设置自定义的指示器圆形、圆角矩形、椭圆形等可以在自定义的Banner中设置,代码已经添加了注释,其中包括设置指示器的位置居左、居中、居右等等。
//绘制默认选中状态图形-- 自定义椭圆形指示器,圆角矩形
GradientDrawable drawable = (GradientDrawable) context.getResources().getDrawable(R.drawable.bg52);
// drawable .setColor(Color.parseColor("#ff4400"));
mSelectedDrawable = new LayerDrawable(new Drawable[]{drawable});
//绘制默认选中状态图形 -- 圆形
// GradientDrawable selectedGradientDrawable = new GradientDrawable();
// selectedGradientDrawable.setShape(GradientDrawable.OVAL);
// selectedGradientDrawable.setColor(Color.RED);
// selectedGradientDrawable.setSize(dp2px(5), dp2px(5));
// selectedGradientDrawable.setCornerRadius(dp2px(5) / 2);
// mSelectedDrawable = new LayerDrawable(new Drawable[]{selectedGradientDrawable});
//绘制默认未选中状态图形 -- 自定义椭圆形指示器,圆角矩形
GradientDrawable drawable = (GradientDrawable) context.getResources().getDrawable(R.drawable.bg53);
// drawable .setColor(Color.parseColor("#ff4400"));
mUnselectedDrawable = new LayerDrawable(new Drawable[]{drawable});
//绘制默认未选中状态图形 -- 圆形
// GradientDrawable unSelectedGradientDrawable = new GradientDrawable();
// unSelectedGradientDrawable.setShape(GradientDrawable.OVAL);
// unSelectedGradientDrawable.setColor(Color.GRAY);
// unSelectedGradientDrawable.setSize(dp2px(5), dp2px(5));
// unSelectedGradientDrawable.setCornerRadius(dp2px(5) / 2);
// mUnselectedDrawable = new LayerDrawable(new Drawable[]{unSelectedGradientDrawable});
LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
// params.gravity = Gravity.BOTTOM | gravity;
params.gravity = Gravity.BOTTOM | CENTER;//设置指示器据中显示
// params.setMargins(marginLeft, 0, marginRight, marginBottom);
params.setMargins(0, 0, 0, 0);
addView(indicatorContainer, params);
indicatorMargin = dp2px(4);
int marginLeft = dp2px(16);
int marginRight = dp2px(0);
int marginBottom = dp2px(11);
int gravity = GravityCompat.START;
...
LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.BOTTOM | gravity;//指示器位置居左显示,可以设置上下左右的距离
// params.gravity = Gravity.BOTTOM | RIGHT;//设置指示器居右显示
// params.gravity = Gravity.BOTTOM | LEFT;//设置指示器居左显示
// params.gravity = Gravity.BOTTOM | CENTER;//设置指示器居中显示
params.setMargins(marginLeft, 0, marginRight, marginBottom);
// params.setMargins(0, 0, 0, 0);
addView(indicatorContainer, params);