前言:相信大家肯定都在项目开发中或多或少的接触过轮转广告图,有些朋友也自己写过。其实是比较初级的东西,是去年在做交行客户端维护时将Gallery的实现替换为ViewPager的一种方案。经过朋友们以及在其他项目的使用,功能不断完善,使用也更简单。转载请标明出处:
http://blog.csdn.net/xuehuayous/article/details/50518393;
本文出自:【Kevin.zhou的博客】
按照以前博客的风格,我们先看下最终实现的效果:
public BaseLoopView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // 设置默认属性 final float defaultDotMargin = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 3, getResources().getDisplayMetrics()); final int defaultInterval = 3000; // 设置样式属性 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LoopView); mDotMargin = a.getDimension(R.styleable.LoopView_loop_dotMargin, defaultDotMargin); mInterval = a.getInt(R.styleable.LoopView_loop_interval, defaultInterval); autoLoop = a.getBoolean(R.styleable.LoopView_loop_autoLoop, false); mDotSelector = a.getResourceId(R.styleable.LoopView_loop_dotSelector, R.drawable.loop_view_dots_selector); mDefaultImgId = a.getResourceId(R.styleable.LoopView_loop_defaultImg, 0); mLoopLayoutId = a.getResourceId(R.styleable.LoopView_loop_layout, 0); a.recycle(); initRealView(); }
@Override @SuppressWarnings("deprecation") protected void initRealView() { View view = null; if (mLoopLayoutId != 0) { // If there is a custom loop view layout id set, try and inflate it view = LayoutInflater.from(getContext()).inflate(mLoopLayoutId, null); // ViewPager mViewPager = (ViewPager) view.findViewById(R.id.loop_view_pager); // 指示点父控件 dotsView = (LinearLayout) view.findViewById(R.id.loop_view_dots); // 描述文字 descText = (TextView) view.findViewById(R.id.loop_view_desc); } if(view == null) { view = createDefaultView(); } setScrollDuration(1000); // 设置页面切换时间 this.addView(view); }
private View createDefaultView() { RelativeLayout contentView = new RelativeLayout(getContext()); int viewWidth = ViewGroup.LayoutParams.MATCH_PARENT; int viewHeight = ViewGroup.LayoutParams.WRAP_CONTENT; ViewGroup.LayoutParams viewParams = new ViewGroup.LayoutParams(viewWidth, viewHeight); contentView.setLayoutParams(viewParams); // 初始化ViewPager mViewPager = new ViewPager(getContext()); mViewPager.setId(R.id.loop_view_pager); int viewPagerWidth = LayoutParams.MATCH_PARENT; int viewPagerHeight = LayoutParams.WRAP_CONTENT; LayoutParams viewPagerParams = new LayoutParams(viewPagerWidth, viewPagerHeight); this.addView(mViewPager, viewPagerParams); // 初始化下方指示条 RelativeLayout bottomLayout = new RelativeLayout(getContext()); int bottomLayoutWidth = LayoutParams.MATCH_PARENT; int bottomLayoutHeight = LayoutParams.WRAP_CONTENT; LayoutParams bottomLayoutParams = new LayoutParams(bottomLayoutWidth, bottomLayoutHeight); bottomLayoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, mViewPager.getId()); Drawable mBackground = new ColorDrawable(Color.DKGRAY); mBackground.setAlpha((int) (0.3 * 255)); bottomLayout.setBackgroundDrawable(mBackground); bottomLayout.setGravity(Gravity.CENTER_VERTICAL); this.addView(bottomLayout, bottomLayoutParams); // 初始化指示点父控件 dotsView = new LinearLayout(getContext()); dotsView.setId(R.id.loop_view_dots); int dotsViewWidth = LayoutParams.WRAP_CONTENT; int dotsViewHeight = LayoutParams.WRAP_CONTENT; LayoutParams dotsViewParams = new LayoutParams(dotsViewWidth, dotsViewHeight); dotsView.setOrientation(LinearLayout.HORIZONTAL); dotsViewParams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE); dotsViewParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE); bottomLayout.addView(dotsView, dotsViewParams); // 初始描述文字 descText = new TextView(getContext()); int descTextWidth = LayoutParams.MATCH_PARENT; int descTextHeight = LayoutParams.WRAP_CONTENT; LayoutParams descTextParams = new LayoutParams(descTextWidth, descTextHeight); descTextParams.addRule(RelativeLayout.LEFT_OF, dotsView.getId()); descText.setSingleLine(true); descText.getPaint().setTextSize((int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 14, getResources().getDisplayMetrics())); descText.setTextColor(Color.WHITE); descText.setGravity(Gravity.LEFT); int padding = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics()); descText.setPadding(padding, padding, padding, padding); bottomLayout.addView(descText, descTextParams); return contentView; }
private void initLoopViewPager() { adapter = initAdapter(); adapter.setDefaultImgId(mDefaultImgId); mViewPager.setAdapter(adapter); initDots(mLoopData.items.size()); // 初始化指示点 if(null != descText) { String descStr = mLoopData.items.get(0).descText; if(!TextUtils.isEmpty(descStr)) { descText.setText(descStr); // 初始化描述信息 } } setViewListener(); // 初始化点击监听事件 int startPosition = Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % mLoopData.items.size(); mViewPager.setCurrentItem(startPosition, false); // 设置当前显示的位置 if (mHandler == null) { mHandler = new LoopHandler(this, (Activity)getContext()); } if (autoLoop) { startAutoLoop(); } }
@Override public Object instantiateItem(ViewGroup container, final int position) { final View view; final int index = position % mLoopData.items.size(); String imageUrl = mLoopData.items.get(index).imgUrl; // 首先读取软引用,如果不存在则初始化该View if (instantiateViewMap.containsKey(index)) { SoftReference<View> reference = instantiateViewMap.remove(index); if (null == reference || null == reference.get()) { // ToastUtils.showShortToast(mContext, "被回收了..."); view = instantiateItemView(imageUrl, index); } else { view = reference.get(); // ToastUtils.showShortToast(mContext, "读取软引用..."); } } else { // ToastUtils.showShortToast(mContext, "初始化..."); view = instantiateItemView(imageUrl, index); } if(mOnItemClickListener != null) { view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 条目点击监听回调 mOnItemClickListener.onItemClick(BaseLoopAdapter.this, view, index, position); } }); } container.addView(view, 0); return view; }
@Override protected void setOnPageChangeListener() { // 数据适配器滑动监听 mViewPager.addOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { int i = position % mLoopData.items.size(); if(null != dotsView) { dotsView.getChildAt(i).setEnabled(true); } if(null != dotsView && currentPosition != -1) { dotsView.getChildAt(currentPosition).setEnabled(false); } currentPosition = i; if(null != descText) { if(!TextUtils.isEmpty(mLoopData.items.get(i).descText)) { if(descText.getVisibility() != View.VISIBLE) descText.setVisibility(View.VISIBLE); String imageDesc = mLoopData.items.get(i).descText; descText.setText(imageDesc); } else { if(descText.getVisibility() == View.VISIBLE) descText.setVisibility(View.GONE); } } // 跳转到头部尾部的监听回调 if(mOnLoopListener != null) { if(i == 0) { mOnLoopListener.onLoopToStart(position); } else if(i == mLoopData.items.size() -1) { mOnLoopListener.onLoopToEnd(position); } } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {} @Override public void onPageScrollStateChanged(int state) {} }); }
public class LoopHandler extends Handler { private final WeakReference<Activity> mActivity; private final WeakReference<BaseLoopView> mLoopView; public LoopHandler(BaseLoopView loopView, Activity activity) { this.mLoopView = new WeakReference<BaseLoopView>(loopView); this.mActivity = new WeakReference<Activity>(activity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 0: Activity activity = mActivity.get(); BaseLoopView loopView = mLoopView.get(); if (activity != null && loopView != null) { if (!loopView.isAutoScroll()) return; int change = (loopView.getDirection() == BaseLoopView.LEFT) ? -1 : 1; loopView.getViewPager().setCurrentItem(loopView.getViewPager().getCurrentItem() + change, true); loopView.sendScrollMessage(loopView.getInterval()); } else { removeMessages(0); if(loopView != null) { loopView.releaseResources(); } } default: break; } } }
/** * stopScrollWhenTouch为TRUE时 * 按下操作停止轮转 * 抬起操作继续轮转 */ @Override public boolean dispatchTouchEvent(MotionEvent ev) { if(stopScrollWhenTouch) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: if(isAutoScroll) { stopAutoLoop(); isStoppedByTouch = true; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: if(isStoppedByTouch) { startAutoLoop(mInterval); isStoppedByTouch = false; } break; } } return super.dispatchTouchEvent(ev); }
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { // 当Y方向滑动距离大于X方向滑动距离时不获取滚动事件 switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mDownX = ev.getX(); mDownY = ev.getY(); break; case MotionEvent.ACTION_MOVE: if(Math.abs(ev.getY() - mDownY) > Math.abs(ev.getX() - mDownX)) { getParent().requestDisallowInterceptTouchEvent(false); } else { getParent().requestDisallowInterceptTouchEvent(true); } mDownX = ev.getX(); mDownY = ev.getY(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: getParent().requestDisallowInterceptTouchEvent(false); break; } return super.onInterceptTouchEvent(ev); }
@Override protected void onWindowVisibilityChanged(int visibility) { super.onWindowVisibilityChanged(visibility); // 当不可见的时候停止自动跳转 switch (visibility) { case VISIBLE: if(isStoppedByInvisible) { startAutoLoop(mInterval); isStoppedByInvisible = false; } break; case INVISIBLE: case GONE: if(isAutoScroll) { stopAutoLoop(); isStoppedByInvisible = true; } break; } }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:kevin="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.kevin.loopview.AdLoopView android:id="@+id/adloop_act_adloopview" android:layout_width="match_parent" android:layout_height="192dp" kevin:loop_interval="5000" kevin:loop_dotMargin="5dp" kevin:loop_autoLoop="true"> </com.kevin.loopview.AdLoopView> </RelativeLayout>
/** * 初始化LoopView * * @return void */ private void initRotateView() { mLoopView = (AdLoopView) this.findViewById(R.id.main_act_adloopview); String json = LocalFileUtils.getStringFormAsset(this, "loopview_date.json"); LoopData loopData = JsonTool.toBean(json, LoopData.class); if(null != loopData) { mLoopView.refreshData(loopData); mLoopView.startAutoLoop(); } }
{ "items": [ { "id": "0", "descText": "传递数据纠结吗?", "imgUrl": "http://cms.csdnimg.cn/article/201305/21/519b0d442e3e7.jpg", "link":"https://github.com/greenrobot/EventBus", "type":"ad" }, { "id": "1", "descText": "OOM了肿么办,不用怕!", "imgUrl": "http://cms.csdnimg.cn/article/201305/03/51834d562e039_middle.jpg", "link":"https://github.com/nostra13/Android-Universal-Image-Loader", "type":"ad" }, { "id": "2", "descText": "不想写sql语句唉", "imgUrl": "http://www.strongcms.net/uploads/allimg/c120202/132Q962920TP-1W17.png", "link":"http://ormlite.com/sqlite_java_android_orm.shtml", "type":"ad" } ] }
如果您的项目使用 Gradle 构建, 只需要在您的build.gradle
文件添加下面一行到 dependencies
:
compile 'com.kevin:loopview:1.0.6'