Android之最简单的Banner实现
2016-12-16 15:31
337 查看
本文主要记录一些零碎的东西
最近项目里需要在首页做一个展示用的banner,基本需求就是可以滚动,可以点击
网上很多现成的,自己有思路,撸了一个简单的实现版本
![](https://img-blog.csdn.net/20161213134747808?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSV9kb19jYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](https://img-blog.csdn.net/20161213134755247?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSV9kb19jYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
代码比较简单
测试代码
附:
---------更新------------------------
降低banner 自动滑动速度
最近项目里需要在首页做一个展示用的banner,基本需求就是可以滚动,可以点击
网上很多现成的,自己有思路,撸了一个简单的实现版本
使用ViewPager ,图片加载使用Glide 循环原理 : 4--1- 2- 3 -4--1 第一页左边增加最后一页,最后一页右边增加第一页 0 1 2 3 4 5 当选中新的界面上的第0页时,调到新的界面第4页;当选中新的界面上的第5页时,调到新的界面第1页.
代码比较简单
--有滑动界面指示器(右下角小圆点) --支持自定义自动滑动的时间间隔 --支持自动滑动 --支持手势滑动,取消自动滑动,无手势3秒后,如设置了自动滑动,继续自动滑动 --支持item点击
只有一个文件 BannerView
import android.content.Context; import android.os.Handler; import android.os.Looper; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.bumptech.glide.Glide; import java.util.ArrayList; import java.util.List; /** * 循环 banner 3- 1-2-3 -1 * Created by slack on 2016/12/9 18:46. * 如何区分是手动 还是 自动 */ public class BannerView extends FrameLayout implements View.OnClickListener { private ViewPager mViewPager; private List<String> mFilePathList; private ImageView mImageView; private List<ImageView> mImageList = new ArrayList<>(); // test // private List<TextView> mImageList = new ArrayList<>(); // private TextView mImageView; private int mCurrentPosition; private Handler mHandler; private int DEFAULT_INTERVAL = 1500; private int DEFAULT_WAIT_TIME = 3000; // 3s 后用户没有点击,继续自动滑动 private long mTouchTime; private boolean auto = false; private OnItemClickListener mOnItemClickListener; private LinearLayout mPointContainer; // 存放点的容器 private int mPointDrawableId = R.drawable.selector_banner_point; // 点的drawable资源id private ImageView mPoint; public BannerView(Context context) { this(context, null); } public BannerView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public BannerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mHandler = new Handler(Looper.getMainLooper()); initView(); } public BannerView setOnItemClickListener(OnItemClickListener l) { mOnItemClickListener = l; return this; } /** * 设置数据,初始化view部分 * * @param list imageUri 使用Glide 加载 * @return */ public BannerView setBannerData(List<String> list) { mFilePathList = list; if (list.size() > 1) { for (int i = 0; i < list.size(); i++) { // mImageView = new ImageView(getContext()); createNewView(list.get(i)); // point mPoint = new ImageView(getContext()); mPoint.setImageResource(mPointDrawableId); mPoint.setEnabled(false); mPoint.setPadding(10, 0, 10, 0); mPointContainer.addView(mPoint); } // 第一页加在最后 createNewView(list.get(0), -1); // 最后一页加在第一页 createNewView(list.get(list.size() - 1), 0); mCurrentPosition = 1; mViewPager.setOffscreenPageLimit(2); mViewPager.addOnPageChangeListener(pageChangeListener); } else { createNewView(list.get(0)); mCurrentPosition = 0; mPoint = new ImageView(getContext()); mPoint.setImageResource(mPointDrawableId); mPoint.setEnabled(true); mPointContainer.addView(mPoint); } mViewPager.setAdapter(new InnerPagerAdapter()); mViewPager.setCurrentItem(mCurrentPosition); return this; } /** * 对应activity的生命周期 * * @return */ public BannerView onResume() { if (auto) { mHandler.removeCallbacks(autoSmooth); mHandler.post(autoSmooth); } return this; } public BannerView onPause() { mHandler.removeCallbacks(autoSmooth); mHandler.removeCallbacks(timeCount); return this; } private void createNewView(String text) { createNewView(text, -1); } private void createNewView(String url, int position) { mImageView = new ImageView(getContext()); mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP); if (position == -1) { mImageList.add(mImageView); } else { mImageList.add(position, mImageView); } mImageView.setOnClickListener(this); Glide.with(getContext()) .load(url) .placeholder(R.mipmap.empty) .error(R.mipmap.error) .into(mImageView); // mImageView = new TextView(getContext()); // mImageView.setText(text); // if(position == -1) { // mImageList.add(mImageView); // }else { // mImageList.add(position,mImageView); // } // mImageView.setOnClickListener(this); } /** * 时间间隔 * * @param interval */ public BannerView setSmoothInterval(int interval) { DEFAULT_INTERVAL = interval; return this; } /** * 自动滑动 */ public void startSmoothAuto() { if (mImageList.size() == 1) { return; } auto = true; mHandler.postDelayed(autoSmooth, DEFAULT_INTERVAL); } Runnable autoSmooth = new Runnable() { @Override public void run() { mCurrentPosition++; mCurrentPosition = mCurrentPosition % mImageList.size(); mViewPager.setCurrentItem(mCurrentPosition); mHandler.postDelayed(this, DEFAULT_INTERVAL); } }; Runnable timeCount = new Runnable() { @Override public void run() { if (System.currentTimeMillis() - mTouchTime > DEFAULT_WAIT_TIME) { mHandler.removeCallbacks(this); mHandler.removeCallbacks(autoSmooth); mHandler.post(autoSmooth); return; } mHandler.postDelayed(this, DEFAULT_INTERVAL); } }; private void initView() { mViewPager = new ViewPager(getContext()); addView(mViewPager); mPointContainer = new LinearLayout(getContext()); mPointContainer.setPadding(0, 0, 80, 20); mPointContainer.setGravity(Gravity.BOTTOM | Gravity.RIGHT); addView(mPointContainer); } ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { // Log.i("slack","onPageScrolled..."); } @Override public void onPageSelected(int position) { // Log.i("slack","onPageSelected..."); mCurrentPosition = position; switchToPoint(); } @Override public void onPageScrollStateChanged(int state) { if (state == ViewPager.SCROLL_STATE_IDLE && mImageList.size() > 1) { if (mCurrentPosition == 0) { mCurrentPosition = mImageList.size() - 2; mViewPager.setCurrentItem(mCurrentPosition, false); } else if (mCurrentPosition == (mImageList.size() - 1)) { mCurrentPosition = 1; mViewPager.setCurrentItem(mCurrentPosition, false); } // Log.i("slack","onPageScrollStateChanged..." + mCurrentPosition); } } }; /** * point 假如有三个实际页面,0-2 */ private void switchToPoint() { if (mCurrentPosition == 0 || mCurrentPosition == mImageList.size() - 1) { return; } for (int i = 0; i < mPointContainer.getChildCount(); i++) { mPointContainer.getChildAt(i).setEnabled(false); } mPointContainer.getChildAt(mCurrentPosition - 1).setEnabled(true); } @Override public void onClick(View view) { // Log.i("slack", "pos: " + mCurrentPosition); if (mOnItemClickListener != null) { mOnItemClickListener.onItemClick(mCurrentPosition - 1); } } /** * viewPager的适配器 */ private class InnerPagerAdapter extends PagerAdapter { @Override public int getCount() { return mImageList.size() > 1 ? mImageList.size() : 1; } @Override public Object instantiateItem(ViewGroup container, final int position) { container.addView(mImageList.get(position)); return mImageList.get(position); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public int getItemPosition(Object object) { return POSITION_NONE; } } // ACTION_UP 滑动冲突,获取不到 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { // Log.i("slack","onInterceptTouchEvent..." + ev.toString()); if (auto) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { mHandler.removeCallbacks(autoSmooth); } else if (ev.getAction() == MotionEvent.ACTION_MOVE) { mTouchTime = System.currentTimeMillis(); mHandler.postDelayed(timeCount, 100); } } return super.onInterceptTouchEvent(ev); } public interface OnItemClickListener { void onItemClick(int position); } }
测试代码
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.Toast; import java.util.ArrayList; import java.util.List; public class BannerActivity extends AppCompatActivity { private BannerView mBannerView; private List<String> mList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_banner); mBannerView = (BannerView) findViewById(R.id.id_banner); mList = new ArrayList<>(); mList.add("http://img1.imgtn.bdimg.com/it/u=2387069514,246472357&fm=23&gp=0.jpg"); mList.add("http://img3.duitang.com/uploads/item/201601/03/20160103103827_5XEts.thumb.700_0.jpeg"); mList.add("http://f2.dn.anqu.com/down/YjFkMw==/allimg/1301/60-130130114620.jpg"); mBannerView.setOnItemClickListener(new BannerView.OnItemClickListener() { @Override public void onItemClick(int position) { Toast.makeText(BannerActivity.this,"Position " + position ,Toast.LENGTH_SHORT).show(); } }).setBannerData(mList).setSmoothInterval(1500).startSmoothAuto(); } @Override protected void onResume() { super.onResume(); mBannerView.onResume(); } @Override protected void onPause() { super.onPause(); mBannerView.onPause(); } }
附:
指示器圆点显示:drawable/selector_banner_point.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="true"> <shape android:shape="oval"> <size android:width="6dp" android:height="6dp" /> <solid android:color="@android:color/white" /> </shape> </item> <item> <shape android:shape="oval"> <size android:width="6dp" android:height="6dp" /> <solid android:color="#C6C6C6" /> </shape> </item> </selector>Glide引入:dependencies { compile 'com.github.bumptech.glide:glide:3.5.2'}别忘了联网权限 AndroidManifest.xml<uses-permission android:name="android.permission.INTERNET"/>
---------更新------------------------
降低banner 自动滑动速度
import android.content.Context; import android.os.Handler; import android.os.Looper; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Scroller; import com.benqu.serverside.model.appsettings.ApiModelCarousel; import com.benqu.wuta.R; import com.benqu.wuta.WTController; import com.benqu.wuta.utils.BannerUtil; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; /** 首页 循环 banner 3- 1-2-3 -1 * Created by slack on 2016/12/14 17:41. */ public class BannerView extends FrameLayout implements View.OnClickListener { private ViewPagerCustomDuration mViewPager; private ImageView mImageView; private List<ImageView> mImageList = new ArrayList<>(); private int mCurrentPosition; private Handler mHandler; private static final int DEFAULT_DELAY = 1000; private int DEFAULT_INTERVAL = 1500; private int DEFAULT_WAIT_TIME = 3000; // 3s 后用户没有点击,继续自动滑动 private long mTouchTime; private boolean auto = false; private OnItemClickListener mOnItemClickListener; // private LinearLayout mPointContainer; // 存放点的容器 // private int mPointDrawableId = R.drawable.banner_point; // 点的drawable资源id // private ImageView mPoint; private BannerUtil mBannerUtil = BannerUtil.util; public BannerView(Context context) { this(context, null); } public BannerView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public BannerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mHandler = new Handler(Looper.getMainLooper()); initView(); } public BannerView setOnItemClickListener(OnItemClickListener l) { mOnItemClickListener = l; return this; } /** * 设置数据,初始化view部分 * * @return */ public BannerView setBannerData(ApiModelCarousel carousel) { if (carousel.itemList.size() > 1) { for (int i = 0; i < carousel.itemList.size(); i++) { // mImageView = new ImageView(getContext()); createNewView(carousel.itemList.get(i)); // point // mPoint = new ImageView(getContext()); // mPoint.setImageResource(mPointDrawableId); // mPoint.setEnabled(false); // mPoint.setPadding(10, 0, 10, 0); // mPointContainer.addView(mPoint); } // 第一页加在最后 createNewView(carousel.itemList.get(0)); // 最后一页加在第一页 createNewView(carousel.itemList.get(carousel.itemList.size() - 1), 0); mCurrentPosition = 1; mViewPager.setOffscreenPageLimit(2); mViewPager.addOnPageChangeListener(pageChangeListener); } else { createNewView(carousel.itemList.get(0)); mCurrentPosition = 0; // mPoint = new ImageView(getContext()); // mPoint.setImageResource(mPointDrawableId); // mPoint.setEnabled(true); // mPointContainer.addView(mPoint); } mViewPager.setAdapter(new InnerPagerAdapter()); mViewPager.setCurrentItem(mCurrentPosition); return this; } /** * 对应activity的生命周期 * * @return */ public BannerView onResume() { if (auto && mImageList != null && mImageList.size() > 1) { mHandler.removeCallbacks(autoSmooth); mHandler.postDelayed(autoSmooth,DEFAULT_DELAY); } return this; } public BannerView onPause() { mHandler.removeCallbacks(autoSmooth); mHandler.removeCallbacks(timeCount); return this; } private void createNewView(ApiModelCarousel.ApiModelCarouselItem item) { createNewView(item,-1); } private void createNewView(ApiModelCarousel.ApiModelCarouselItem item, int position) { mImageView = new ImageView(getContext()); mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP); if (position == -1) { mImageList.add(mImageView); } else { mImageList.add(position, mImageView); } mImageView.setOnClickListener(this); mBannerUtil.showBannerImage(mImageView,item.getImgUrl()); } /** * 时间间隔 * * @param interval */ public BannerView setSmoothInterval(int interval) { DEFAULT_INTERVAL = interval; return this; } /** * 自动滑动 */ public void startSmoothAuto() { if (mImageList.size() == 1) { return; } auto = true; mHandler.postDelayed(autoSmooth, DEFAULT_DELAY);// delay 1s } Runnable autoSmooth = new Runnable() { @Override public void run() { mCurrentPosition++; mCurrentPosition = mCurrentPosition % mImageList.size(); mViewPager.setCurrentItem(mCurrentPosition,true); mHandler.postDelayed(this, DEFAULT_INTERVAL); } }; Runnable timeCount = new Runnable() { @Override public void run() { if (System.currentTimeMillis() - mTouchTime > DEFAULT_WAIT_TIME) { mHandler.removeCallbacks(this); mHandler.removeCallbacks(autoSmooth); mHandler.post(autoSmooth); return; } mHandler.postDelayed(this, DEFAULT_INTERVAL); } }; private void initView() { // mViewPager = new ViewPager(getContext()); mViewPager = new ViewPagerCustomDuration(getContext()); addView(mViewPager); // mPointContainer = new LinearLayout(getContext()); // mPointContainer.setPadding(0, 0, 80, 20); // mPointContainer.setGravity(Gravity.BOTTOM | Gravity.RIGHT); // // addView(mPointContainer); } ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { // Log.i("slack","onPageScrolled..."); } @Override public void onPageSelected(int position) { // Log.i("slack","onPageSelected..."); mCurrentPosition = position; switchToPoint(); } @Override public void onPageScrollStateChanged(int state) { if (state == ViewPager.SCROLL_STATE_IDLE && mImageList.size() > 1) { if (mCurrentPosition == 0) { mCurrentPosition = mImageList.size() - 2; mViewPager.setCurrentItem(mCurrentPosition, false); } else if (mCurrentPosition == (mImageList.size() - 1)) { mCurrentPosition = 1; mViewPager.setCurrentItem(mCurrentPosition, false); } // Log.i("slack","onPageScrollStateChanged..." + mCurrentPosition); } } }; /** * point 假如有三个实际页面,0-2 */ private void switchToPoint() { // if (mCurrentPosition == 0 || mCurrentPosition == mImageList.size() - 1) { // return; // } // // for (int i = 0; i < mPointContainer.getChildCount(); i++) { // mPointContainer.getChildAt(i).setEnabled(false); // } // // mPointContainer.getChildAt(mCurrentPosition - 1).setEnabled(true); } @Override public void onClick(View view) { // Log.i("slack", "pos: " + mCurrentPosition); if (mOnItemClickListener != null) { mOnItemClickListener.onItemClick(mImageList.size() > 1 ? mCurrentPosition - 1 : 0); } } /** * viewPager的适配器 */ private class InnerPagerAdapter extends PagerAdapter { @Override public int getCount() { return mImageList.size() > 1 ? mImageList.size() : 1; } @Override public Object instantiateItem(ViewGroup container, final int position) { container.addView(mImageList.get(position)); return mImageList.get(position); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public int getItemPosition(Object object) { return POSITION_NONE; } } /** * my ViewPager slow down zhe speed */ private class ViewPagerCustomDuration extends ViewPager { private FixedSpeedScroller mScroller = null; public ViewPagerCustomDuration(Context context) { super(context); init(); } public ViewPagerCustomDuration(Context context, AttributeSet attrs) { super(context, attrs); init(); } /* * Override the Scroller instance with our own class so we can change the * duration */ private void init() { try { Class<?> viewpager = ViewPager.class; Field scroller = viewpager.getDeclaredField("mScroller"); scroller.setAccessible(true); mScroller = new FixedSpeedScroller(getContext(), new DecelerateInterpolator()); scroller.set(this, mScroller); } catch (Exception ignored) { } } /* * Set the factor by which the duration will change */ public void setScrollDuration(int duration) { mScroller.setScrollDuration(duration); } private class FixedSpeedScroller extends Scroller { private int mDuration = 500; public FixedSpeedScroller(Context context) { super(context); } public FixedSpeedScroller(Context context, Interpolator interpolator) { super(context, interpolator); } public FixedSpeedScroller(Context context, Interpolator interpolator, boolean flywheel) { super(context, interpolator, flywheel); } @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 void setScrollDuration(int duration) { mDuration = duration; } } } // ACTION_UP 滑动冲突,获取不到 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { // Log.i("slack","onInterceptTouchEvent..." + ev.toString()); if (auto) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { mHandler.removeCallbacks(autoSmooth); } else if (ev.getAction() == MotionEvent.ACTION_MOVE) { mTouchTime = System.currentTimeMillis(); mHandler.postDelayed(timeCount, 100); } } return super.onInterceptTouchEvent(ev); } public interface OnItemClickListener { void onItemClick(int position); } }
相关文章推荐
- Android简单暴力实现Banner
- Android框架_Banner实现轮播图Demo——超简单
- Android Banner效果简单实现
- Android 轮播图Banner的简单实现
- Android Banner 简单实现
- android 简单实现Banner 轮廓图效果自动播放
- Android:一个简单查询界面的实现
- 实现简单的Android的播放视频功能
- android listview 的弹性滑动 简单demo 实现
- 【Android游戏开发十六】Android Gesture之【触摸屏手势识别】操作!利用触摸屏手势实现一个简单切换图片的功能!
- Android 手机重力感应实现简单介绍
- Android中用AsyncTask简单实现多线程
- 【android】sqlite+content provider+cursor adapter的最简单实现示例
- Android HAL实现的三种方式- 基于JNI的简单HAL设计
- android 之手机拨号器,以及短信发送器的简单实现
- 简单实现Android顶部工具栏和底部工具栏
- android 3D 游戏实现之简单碰撞检测
- android listview 的弹性滑动 简单demo 实现
- Android Tab 选项卡的简单实现
- 【Android游戏开发十六】Android Gesture之【触摸屏手势识别】操作!利用触摸屏手势实现一个简单切换图片的功能!