android 画廊效果(中间大两边小)的无限轮播banner
ps: 项目要求做一个中间大两边小的轮播图,百度了一圈有了些灵感,分享一下心得,国际惯例先上效果图
banner.gif废话不多说,直接上关键代码:
/**
* Created by tf on 2018/12/21.
*/
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import android.widget.Scroller;
import android.widget.TextView;
import com.hexin.cardservice.R;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public class LoopViewPager extends ViewPager {
OnPageChangeListener mOuterPageChangeListener;
private LoopPagerAdapterWrapper mAdapter;
private MyHandler mHandler;
private final static int HANDLE_LOOP_MSG = 101;
private AtomicBoolean isAutoLoop = new AtomicBoolean();
public void setTxtPoints(List<TextView> txtPoints) {
this.txtPoints = txtPoints;
}
private List<TextView> txtPoints;
public void changePoints(int pos) {
if (txtPoints != null) {
for (int i = 0; i < txtPoints.size(); i++) {
if (pos == i) {
txtPoints.get(i).setBackgroundResource(R.mipmap.home_yuan_sel);
} else {
txtPoints.get(i).setBackgroundResource(R.mipmap.home_yuan);
}
}
}
}
@Override
public void setAdapter(PagerAdapter adapter) {
mAdapter = new LoopPagerAdapterWrapper(adapter);
super.setAdapter(mAdapter);
isAutoLoop.set(false);
setCurrentItem(0, false);
}
@Override
public PagerAdapter getAdapter() {
return mAdapter != null ? mAdapter.getRealAdapter() : mAdapter;
}
/**
* 获取当前真实的item
*
* @return
*/
public int getRealItem() {
return mAdapter != null ? mAdapter.toRealPosition(super.getCurrentItem()) : 0;
}
public void setCurrentItem(int item, boolean smoothScroll) {
int realItem = mAdapter.toInnerPosition(item);
super.setCurrentItem(realItem, smoothScroll);
}
@Override
public void setOnPageChangeListener(OnPageChangeListener listener) {
mOuterPageChangeListener = listener;
}
public LoopViewPager(Context context) {
super(context);
init();
}
public LoopViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
super.setOnPageChangeListener(onPageChangeListener);
try {
Field scrollerField = ViewPager.class.getDeclaredField("mScroller");
scrollerField.setAccessible(true);
Field interpolator = ViewPager.class.getDeclaredField("sInterpolator");
interpolator.setAccessible(true);
Scroller scroller = new Scroller(getContext(), (Interpolator) interpolator.get(null)) {
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
//控制滑动速度
super.startScroll(startX, startY, dx, dy, (int) (1300 * (double) Math.abs(dx) / getWidth(getContext())));
}
};
scrollerField.set(this, scroller);
} catch (Exception e) {
e.printStackTrace();
}
}
public void autoLoop(boolean isAuto) {
if (mHandler == null) {
mHandler = new MyHandler(getContext());
}
if (isAuto) {
mHandler.sendEmptyMessageDelayed(HANDLE_LOOP_MSG, 3000);
} else {
mHandler.removeCallbacksAndMessages(null);
}
isAutoLoop.set(isAuto);
}
private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {
private float mPreviousOffset = -1;
private float mPreviousPosition = -1;
@Override
public void onPageSelected(int position) {
int realPosition = mAdapter.toRealPosition(position);
changePoints(realPosition);
if (mPreviousPosition != realPosition) {
mPreviousPosition = realPosition;
if (mOuterPageChangeListener != null) {
mOuterPageChangeListener.onPageSelected(realPosition);
}
}
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
int realPosition = position;
if (mAdapter != null) {
realPosition = mAdapter.toRealPosition(position);
if (positionOffset == 0
&& mPreviousOffset == 0
&& (position == 0 || position == mAdapter.getCount() - 1)) {
setCurrentItem(realPosition, false);
}
}
mPreviousOffset = positionOffset;
if (mOuterPageChangeListener != null) {
if (realPosition != mAdapter.getRealCount() - 1) {
mOuterPageChangeListener.onPageScrolled(realPosition,
positionOffset, positionOffsetPixels);
} else {
if (positionOffset > .5) {
mOuterPageChangeListener.onPageScrolled(0, 0, 0);
} else {
mOuterPageChangeListener.onPageScrolled(realPosition,
0, 0);
}
}
}
}
@Override
public void onPageScrollStateChanged(int state) {
switch (state) {
case SCROLL_STATE_DRAGGING:
if (isAutoLoop.get()) {
mHandler.removeCallbacksAndMessages(null);
}
break;
case SCROLL_STATE_IDLE:
if (isAutoLoop.get()) {
mHandler.sendEmptyMessageDelayed(HANDLE_LOOP_MSG, 3000);
}
break;
case SCROLL_STATE_SETTLING:
break;
}
if (mOuterPageChangeListener != null) {
mOuterPageChangeListener.onPageScrollStateChanged(state);
}
}
};
// @Override
// protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//
// int height = 0;
// for (int i = 0; i < getChildCount(); i++) {
// View child = getChildAt(i);
// child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
// int h = child.getMeasuredHeight();
// if (h > height)
// height = h;
// }
// int width = 0;
// for (int i = 0; i < getChildCount(); i++) {
// View child = getChildAt(i);
// child.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), heightMeasureSpec);
// int h = child.getMeasuredWidth();
// if (h > width)
// width = h;
// }
//
// heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
// widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
//
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// }
private class MyHandler extends Handler {
WeakReference<Context> mWeakReference;
public MyHandler(Context context) {
mWeakReference = new WeakReference<>(context);
}
@Override
public void handleMessage(Message msg) {
final Context context = mWeakReference.get();
if (context == null) {
return;
}
switch (msg.what) {
case HANDLE_LOOP_MSG:
int curItem = getCurrentItem();
setCurrentItem(++curItem);
changePoints(curItem % txtPoints.size() );
break;
}
}
}
public int getWidth(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}
}
- LoopPagerAdapterWrapper类
package com.hexin.cardservice.ui.customView;
/**
* Created by 15061 on 2018/12/21.
*/
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
public class LoopPagerAdapterWrapper extends PagerAdapter {
private PagerAdapter mAdapter;
LoopPagerAdapterWrapper(PagerAdapter adapter) {
this.mAdapter = adapter;
}
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
public int toInnerPosition(int realPosition) {
return realPosition + getCount() / 2 - getCount() % getRealCount();
}
int toRealPosition(int position) {
return position % getRealCount();
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
public int getRealCount() {
return mAdapter.getCount();
}
public PagerAdapter getRealAdapter() {
return mAdapter;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
int realPosition = position % getRealCount();
return mAdapter.instantiateItem(container, realPosition);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
int realPosition = position % getRealCount();
mAdapter.destroyItem(container, realPosition, object);
}
@Override
public void finishUpdate(ViewGroup container) {
mAdapter.finishUpdate(container);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return mAdapter.isViewFromObject(view, object);
}
@Override
public void restoreState(Parcelable bundle, ClassLoader classLoader) {
mAdapter.restoreState(bundle, classLoader);
}
@Override
public Parcelable saveState() {
return mAdapter.saveState();
}
@Override
public void startUpdate(ViewGroup container) {
mAdapter.startUpdate(container);
}
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
mAdapter.setPrimaryItem(container, position, object);
}
}
配置文件代码
<RelativeLayout
android:id="@+id/relativelayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp">
<.LoopViewPager
android:id="@+id/myviewpager"
android:layout_width="match_parent"
android:layout_height="125dp" />
<!-- 存放圆点 -->
<LinearLayout
android:id="@+id/layout_dots"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:gravity="center"
android:orientation="horizontal"/>
</RelativeLayout>
MainActivity 应用
初始化ViewPager
private void initViewPager() {
mViewpager = view.findViewById(R.id.myviewpager);
//图片圆角处理
for (int i = 0; i < mBannerArr.length; i++) {
ImageView view1 = new ImageView(getContext());
RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(), BitmapFactory.decodeResource(getResources(), mBannerArr[i]));
//view1.setImageResource(R.mipmap.pic);
roundedBitmapDrawable.setCornerRadius(30);
view1.setImageDrawable(roundedBitmapDrawable);
mImageList.add(view1);
}
mViewpager.setClipChildren(false);
DisplayMetrics dm = getResources().getDisplayMetrics();
mViewpager.setPageMargin(-dm.widthPixels / 13);//设置viewpage之间的间距
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mViewpager.getLayoutParams();
//高度根据图片进行适配(这里图片为750 *300)
params.height = (int) (getResources().getDisplayMetrics().widthPixels * 330 / 750.0);
params.width = getResources().getDisplayMetrics().widthPixels;
mViewpager.setLayoutParams(params);
mViewpager.setAdapter(new MyAdapter());
mViewpager.setPageTransformer(true, new ViewPager.PageTransformer() {
float scale = 0.85f;
@Override
public void transformPage(View page, float position) {
if (position >= 0 && position <= 1) {
page.setScaleY(scale + (1 - scale) * (1 - position));
} else if (position > -1 && position < 0) {
page.setScaleY(1 + (1 - scale) * position);
} else {
page.setScaleY(scale);
}
}
});
mViewpager.autoLoop(true);
}
初始化指示器小圆点
/**
* 初始化小圆点
*/
private void initCircle() {
mLayoutPoints = view.findViewById(R.id.layout_dots);
mTxtPoints = new ArrayList<>();
int d = DensityUtils.dp2px(mContext, 6);
int m = 10;
for (int i = 0; i < mImageList.size(); i++) {
TextView txt = new TextView(getContext());
if (i == 0) {
txt.setBackgroundResource(R.mipmap.home_yuan_sel);
} else {
txt.setBackgroundResource(R.mipmap.home_yuan);
}
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(d, d);
params.setMargins(m, m, m, m);
txt.setLayoutParams(params);
mTxtPoints.add(txt);
mLayoutPoints.addView(txt);
}
mViewpager.setTxtPoints(mTxtPoints);
}
viewpager自定义适配器:
class MyAdapter extends PagerAdapter {
@Override
public int getCount() {
return mImageList.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
ImageView view = mImageList.get(position);
ViewParent viewParent = view.getParent();
if (viewParent == null) {
container.addView(view);
}
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
log.d(TAG, "点击了第" + postion + "张图");
}
});
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
PS:这些就是轮播效果图了,希望对读者有帮助。。。
网友评论