做一个引导页又要动画又要动态更新,心累,本着能复制粘贴绝不敲代码的原则 ,把 BannerLayout做首页轮播图的一个组件改了,原作者谁也不知道,直接在旧项目上改的,改完发现和自己写事件差不多,但是敲得代码少啊,也学习人家代码了。
上代码 BannerLayout 就是加了个Adapter
public class BannerLayout extends RelativeLayout {
private ViewPager pager;
//指示器容器
private LinearLayout indicatorContainer;
private Drawable unSelectedDrawable;
private Drawable selectedDrawable;
private int WHAT_AUTO_PLAY = 1000;
private boolean isAutoPlay = true;
private int itemCount;
private int selectedIndicatorColor = 0xffff0000;
private int unSelectedIndicatorColor = 0x88888888;
private Shape indicatorShape = Shape.oval;
private int selectedIndicatorHeight = 3;
private int selectedIndicatorWidth = 3;
private int unSelectedIndicatorHeight = 3;
private int unSelectedIndicatorWidth = 3;
private Position indicatorPosition = Position.centerBottom;
private int autoPlayDuration = 4000;
private int scrollDuration = 900;
private int indicatorSpace = 2;
private int indicatorMargin = 5;
private int currentPosition;
private ImageLoader imageLoader;
private Adapter adapter;
private enum Shape {
rect, oval
}
private enum Position {
centerBottom,
rightBottom,
leftBottom,
centerTop,
rightTop,
leftTop
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
startAutoPlay();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
stopAutoPlay();
}
private OnBannerItemClickListener onBannerItemClickListener;
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.what == WHAT_AUTO_PLAY) {
if (pager != null && isAutoPlay) {
pager.setCurrentItem(pager.getCurrentItem() + 1, true);
handler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration);
}
}
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);
init(attrs, defStyleAttr);
}
private void init(AttributeSet attrs, int defStyle) {
TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.BannerLayoutStyle, defStyle, 0);
selectedIndicatorColor = array.getColor(R.styleable.BannerLayoutStyle_selectedIndicatorColor, selectedIndicatorColor);
unSelectedIndicatorColor = array.getColor(R.styleable.BannerLayoutStyle_unSelectedIndicatorColor, unSelectedIndicatorColor);
int shape = array.getInt(R.styleable.BannerLayoutStyle_indicatorShape, Shape.oval.ordinal());
for (Shape shape1 : Shape.values()) {
if (shape1.ordinal() == shape) {
indicatorShape = shape1;
break;
}
}
selectedIndicatorHeight = (int) array.getDimension(R.styleable.BannerLayoutStyle_selectedIndicatorHeight, selectedIndicatorHeight);
selectedIndicatorWidth = (int) array.getDimension(R.styleable.BannerLayoutStyle_selectedIndicatorWidth, selectedIndicatorWidth);
unSelectedIndicatorHeight = (int) array.getDimension(R.styleable.BannerLayoutStyle_unSelectedIndicatorHeight, unSelectedIndicatorHeight);
unSelectedIndicatorWidth = (int) array.getDimension(R.styleable.BannerLayoutStyle_unSelectedIndicatorWidth, unSelectedIndicatorWidth);
int position = array.getInt(R.styleable.BannerLayoutStyle_indicatorPosition, Position.centerBottom.ordinal());
for (Position position1 : Position.values()) {
if (position == position1.ordinal()) {
indicatorPosition = position1;
}
}
indicatorSpace = (int) array.getDimension(R.styleable.BannerLayoutStyle_indicatorSpace, indicatorSpace);
indicatorMargin = (int) array.getDimension(R.styleable.BannerLayoutStyle_indicatorMargin, indicatorMargin);
autoPlayDuration = array.getInt(R.styleable.BannerLayoutStyle_autoPlayDuration, autoPlayDuration);
scrollDuration = array.getInt(R.styleable.BannerLayoutStyle_scrollDuration, scrollDuration);
isAutoPlay = array.getBoolean(R.styleable.BannerLayoutStyle_isAutoPlay, isAutoPlay);
array.recycle();
//绘制未选中状态图形
LayerDrawable unSelectedLayerDrawable;
LayerDrawable selectedLayerDrawable;
GradientDrawable unSelectedGradientDrawable;
unSelectedGradientDrawable = new GradientDrawable();
//绘制选中状态图形
GradientDrawable selectedGradientDrawable;
selectedGradientDrawable = new GradientDrawable();
switch (indicatorShape) {
case rect:
unSelectedGradientDrawable.setShape(GradientDrawable.RECTANGLE);
selectedGradientDrawable.setShape(GradientDrawable.RECTANGLE);
break;
case oval:
unSelectedGradientDrawable.setShape(GradientDrawable.OVAL);
selectedGradientDrawable.setShape(GradientDrawable.OVAL);
break;
}
unSelectedGradientDrawable.setColor(unSelectedIndicatorColor);
unSelectedGradientDrawable.setSize(unSelectedIndicatorWidth, unSelectedIndicatorHeight);
unSelectedLayerDrawable = new LayerDrawable(new Drawable[]{unSelectedGradientDrawable});
unSelectedDrawable = unSelectedLayerDrawable;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.banner_unselect);
unSelectedDrawable = new BitmapDrawable(bitmap);
selectedGradientDrawable.setColor(selectedIndicatorColor);
selectedGradientDrawable.setSize(selectedIndicatorWidth, selectedIndicatorHeight);
selectedLayerDrawable = new LayerDrawable(new Drawable[]{selectedGradientDrawable});
selectedDrawable = selectedLayerDrawable;
Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.banner_select);
selectedDrawable = new BitmapDrawable(originalBitmap);
}
//添加网络图片路径
public void setViewUrls(List<String> urls) {
List<View> views = new ArrayList<>();
itemCount = urls.size();
//主要是解决当item为小于3个的时候滑动有问题,这里将其拼凑成3个以上
if (itemCount < 1) {//当item个数0
throw new IllegalStateException("item count not equal zero");
} else {
for (int i = 0; i < urls.size(); i++) {
if(i==urls.size()-1){
views.add(getView(urls.get(i), i));
}else {
views.add(getImageView(urls.get(i), i));
}
}
}
setViews(views);
}
public void setAdapter(Adapter adapter){
List<View> views = new ArrayList<>();
this.adapter=adapter;
itemCount = adapter.getItemCount();
//主要是解决当item为小于3个的时候滑动有问题,这里将其拼凑成3个以上
if (itemCount < 1) {//当item个数0
throw new IllegalStateException("item count not equal zero");
} else {
for (int i = 0; i < itemCount; i++) {
views.add(adapter.getView(i));
}
}
setViews(views);
}
@NonNull
private View getView(String url, final int position) {
View view=inflate(getContext(), R.layout.banner_view,null);
ImageView imageView = view.findViewById(R.id.imageView);
imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (onBannerItemClickListener != null) {
onBannerItemClickListener.onItemClick(position);
}
}
});
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageLoader.displayImage(getContext(), url, imageView);
return view;
}
@NonNull
private ImageView getImageView(String url, final int position) {
ImageView imageView = new ImageView(getContext());
imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (onBannerItemClickListener != null) {
onBannerItemClickListener.onItemClick(position);
}
}
});
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageLoader.displayImage(getContext(), url, imageView);
return imageView;
}
public void setImageLoader(ImageLoader imageLoader) {
this.imageLoader = imageLoader;
}
public ViewPager getPager() {
if (pager != null) {
return pager;
}
return null;
}
//添加任意View视图
public void setViews(final List<View> views) {
//初始化pager
pager = new ViewPager(getContext());
//添加viewpager到SliderLayout
addView(pager);
setSliderTransformDuration(scrollDuration);
//初始化indicatorContainer
indicatorContainer = new LinearLayout(getContext());
indicatorContainer.setGravity(Gravity.CENTER_VERTICAL);
RelativeLayout.LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
switch (indicatorPosition) {
case centerBottom:
params.addRule(RelativeLayout.CENTER_HORIZONTAL);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
break;
case centerTop:
params.addRule(RelativeLayout.CENTER_HORIZONTAL);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
break;
case leftBottom:
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
break;
case leftTop:
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
break;
case rightBottom:
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
break;
case rightTop:
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
break;
}
//设置margin
params.setMargins(indicatorMargin, indicatorMargin, indicatorMargin, indicatorMargin);
//添加指示器容器布局到SliderLayout
addView(indicatorContainer, params);
//初始化指示器,并添加到指示器容器布局
for (int i = 0; i < itemCount; i++) {
ImageView indicator = new ImageView(getContext());
indicator.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
indicator.setPadding(indicatorSpace, indicatorSpace, indicatorSpace, indicatorSpace);
indicator.setImageDrawable(unSelectedDrawable);
indicatorContainer.addView(indicator);
}
LoopPagerAdapter pagerAdapter = new LoopPagerAdapter(views);
pager.setAdapter(pagerAdapter);
//设置当前item到Integer.MAX_VALUE中间的一个值,看起来像无论是往前滑还是往后滑都是ok的
//如果不设置,用户往左边滑动的时候已经划不动了
// int targetItemPosition = Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % itemCount;
// currentPosition = targetItemPosition;
// pager.setCurrentItem(targetItemPosition);
switchIndicator(0);
pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
currentPosition = position;
switchIndicator(position % itemCount);
if(adapter!=null){
adapter.switchIndicator(position % itemCount);
}
}
});
if (isAutoPlay) {
startAutoPlay();
}
}
public void setSliderTransformDuration(int duration) {
try {
Field mScroller = ViewPager.class.getDeclaredField("mScroller");
mScroller.setAccessible(true);
FixedSpeedScroller scroller = new FixedSpeedScroller(pager.getContext(), null, duration);
mScroller.set(pager, scroller);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 开始自动轮播
*/
private void startAutoPlay() {
stopAutoPlay(); // 避免重复消息
if (isAutoPlay) {
handler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration);
}
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
if (visibility == VISIBLE) {
startAutoPlay();
} else {
stopAutoPlay();
}
}
/**
* 停止自动轮播
*/
private void stopAutoPlay() {
if (pager != null) {
pager.setCurrentItem(pager.getCurrentItem(), false);
}
if (isAutoPlay) {
handler.removeMessages(WHAT_AUTO_PLAY);
if (pager != null) {
pager.setCurrentItem(pager.getCurrentItem(), false);
}
}
}
/**
* @param autoPlay 是否自动轮播
*/
public void setAutoPlay(boolean autoPlay) {
isAutoPlay = autoPlay;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
stopAutoPlay();
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
startAutoPlay();
break;
}
return super.dispatchTouchEvent(ev);
}
/**
* 切换指示器状态
*
* @param currentPosition 当前位置
*/
private void switchIndicator(int currentPosition) {
for (int i = 0; i < indicatorContainer.getChildCount(); i++) {
((ImageView) indicatorContainer.getChildAt(i)).setImageDrawable(i == currentPosition ? selectedDrawable : unSelectedDrawable);
}
}
public void setOnBannerItemClickListener(OnBannerItemClickListener onBannerItemClickListener) {
this.onBannerItemClickListener = onBannerItemClickListener;
}
public interface OnBannerItemClickListener {
void onItemClick(int position);
}
@Override
public void onRestoreInstanceState(Parcelable state) {
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
currentPosition = savedState.currentPosition;
requestLayout();
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.currentPosition = currentPosition;
return savedState;
}
private static class SavedState extends BaseSavedState {
int currentPosition;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
currentPosition = in.readInt();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(currentPosition);
}
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
private class LoopPagerAdapter extends PagerAdapter {
private List<View> views;
LoopPagerAdapter(List<View> views) {
this.views = views;
}
@Override
public int getCount() {
//Integer.MAX_VALUE = 2147483647
// return Integer.MAX_VALUE;
return views.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
if (views.size() > 0) {
//position % view.size()是指虚拟的position会在[0,view.size())之间循环
View view = views.get(position % views.size());
if (container.equals(view.getParent())) {
container.removeView(view);
}
container.addView(view);
return view;
}
return null;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
}
public class FixedSpeedScroller extends Scroller {
private int mDuration = 1000;
public FixedSpeedScroller(Context context) {
super(context);
}
public FixedSpeedScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}
public FixedSpeedScroller(Context context, Interpolator interpolator, int duration) {
this(context, interpolator);
mDuration = duration;
}
@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 interface ImageLoader extends Serializable {
void displayImage(Context context, String path, ImageView imageView);
}
public interface Adapter{
public int getItemCount();
public View getView(int position);
public void switchIndicator(int position);
}
}
attres文件
<declare-styleable name="BannerLayoutStyle">
<attr name="selectedIndicatorColor" format="color|reference" />
<attr name="unSelectedIndicatorColor" format="color|reference" />
<attr name="indicatorShape" format="enum">
<enum name="rect" value="0" />
<enum name="oval" value="1" />
</attr>
<attr name="selectedIndicatorHeight" format="dimension|reference" />
<attr name="selectedIndicatorWidth" format="dimension|reference" />
<attr name="unSelectedIndicatorHeight" format="dimension|reference" />
<attr name="unSelectedIndicatorWidth" format="dimension|reference" />
<attr name="indicatorPosition" format="enum">
<enum name="centerBottom" value="0" />
<enum name="rightBottom" value="1" />
<enum name="leftBottom" value="2" />
<enum name="centerTop" value="3" />
<enum name="rightTop" value="4" />
<enum name="leftTop" value="5" />
</attr>
<attr name="indicatorSpace" format="dimension|reference" />
<attr name="indicatorMargin" format="dimension|reference" />
<attr name="autoPlayDuration" format="integer|reference" />
<attr name="scrollDuration" format="integer|reference" />
<attr name="isAutoPlay" format="boolean|reference"/>
</declare-styleable>
activity上使用
<com.yjf.lx.view.BannerLayout
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
app:autoPlayDuration="4000"
app:indicatorMargin="20dp"
app:indicatorPosition="centerBottom"
app:indicatorShape="rect"
app:indicatorSpace="2dp"
app:isAutoPlay="true"
app:scrollDuration="600"
app:selectedIndicatorHeight="8dp"
app:selectedIndicatorWidth="8dp"
app:unSelectedIndicatorColor="#99ffffff"
app:unSelectedIndicatorHeight="8dp"
app:unSelectedIndicatorWidth="8dp"
></com.yjf.lx.view.BannerLayout>
bannerLayout.setAutoPlay(false); //自动滑动
bannerLayout.setAdapter(new BannerLayout.Adapter() {
@Override
public int getItemCount() {
return urls.size();
}
@Override
public View getView(int position) {
View view= LayoutInflater.from(context).inflate(R.layout.banner_view,null);
ImageView imageView = view.findViewById(R.id.imageView);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
ImageDownload.initialize().imgDown(context,imageView,urls.get(position));
return view;
}
@Override
public void switchIndicator(int position) {
//显示第几个view
}
});
完事,模仿了Android经常用lis的tAdapter上面直接实现了,可以创建类来传参数,根据需求可以自己改。