最近在学习撸撸的代码,发现他的轮播写法很独特,但是有bug,就重新修改了一下,现在支持左右点击和圆点自定义。
BannerAdapter:(注意适配器自己看ImageView和onclick的自己项目的写法~)
package com.example.p029_banner_lunbo.adapter;
import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.example.p029_banner_lunbo.bannerutils.BannerView;
import com.example.p029_banner_lunbo.domain.Biaoge_listBean;
import java.util.List;
public class BannerAdapter extends BannerView.Adapter {
private List<Biaoge_listBean> mAdList;
private Object mReceiver;
public BannerAdapter(Object receiver, List<Biaoge_listBean> items) {
mReceiver = receiver;
mAdList = items;
}
@Override
public int getRealCount() {
return mAdList.size();
}
@Override
public Object instantiateItem(final ViewGroup container, int position) {
int size = mAdList.size();
if (size == 0) {
return null;
}
final int pos = position % size;
final Biaoge_listBean item = mAdList.get(pos);
ViewGroup.LayoutParams p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
ImageView iv = new ImageView(container.getContext());
iv.setScaleType(ImageView.ScaleType.FIT_XY);
iv.setAdjustViewBounds(true);
container.addView(iv, p);
iv.setBackgroundResource(item.getImg_url());
// GlideUtil.display(container.getContext(), iv, item.getPic_url(),
// GlideOptionsFactory.get(GlideOptionsFactory.Type.RADIUS));
iv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// MobEventHelper.onEvent(container.getContext(), "UI2_ec_index_banner");
// MobEventHelper.onEvent(container.getContext(), "UI2_ec_index_banner_" + String.valueOf(pos + 1));
if (container.getContext() instanceof Activity) {
Activity act = (Activity) container.getContext();
//跳转bufen
// HiosHelper.resolveAd(act, mReceiver, item.getUrl());
}
}
});
return iv;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
DotIndicatorView:(圆点的方法大部分都public了,大家可以DotIndicatorView.自定义~)
package com.example.p029_banner_lunbo.bannerutils;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
/**
* 圆点导航
* @author geek
*
*/
public class DotIndicatorView extends View {
private Paint mPaint;
private int mPadding;
private int mCircleRadius;
private int mCurrentColor;
private int mNormalColor;
private int mCount = 3;
private int mCurrent;
public DotIndicatorView(Context context) {
super(context);
initView();
}
public DotIndicatorView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DotIndicatorView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
private void initView() {
DisplayMetrics dm = getResources().getDisplayMetrics();
mPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, dm);
mCircleRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, dm);
mCurrentColor = Color.WHITE;
mNormalColor = Color.argb(88, 91, 91, 91);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = mCircleRadius * 2 * mCount + mPadding * (mCount -1);
int height = mCircleRadius * 2;
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
for (int i = 0; i < mCount; i++) {
canvas.save();
canvas.translate((mCircleRadius * 2 + mPadding) * i, 0);
if(i == mCurrent) mPaint.setColor(mCurrentColor);
else mPaint.setColor(mNormalColor);
canvas.drawCircle(mCircleRadius , mCircleRadius, mCircleRadius, mPaint);
canvas.restore();
}
}
/**
* 创建导航
* @param count 个数
*/
public void create(int count) {
mCount = count;
requestLayout();
invalidate();
}
/**
* 选中当前
* @param position 选中位置
*/
public void current(int position) {
mCurrent = position;
invalidate();
}
/**
* 获取当前选中的位置
* @return
*/
public int current() {
return mCurrent;
}
}
BannerView:(自定义的View~)
package com.example.p029_banner_lunbo.bannerutils;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import com.example.p029_banner_lunbo.R;
import java.lang.ref.WeakReference;
public class BannerView extends FrameLayout {
private static final int MSG_RUN = 1;
private ViewPager mViewPager;
/**
* 导航的小点
*/
private DotIndicatorView mIndicator;
private Adapter mAdapter;
/**
* 是否处于滑动的状态
*/
private boolean isScrolling;
private int mIndicatorPosition; // center_hori left
/**
* 是否显示indicator
*/
private boolean isShowIndicator = true;
private boolean isTouch;
private Handler mHandler;
private BannerViewHelper mHelper;
private int mScrollTime;
public BannerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BannerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.BannerView,
defStyle, 0);
mIndicatorPosition = ta.getInt(R.styleable.BannerView_indicator_position, 0);
isShowIndicator = ta.getBoolean(R.styleable.BannerView_indicator_visible, true);
mScrollTime = ta.getInteger(R.styleable.BannerView_scroll_time, 3000);
isScrolling = ta.getBoolean(R.styleable.BannerView_auto_start, false);
ta.recycle();
initView(context);
}
private void initView(Context context) {
mViewPager = new ViewPager(context);
mViewPager.addOnPageChangeListener(mOnPageChangeListener);
addView(mViewPager);//, viewPagerParams);
mHandler = new H(mViewPager);
mIndicator = new DotIndicatorView(context);
LayoutParams indicatorParams =
new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
if (mIndicatorPosition == 0) {
indicatorParams.gravity = Gravity.BOTTOM | Gravity.LEFT;
} else if (mIndicatorPosition == 1) {
indicatorParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
} else if (mIndicatorPosition == 2) {
indicatorParams.gravity = Gravity.BOTTOM | Gravity.RIGHT;
}
indicatorParams.bottomMargin = 20;
if (!isShowIndicator) {
return;
}
addView(mIndicator, indicatorParams);
}
@Override
protected void onAttachedToWindow() {
if (isScrolling) {
startScroll();
}
super.onAttachedToWindow();
mHelper = new BannerViewHelper(this);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mHelper != null) {
mHelper.resolveTouchConflict(ev);
}
return super.dispatchTouchEvent(ev);
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}
@Override
protected android.view.ViewGroup.LayoutParams generateLayoutParams(
android.view.ViewGroup.LayoutParams p) {
return new LayoutParams(p);
}
@Override
protected boolean checkLayoutParams(android.view.ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
private OnPageChangeListener mOnPageChangeListener = new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
int relCount = mAdapter.getRealCount();
if (relCount <= 0) {
mIndicator.current(0);
} else {
mIndicator.current(position % relCount);
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
isTouch = arg0 == ViewPager.SCROLL_STATE_DRAGGING;
if (arg0 == ViewPager.SCROLL_STATE_IDLE && isScrolling) {
mHandler.removeMessages(MSG_RUN);
Message msg = mHandler.obtainMessage(MSG_RUN, isScrolling ? 1 : 0, isTouch ? 1 : 0);
mHandler.sendMessageDelayed(msg, mScrollTime);
}
}
};
/**
* 开始自动滚动
*/
public void startScroll() {
mHandler.removeMessages(MSG_RUN);
isScrolling = true;
Message msg = mHandler.obtainMessage(MSG_RUN, 1, isTouch ? 1 : 0);
mHandler.sendMessageDelayed(msg, mScrollTime);
}
/**
* 停止自动滚动
*/
public void stopScroll() {
isScrolling = false;
if (mHandler != null) {
mHandler.removeMessages(MSG_RUN);
}
}
@Override
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
bundle.putBoolean("scroll", isScrolling);
bundle.putParcelable("state", super.onSaveInstanceState());
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
Bundle bundle = (Bundle) state;
isScrolling = bundle.getBoolean("scroll");
state = bundle.getParcelable("state");
if (state != null) {
super.onRestoreInstanceState(state);
}
}
// @Override
// protected void onAttachedToWindow() {
// super.onAttachedToWindow();
// if(isScrolling) mHandler.sendEmptyMessage(MSG_RUN);
// }
@Override
protected void onDetachedFromWindow() {
mHandler.removeMessages(MSG_RUN);
super.onDetachedFromWindow();
}
/**
* 设置banner的数据集合
*/
public void setAdapter(Adapter adapter) {
mAdapter = adapter;
mViewPager.setAdapter(adapter);
mIndicator.create(adapter.getRealCount());
}
/**
* 获取adapter
*/
public Adapter getAdapter() {
return mAdapter;
}
public int getCurrent() {
return mViewPager.getCurrentItem() + 1;
}
public void setCurrent(int current) {
mViewPager.setCurrentItem(current);
}
private static class H extends Handler {
private WeakReference<ViewPager> mViewPager;
public H(ViewPager pager) {
mViewPager = new WeakReference<>(pager);
}
public void handleMessage(Message msg) {
if (mViewPager.get() == null) return;
boolean isScrolling = msg.arg1 == 1;
boolean isTouch = msg.arg2 == 1;
if (msg.what == MSG_RUN && isScrolling) {
if (!isTouch) {
int pos = mViewPager.get().getCurrentItem() + 1;
mViewPager.get().setCurrentItem(pos);
// sendEmptyMessageDelayed(MSG_RUN, 3000);
} else {
removeMessages(MSG_RUN);
}
}
}
}
public static abstract class Adapter extends PagerAdapter {
@Override
public final int getCount() {
return Integer.MAX_VALUE;
}
/**
* 获取真实的数据统计
*
* @return
*/
public abstract int getRealCount();
@Override
public final boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
public Object getItem(int position) {
return position;
}
}
}
BannerViewHelper:(用于解决BannerView和SwipeRefreshLayout的冲突)
package com.example.p029_banner_lunbo.bannerutils;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewGroup;
/**
* 用于解决BannerView和SwipeRefreshLayout的冲突
* @author geek
*
*/
public class BannerViewHelper {
private BannerView mBannerView;
private SwipeRefreshLayout mSwipeRefreshLayout;
private VelocityTracker mVelocityTracker;
private float mAccuracy = 1.f;
public BannerViewHelper(BannerView bannerView) {
mBannerView = bannerView;
mSwipeRefreshLayout = findSwipeRefreshLayout();
}
public BannerViewHelper(BannerView bannerView, float accuracy) {
this(bannerView);
mAccuracy = accuracy;
}
public void resolveTouchConflict(MotionEvent event) {
if(mSwipeRefreshLayout == null) return;
setupVelocityTracker(event);
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
if(!mSwipeRefreshLayout.isEnabled()) return;
mVelocityTracker.computeCurrentVelocity(1000);
if(Math.abs(mVelocityTracker.getXVelocity()) >
Math.abs(mVelocityTracker.getYVelocity()) * mAccuracy) {
mSwipeRefreshLayout.setEnabled(false);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mSwipeRefreshLayout.setEnabled(true);
recycleVelocityTracker();
default:
break;
}
}
private void setupVelocityTracker(MotionEvent event) {
if(mVelocityTracker == null) mVelocityTracker = VelocityTracker.obtain();
mVelocityTracker.addMovement(event);
}
private void recycleVelocityTracker() {
if(mVelocityTracker != null) {
mVelocityTracker.clear();
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
private SwipeRefreshLayout findSwipeRefreshLayout() {
ViewGroup parent = (ViewGroup) mBannerView.getParent();
while(parent != null && parent.getId() != android.R.id.content) {
if(parent instanceof SwipeRefreshLayout) return (SwipeRefreshLayout) parent;
parent = (ViewGroup) parent.getParent();
}
return null;
}
}
xml布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ccc"
android:orientation="vertical">
<com.example.p029_banner_lunbo.bannerutils.BannerView
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="400dp"
app:indicator_position="center"
app:indicator_visible="false"
app:scroll_time="8000" />
</LinearLayout>
<TextView
android:id="@+id/tv_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/icon_left" />
<TextView
android:id="@+id/tv_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:background="@drawable/icon_right" />
</RelativeLayout>
调用方法:
tv_left = (TextView) findViewById(R.id.tv_left);
tv_left.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//左←
ToastUtil.showToastShort(MainActivity.this, "左");
mBannerView.setCurrent(mBannerView.getCurrent() - 2);
}
});
tv_right = (TextView) findViewById(R.id.tv_right);
tv_right.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//右→
ToastUtil.showToastShort(MainActivity.this, "右");
mBannerView.setCurrent(mBannerView.getCurrent());
}
});
mBannerView = (BannerView) findViewById(R.id.banner);
Data1();
mBannerView.setAdapter(new BannerAdapter(this, mList1));
mBannerView.stopScroll();
mBannerView.startScroll();
代码已经整理好,效果如下图:
图1:
图2:
图2:
地址:https://github.com/geeklx/MyApplication/tree/master/p029_banner_lunbo
附: