打造史上最简单的广告轮播图Banner
来源:互联网 发布:淘宝销售宣传标语 编辑:程序博客网 时间:2024/05/22 07:52
个人警语: 一份耕耘,一份收获,努力越大,收获越多。动眼不动手都是假把式,没事多敲敲 , 收获的不只是更多!
转载请注明出处:http://blog.csdn.net/u014239140/article/details/52658486
我将之前写的知识点类文章全部删掉了,以后只提供项目干货,帮你快速的开发app 。介于是首次写干活类文章,表达不清楚多多包涵!O(∩_∩)O~
言归正传回到今天的主题上吧!之前想写个广告轮播是不是要考虑很多啊?那我们先来列下要做到兼容大多数的情况需要考虑的那些点:
1.是否支持无限滚动,滚动方式类型(1.普通的正向滚动 到最后一页直接回第一页 2.正向滚动到最后一页后是否能够反向滚动回来)。
2.是否支持用户按住时停止滚动 (处理事件类问题)。
3 滚动的处理方式:使用普通的Timer做定时任务?还是使用线程池,安全类问题。
3.是否支持点击图片给出回调方法(比如:你点击了第三张时候将点击的position返回回来)。
4.追求效果的动画效果肯定少不了,那肯定就得添加10多种动画效果 供开发者使用吧!
5.是否支持对图片ImageView.ScaleType的设置。
6.是否支持indicator的显示,显示方式在代码中写死还是交给布局文件?
7.都要支持什么类型的图片:本地?资源文件下?网络?当然这三种我们肯定都要支持才人性化叁。
下面我就随便选择一个翻页来看下demo效果图吧:
好了,我们大致分析了下要考虑的点下面我们就动手躁起来吧!首先我们先来看下如何使用吧?然后在来看一步一怎么实现的。
第一步先来创建我们的布局文件吧,来吧字母走起。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" > <com.example.androidviewpageutil.View.ZZHViewPager android:id="@+id/vip_show" android:layout_width="match_parent" android:layout_height="match_parent" /> <LinearLayout android:id="@+id/ll_point" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="25dp" android:orientation="horizontal"></LinearLayout></RelativeLayout>
布局文件中LinearLayout即为指示器的容器,这里就把指示器交给布局文件了,so,你的indicator是不是就可以谁便你放了,是不是很灵活。
第二步就是装数据 ,初始化控件,当然在项目中我们肯定少不了的一个接口来获取数据吧!这里就不写接口,就在百度上随便找了几个图片地址,将就用吧! 不要嫌我偷懒哦。这篇文章写下来会很长的。先来看下Activity吧。
private List<String> listurl = new ArrayList<String>(); //用于测试网络图片private ZZHViewPager viewPage; //自定义viewpageint[] mImg = { R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d };//用于测试资源图片 private int[] isdots = new int[]{R.drawable.login_point_selected, R.drawable.login_point};//准备好的指示器 private LinearLayout ll_point; //指示器容器 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listurl.add("http://pic.qiantucdn.com/58pic/13/04/21/31D58PICVAH.jpg"); listurl.add("http://img0.imgtn.bdimg.com/it/u=1149180775,4094747667&fm=21&gp=0.jpg"); listurl.add("http://img.taopic.com/uploads/allimg/120625/201826-1206251Z15872.jpg"); listurl.add("http://pic15.nipic.com/20110630/6322714_111532514304_2.jpg"); viewPage = (ZZHViewPager)findViewById(R.id.vip_show); ll_point = (LinearLayout)findViewById(R.id.ll_point); initdata(TransitionEffect.RotateUp); }
第三步重点来了配置我们的banner了,一如既往代码走起。
private void initdata(TransitionEffect effect) { viewPage.setTransitionEffect(effect);//添加动画效果。目前只提供了12种动画 ViewPageAdapter adapter = new ViewPageAdapter(this,viewPage,listurl); adapter.setImageType(SelectImageType.NETWORK); //指定为网络图片 adapter.setImageScaleType(ImageView.ScaleType.FIT_XY);//设置图片缩放模式 adapter.showTips(ll_point, isdots);//设置显示指示器 adapter.startChangePage(6,false);//设置开始滚动 参数1:间隔毫秒数滚动 2.true即支持反向滚动,false则不支持。 viewPage.setAdapter(adapter); //图片的点击事件 可供开发者处理 adapter.setOnclikListener(new ImageClickLstener() { @Override public void setImageOnclikliseter(int position,int allsize) { Toast.makeText(getApplicationContext(), "position:"+position+"allsize:"+allsize, 1).show(); } });}
我靠是不是很简单。其实这三部就已经完成上图的功能了。是不是很酷O(∩_∩)O~
咳咳,偷个懒内部封装的方法api就不在一一介绍了,你看上面的代码吧。我把注释都写的很清楚了!不清楚请邮箱联系...
到此我们的用法就结束了,是不是很想知道内部怎么搞的?来吧往下看。
首先在布局文件看到我们的ZZHViewPage,这是什么鬼?其实就是我们继承ViewPage来写的一个自定义ViewPage。那自定义是什么鬼?这里就不在赘述基础了。其实你记住自定义的基本步骤就好办了。来吧说下步骤:
1.自定义属性。(就是在你Values文件下建立属性文件)
2.在继承的view的构造函数里获取属性值。
3.重写onMesure方法,当然测量不是必要操作。
4.重写onDraw方法(关键点)。清楚就这么四步走策略就可以了。
屁话整了一大堆我想说啥来着?哦哦整到自定义ViewPage了,我们要实现各种动画,各种事件以及预加载view是不是我们都应该在这里做啊?那是当然,来吧看代码:介于篇幅问题,方法我就不单独讲了,我在代码里把关注的方法打上注释
public class ZZHViewPager extends ViewPager{ public static final String TAG = "ViewPager"; private boolean mEnabled = true; private boolean mFadeEnabled = false; private boolean mOutlineEnabled = false; public static int sOutlineColor = Color.WHITE; private TransitionEffect mEffect = TransitionEffect.Standard; private HashMap<Integer, Object> mObjs = new LinkedHashMap<Integer, Object>(); private static final float SCALE_MAX = 0.5f; private static final float ZOOM_MAX = 0.5f; private static final float ROT_MAX = 15.0f; /** * 是否正在触摸状态,用以防止触摸滑动和自动轮播冲突 */ public static boolean mIsTouching = false; public enum TransitionEffect { //提供的12种动画 Standard, Tablet, CubeIn, CubeOut, FlipVertical, FlipHorizontal, Stack, ZoomIn, ZoomOut, RotateUp, RotateDown, Accordion } private static final boolean API_11; static { API_11 = Build.VERSION.SDK_INT >= 11; } public ZZHViewPager(Context context) { this(context, null); } @SuppressWarnings("incomplete-switch") //在构造函数中获取属性值 public ZZHViewPager(Context context, AttributeSet attrs) { super(context, attrs); setClipChildren(false); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ViewPager); int effect = ta.getInt(R.styleable.ViewPager_style, 0); String[] transitions = getResources().getStringArray(R.array.jazzy_effects); setTransitionEffect(TransitionEffect.valueOf(transitions[effect])); setFadeEnabled(ta.getBoolean(R.styleable.ViewPager_fadeEnabled, false)); setOutlineEnabled(ta.getBoolean(R.styleable.ViewPager_outlineEnabled, false)); setOutlineColor(ta.getColor(R.styleable.ViewPager_outlineColor, Color.WHITE)); switch (mEffect) { case Stack: case ZoomOut: setFadeEnabled(true); } ta.recycle(); Util.initImagLoad(context); } @Override public boolean onTouchEvent(MotionEvent ev) { 用于处理是否要阻止滚动的冲突事件 switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mIsTouching = true; case MotionEvent.ACTION_MOVE: mIsTouching = true; break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: mIsTouching = false; break; } return super.onTouchEvent(ev); } @Override protected void onDetachedFromWindow() { //取消定时任务 安全问题 super.onDetachedFromWindow(); if(ViewPageAdapter.scheduledexecutorservice != null && ViewPageAdapter.scheduledexecutorservice.isShutdown() == false){ ViewPageAdapter.scheduledexecutorservice.shutdown(); } ViewPageAdapter.scheduledexecutorservice = null; } public void setTransitionEffect(TransitionEffect effect) { mEffect = effect; } public void setPagingEnabled(boolean enabled) { mEnabled = enabled; } public void setFadeEnabled(boolean enabled) { mFadeEnabled = enabled; } public boolean getFadeEnabled() { return mFadeEnabled; } public void setOutlineEnabled(boolean enabled) { mOutlineEnabled = enabled; wrapWithOutlines(); } public void setOutlineColor(int color) { sOutlineColor = color; } private void wrapWithOutlines() { for (int i = 0; i < getChildCount(); i++) { View v = getChildAt(i); if (!(v instanceof OutlineContainer)) { removeView(v); super.addView(wrapChild(v), i); } } } private View wrapChild(View child) { if (!mOutlineEnabled || child instanceof OutlineContainer) return child; OutlineContainer out = new OutlineContainer(getContext()); out.setLayoutParams(generateDefaultLayoutParams()); child.setLayoutParams(new OutlineContainer.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); out.addView(child); return out; } public void addView(View child) { super.addView(wrapChild(child)); } public void addView(View child, int index) { super.addView(wrapChild(child), index); } public void addView(View child, LayoutParams params) { super.addView(wrapChild(child), params); } public void addView(View child, int width, int height) { super.addView(wrapChild(child), width, height); } public void addView(View child, int index, LayoutParams params) { super.addView(wrapChild(child), index, params); } @Override public boolean onInterceptTouchEvent(MotionEvent arg0) { return mEnabled ? super.onInterceptTouchEvent(arg0) : false; } private State mState; private int oldPage; private View mLeft; private View mRight; private float mRot; private float mTrans; private float mScale; private enum State { IDLE, GOING_LEFT, GOING_RIGHT } private void logState(View v, String title) { Log.v(TAG, title + ": ROT (" + ViewHelper.getRotation(v) + ", " + ViewHelper.getRotationX(v) + ", " + ViewHelper.getRotationY(v) + "), TRANS (" + ViewHelper.getTranslationX(v) + ", " + ViewHelper.getTranslationY(v) + "), SCALE (" + ViewHelper.getScaleX(v) + ", " + ViewHelper.getScaleY(v) + "), ALPHA " + ViewHelper.getAlpha(v)); } protected void animateScroll(int position, float positionOffset) { if (mState != State.IDLE) { mRot = (float)(1-Math.cos(2*Math.PI*positionOffset))/2*30.0f; ViewHelper.setRotationY(this, mState == State.GOING_RIGHT ? mRot : -mRot); ViewHelper.setPivotX(this, getMeasuredWidth()*0.5f); ViewHelper.setPivotY(this, getMeasuredHeight()*0.5f); } } protected void animateTablet(View left, View right, float positionOffset) { if (mState != State.IDLE) { if (left != null) { manageLayer(left, true); mRot = 30.0f * positionOffset; mTrans = getOffsetXForRotation(mRot, left.getMeasuredWidth(), left.getMeasuredHeight()); ViewHelper.setPivotX(left, left.getMeasuredWidth()/2); ViewHelper.setPivotY(left, left.getMeasuredHeight()/2); ViewHelper.setTranslationX(left, mTrans); ViewHelper.setRotationY(left, mRot); logState(left, "Left"); } if (right != null) { manageLayer(right, true); mRot = -30.0f * (1-positionOffset); mTrans = getOffsetXForRotation(mRot, right.getMeasuredWidth(), right.getMeasuredHeight()); ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f); ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f); ViewHelper.setTranslationX(right, mTrans); ViewHelper.setRotationY(right, mRot); logState(right, "Right"); } } } private void animateCube(View left, View right, float positionOffset, boolean in) { if (mState != State.IDLE) { if (left != null) { manageLayer(left, true); mRot = (in ? 90.0f : -90.0f) * positionOffset; ViewHelper.setPivotX(left, left.getMeasuredWidth()); ViewHelper.setPivotY(left, left.getMeasuredHeight()*0.5f); ViewHelper.setRotationY(left, mRot); } if (right != null) { manageLayer(right, true); mRot = -(in ? 90.0f : -90.0f) * (1-positionOffset); ViewHelper.setPivotX(right, 0); ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f); ViewHelper.setRotationY(right, mRot); } } } private void animateAccordion(View left, View right, float positionOffset) { if (mState != State.IDLE) { if (left != null) { manageLayer(left, true); ViewHelper.setPivotX(left, left.getMeasuredWidth()); ViewHelper.setPivotY(left, 0); ViewHelper.setScaleX(left, 1-positionOffset); } if (right != null) { manageLayer(right, true); ViewHelper.setPivotX(right, 0); ViewHelper.setPivotY(right, 0); ViewHelper.setScaleX(right, positionOffset); } } } private void animateZoom(View left, View right, float positionOffset, boolean in) { if (mState != State.IDLE) { if (left != null) { manageLayer(left, true); mScale = in ? ZOOM_MAX + (1-ZOOM_MAX)*(1-positionOffset) : 1+ZOOM_MAX - ZOOM_MAX*(1-positionOffset); ViewHelper.setPivotX(left, left.getMeasuredWidth()*0.5f); ViewHelper.setPivotY(left, left.getMeasuredHeight()*0.5f); ViewHelper.setScaleX(left, mScale); ViewHelper.setScaleY(left, mScale); } if (right != null) { manageLayer(right, true); mScale = in ? ZOOM_MAX + (1-ZOOM_MAX)*positionOffset : 1+ZOOM_MAX - ZOOM_MAX*positionOffset; ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f); ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f); ViewHelper.setScaleX(right, mScale); ViewHelper.setScaleY(right, mScale); } } } private void animateRotate(View left, View right, float positionOffset, boolean up) { if (mState != State.IDLE) { if (left != null) { manageLayer(left, true); mRot = (up ? 1 : -1) * (ROT_MAX * positionOffset); mTrans = (up ? -1 : 1) * (float) (getMeasuredHeight() - getMeasuredHeight()*Math.cos(mRot*Math.PI/180.0f)); ViewHelper.setPivotX(left, left.getMeasuredWidth()*0.5f); ViewHelper.setPivotY(left, up ? 0 : left.getMeasuredHeight()); ViewHelper.setTranslationY(left, mTrans); ViewHelper.setRotation(left, mRot); } if (right != null) { manageLayer(right, true); mRot = (up ? 1 : -1) * (-ROT_MAX + ROT_MAX*positionOffset); mTrans = (up ? -1 : 1) * (float) (getMeasuredHeight() - getMeasuredHeight()*Math.cos(mRot*Math.PI/180.0f)); ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f); ViewHelper.setPivotY(right, up ? 0 : right.getMeasuredHeight()); ViewHelper.setTranslationY(right, mTrans); ViewHelper.setRotation(right, mRot); } } } private void animateFlipHorizontal(View left, View right, float positionOffset, int positionOffsetPixels) { if (mState != State.IDLE) { if (left != null) { manageLayer(left, true); mRot = 180.0f * positionOffset; if (mRot > 90.0f) { left.setVisibility(View.INVISIBLE); } else { if (left.getVisibility() == View.INVISIBLE) left.setVisibility(View.VISIBLE); mTrans = positionOffsetPixels; ViewHelper.setPivotX(left, left.getMeasuredWidth()*0.5f); ViewHelper.setPivotY(left, left.getMeasuredHeight()*0.5f); ViewHelper.setTranslationX(left, mTrans); ViewHelper.setRotationY(left, mRot); } } if (right != null) { manageLayer(right, true); mRot = -180.0f * (1-positionOffset); if (mRot < -90.0f) { right.setVisibility(View.INVISIBLE); } else { if (right.getVisibility() == View.INVISIBLE) right.setVisibility(View.VISIBLE); mTrans = -getWidth()-getPageMargin()+positionOffsetPixels; ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f); ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f); ViewHelper.setTranslationX(right, mTrans); ViewHelper.setRotationY(right, mRot); } } } } private void animateFlipVertical(View left, View right, float positionOffset, int positionOffsetPixels) { if(mState != State.IDLE) { if (left != null) { manageLayer(left, true); mRot = 180.0f * positionOffset; if (mRot > 90.0f) { left.setVisibility(View.INVISIBLE); } else { if (left.getVisibility() == View.INVISIBLE) left.setVisibility(View.VISIBLE); mTrans = positionOffsetPixels; ViewHelper.setPivotX(left, left.getMeasuredWidth()*0.5f); ViewHelper.setPivotY(left, left.getMeasuredHeight()*0.5f); ViewHelper.setTranslationX(left, mTrans); ViewHelper.setRotationX(left, mRot); } } if (right != null) { manageLayer(right, true); mRot = -180.0f * (1-positionOffset); if (mRot < -90.0f) { right.setVisibility(View.INVISIBLE); } else { if (right.getVisibility() == View.INVISIBLE) right.setVisibility(View.VISIBLE); mTrans = -getWidth()-getPageMargin()+positionOffsetPixels; ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f); ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f); ViewHelper.setTranslationX(right, mTrans); ViewHelper.setRotationX(right, mRot); } } } } protected void animateStack(View left, View right, float positionOffset, int positionOffsetPixels) { if (mState != State.IDLE) { if (right != null) { manageLayer(right, true); mScale = (1-SCALE_MAX) * positionOffset + SCALE_MAX; mTrans = -getWidth()-getPageMargin()+positionOffsetPixels; ViewHelper.setScaleX(right, mScale); ViewHelper.setScaleY(right, mScale); ViewHelper.setTranslationX(right, mTrans); } if (left != null) { left.bringToFront(); } } } private void manageLayer(View v, boolean enableHardware) { if (!API_11) return; int layerType = enableHardware ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE; if (layerType != v.getLayerType()) v.setLayerType(layerType, null); } private void disableHardwareLayer() { if (!API_11) return; View v; for (int i = 0; i < getChildCount(); i++) { v = getChildAt(i); if (v.getLayerType() != View.LAYER_TYPE_NONE) v.setLayerType(View.LAYER_TYPE_NONE, null); } } private Matrix mMatrix = new Matrix(); private Camera mCamera = new Camera(); private float[] mTempFloat2 = new float[2]; protected float getOffsetXForRotation(float degrees, int width, int height) { mMatrix.reset(); mCamera.save(); mCamera.rotateY(Math.abs(degrees)); mCamera.getMatrix(mMatrix); mCamera.restore(); mMatrix.preTranslate(-width * 0.5f, -height * 0.5f); mMatrix.postTranslate(width * 0.5f, height * 0.5f); mTempFloat2[0] = width; mTempFloat2[1] = height; mMatrix.mapPoints(mTempFloat2); return (width - mTempFloat2[0]) * (degrees > 0.0f ? 1.0f : -1.0f); } protected void animateFade(View left, View right, float positionOffset) { if (left != null) { ViewHelper.setAlpha(left, 1-positionOffset); } if (right != null) { ViewHelper.setAlpha(right, positionOffset); } } protected void animateOutline(View left, View right) { if (!(left instanceof OutlineContainer)) return; if (mState != State.IDLE) { if (left != null) { manageLayer(left, true); ((OutlineContainer)left).setOutlineAlpha(1.0f); } if (right != null) { manageLayer(right, true); ((OutlineContainer)right).setOutlineAlpha(1.0f); } } else { if (left != null) ((OutlineContainer)left).start(); if (right != null) ((OutlineContainer)right).start(); } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if (mState == State.IDLE && positionOffset > 0) { oldPage = getCurrentItem(); mState = position == oldPage ? State.GOING_RIGHT : State.GOING_LEFT; } boolean goingRight = position == oldPage; if (mState == State.GOING_RIGHT && !goingRight) mState = State.GOING_LEFT; else if (mState == State.GOING_LEFT && goingRight) mState = State.GOING_RIGHT; float effectOffset = isSmall(positionOffset) ? 0 : positionOffset; // mLeft = getChildAt(position);// mRight = getChildAt(position+1); mLeft = findViewFromObject(position); mRight = findViewFromObject(position+1); if (mFadeEnabled) animateFade(mLeft, mRight, effectOffset); if (mOutlineEnabled) animateOutline(mLeft, mRight); switch (mEffect) { case Standard: break; case Tablet: animateTablet(mLeft, mRight, effectOffset); break; case CubeIn: animateCube(mLeft, mRight, effectOffset, true); break; case CubeOut: animateCube(mLeft, mRight, effectOffset, false); break; case FlipVertical: animateFlipVertical(mLeft, mRight, positionOffset, positionOffsetPixels); break; case FlipHorizontal: animateFlipHorizontal(mLeft, mRight, effectOffset, positionOffsetPixels); case Stack: animateStack(mLeft, mRight, effectOffset, positionOffsetPixels); break; case ZoomIn: animateZoom(mLeft, mRight, effectOffset, true); break; case ZoomOut: animateZoom(mLeft, mRight, effectOffset, false); break; case RotateUp: animateRotate(mLeft, mRight, effectOffset, true); break; case RotateDown: animateRotate(mLeft, mRight, effectOffset, false); break; case Accordion: animateAccordion(mLeft, mRight, effectOffset); break; } super.onPageScrolled(position, positionOffset, positionOffsetPixels); if (effectOffset == 0) { disableHardwareLayer(); mState = State.IDLE; } } private boolean isSmall(float positionOffset) { return Math.abs(positionOffset) < 0.0001; } public void setObjectForPosition(Object obj, int position) { mObjs.put(Integer.valueOf(position), obj); } public View findViewFromObject(int position) { Object o = mObjs.get(Integer.valueOf(position)); if (o == null) { return null; } PagerAdapter a = getAdapter(); View v; for (int i = 0; i < getChildCount(); i++) { v = getChildAt(i); if (a.isViewFromObject(v, o)) return v; } return null; } }
到这我们的自定义ViewPage就结束了。下面来看我们的PageAdapter呢 ! 要实支持那么多功能adapter的逻辑可定不会简单。同上解释在代码里。
/** * @author zhengzaihong */public class ViewPageAdapter extends PagerAdapter{ private Context context; private ImageView[] imageviews; private int mImg[]; private List<String> listUrl; private ZZHViewPager viewpage; private SelectImageType enumtype = SelectImageType.NETWORK;; private ImageView.ScaleType scaleType; private boolean isreverse=false; private boolean isend=false; private ImageView tips[]; private ViewGroup viewGroup; private int[] dots; private int beginPosition; private int returnPosition=0; private int allsize=0; public Timer timer = new Timer(); //这里采用线程池 原因:如果你采用的TimerTask方式 就得考虑两点问题:1 如果采用Timer 而Timer只会创建一个线程并且不会捕获异常,因此当TimerTask抛出未检查的异常时将会终止Timer。 // 这种情形下,Timer将因无法恢复线程执行行,而是错误地促使整个Timer被取消了,那么整个定时任务就无法调度来。 //SingleThreadScheduledExecutor不会有这些问题,当线程池中的唯一线程因特殊原因挂掉,线程池会自动开启一个新线程,保证定时任务继续。 public static ScheduledExecutorService scheduledexecutorservice = Executors.newSingleThreadScheduledExecutor();; /** * @param enumtype 图片来源类型 NETWORK:网络图片,APPID:资源图片id类型,LOCATION:手机存储图片 * 此方法一定是在setadapter()之前调用 否则会报错 */ public enum SelectImageType { NETWORK, APPID, LOCATION } public void setImageType(SelectImageType enumtype){ this.enumtype=enumtype; initImageView(); } /** *@param scaleType 图片的缩放模式(不建议使用该方法) */ public void setImageScaleType(ImageView.ScaleType scaleType){ this.scaleType=scaleType; initImageView(); } /** * @see 是否支持显示提示点 * @param viewGroup 装提示点的容器 此处采用的是linerlayout 可方便用户自定义 提示点的位置在 完全交给用户在xml文件中配置 * @param dots 装有选中和没选中的两张图片 */ public void showTips(ViewGroup viewGroup,int dots[]){ this.viewGroup=viewGroup; this.dots=dots; if(enumtype==SelectImageType.NETWORK ||enumtype==SelectImageType.LOCATION){ creatDot(listUrl.size()); }else if(enumtype==SelectImageType.APPID){ creatDot(mImg.length); } } /** * @param howlong 设置多少秒翻页 * @param isreverse 设置是否顺序轮播 true表示在轮播到最后一页时倒着轮播回来 false表示每次轮播完毕都从开始位置起。 */ public void startChangePage(int howlong,final boolean isreverse){ this.isreverse=isreverse; scheduledexecutorservice.scheduleAtFixedRate(new Runnable() { @Override public void run() { handler.sendEmptyMessage(0X1515); } },howlong*1000,howlong*1000, TimeUnit.MILLISECONDS); } //这段逻辑复杂了点 劲量看吧。此处待优化,后期处理。。 Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { if(!(ZZHViewPager.mIsTouching)){ if(isreverse){ if(beginPosition==(allsize-1)){ isend=true; beginPosition--; }else{ if(beginPosition==0){ beginPosition++; isend=false; }else{ if(isend){ beginPosition--; }else{ beginPosition++; } } } }else{ beginPosition++; } int position = 0; if(enumtype==SelectImageType.NETWORK ||enumtype==SelectImageType.LOCATION){ position=beginPosition % listUrl.size(); }else if(enumtype==SelectImageType.APPID){ position=beginPosition % mImg.length; } if(isreverse){ if(beginPosition==allsize){ beginPosition = returnPosition+1; } } viewpage.setCurrentItem(position); } }; }; /** * @param context 上下文 * @param viewpage viewpage传进来 * @param mImg 资源图片id */ public ViewPageAdapter(Context context,ZZHViewPager viewpage,int mImg[]){ this.context=context; this.viewpage=viewpage; this.mImg=mImg; } /** * @param context 上下文 * @param viewpage viewpage传进来 * @param listUrl 网络图片地址集合 */ public ViewPageAdapter(Context context,ZZHViewPager viewpage,List<String> listUrl){ this.context=context; this.viewpage=viewpage; this.listUrl=listUrl; } private void initImageView(){ int length=0; if(enumtype==SelectImageType.NETWORK ||enumtype==SelectImageType.LOCATION){ length=listUrl.size(); }else if(enumtype==SelectImageType.APPID){ length=mImg.length; } allsize =length; imageviews = new ImageView[length]; for(int i=0;i<length;i++){ ImageView imageView = new ImageView(context); if( scaleType instanceof ImageView.ScaleType && scaleType !=null){ imageView.setScaleType(scaleType); } imageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { listener.setImageOnclikliseter(returnPosition,allsize); } }); imageviews[i]=imageView; } } @Override public Object instantiateItem(ViewGroup container, final int position) { ImageView imageView =imageviews[position]; beginPosition=position-1; try{ switch (enumtype) { case NETWORK: Util.drowNetWorkImage(listUrl.get(position), imageView); break; case APPID: imageView.setBackgroundResource(mImg[position]);//如果是资源图片就直接设置背景了 break; case LOCATION: Util.drowLocationImage(listUrl.get(position), imageView); break; } }catch(Exception e){ e.printStackTrace(); } container.addView(imageView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); viewpage.setObjectForPosition(imageView, position); return imageView; } @Override public void destroyItem(ViewGroup container, int position, Object obj) { container.removeView(viewpage.findViewFromObject(position)); } @Override public int getCount() { if(enumtype==SelectImageType.NETWORK ||enumtype==SelectImageType.LOCATION){ return listUrl.size(); }else if(enumtype==SelectImageType.APPID){ return mImg.length; } return 0; } @Override public boolean isViewFromObject(View view, Object obj) { if (view instanceof OutlineContainer) { return ((OutlineContainer) view).getChildAt(0) == obj; } else { return view == obj; } } /* * 初始化 提示点数量 */ private void creatDot(int size){ setViewPageChangeListener(); tips = new ImageView[size]; for (int i = 0; i < tips.length; i++) { ImageView imageView = new ImageView(context); imageView.setLayoutParams(new ViewGroup.LayoutParams(15, 15)); tips[i] = imageView; if (i == 0) { tips[i].setBackgroundResource(dots[0]); } else { tips[i].setBackgroundResource(dots[1]); } LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); layoutParams.leftMargin = 8; layoutParams.rightMargin = 8; viewGroup.addView(imageView, layoutParams); } } @SuppressWarnings("deprecation") private void setViewPageChangeListener() { viewpage.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { setTipsBackgroud(position, dots); returnPosition=position; } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageScrollStateChanged(int position) { } }); } /* * 让图片和提示点联动 */ private void setTipsBackgroud(int position, int dot[]) { for (int i = 0; i < tips.length; i++) { if (i == position) { tips[i].setBackgroundResource(dot[0]); } else { tips[i].setBackgroundResource(dot[1]); } } } private ImageClickLstener listener; /** * @see 为每张图片添加点击事件 返回当前的图片位置 和总的图片数 * @param 传进来 ImageClickLstener监听对象 */ public void setOnclikListener(ImageClickLstener listener){ this.listener=listener; } public interface ImageClickLstener{ void setImageOnclikliseter(int returnPosition,int allsize); }}
好了真正的核心代码已经完成了,仔细看的童鞋们是不发现在上面分析的7点在代码里都作出了解释呢?
接下来看下另外两个辅助类吧。首先上我们的动画辅助类!
public class OutlineContainer extends FrameLayout implements Animatable { private Paint mOutlinePaint; private boolean mIsRunning = false; private long mStartTime; private float mAlpha = 1.0f; private static final long ANIMATION_DURATION = 500; private static final long FRAME_DURATION = 1000 / 60; private final Interpolator mInterpolator = new Interpolator() { public float getInterpolation(float t) { t -= 1.0f; return t * t * t + 1.0f; } }; public OutlineContainer(Context context) { super(context); init(); } public OutlineContainer(Context context, AttributeSet attrs) { super(context, attrs); init(); } public OutlineContainer(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { mOutlinePaint = new Paint(); mOutlinePaint.setAntiAlias(true); mOutlinePaint.setStrokeWidth(Util.dpToPx(getResources(), 2)); mOutlinePaint.setColor(getResources().getColor(R.color.holo_blue)); mOutlinePaint.setStyle(Style.STROKE); int padding = Util.dpToPx(getResources(), 10); setPadding(padding, padding, padding, padding); } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); int offset = Util.dpToPx(getResources(), 5); if (mOutlinePaint.getColor() != ZZHViewPager.sOutlineColor) { mOutlinePaint.setColor(ZZHViewPager.sOutlineColor); } mOutlinePaint.setAlpha((int)(mAlpha * 255)); Rect rect = new Rect(offset, offset, getMeasuredWidth()-offset, getMeasuredHeight()-offset); canvas.drawRect(rect, mOutlinePaint); } public void setOutlineAlpha(float alpha) { mAlpha = alpha; } @Override public boolean isRunning() { return mIsRunning; } @Override public void start() { if (mIsRunning) return; mIsRunning = true; mStartTime = AnimationUtils.currentAnimationTimeMillis(); post(mUpdater); } @Override public void stop() { if (!mIsRunning) return; mIsRunning = false; } private final Runnable mUpdater = new Runnable() { @Override public void run() { long now = AnimationUtils.currentAnimationTimeMillis(); long duration = now - mStartTime; if (duration >= ANIMATION_DURATION) { mAlpha = 0.0f; invalidate(); stop(); return; } else { mAlpha = mInterpolator.getInterpolation(1 - duration / (float) ANIMATION_DURATION); invalidate(); } postDelayed(mUpdater, FRAME_DURATION); } };}
好了动画辅助类完了,然后是图片加载类了,这里就没用自己动手写图片加载类了,偷个懒下面是利用第三方 Universal-Image-Loader做了个超简单的util,更多的配置请查阅官网。
public class Util { public static int dpToPx(Resources res, int dp) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics()); } public static void initImagLoad(Context context){ File cacheDir = StorageUtils.getOwnCacheDirectory(context, "imageloader/Cache"); ImageLoader imageLoader = ImageLoader.getInstance(); if (!imageLoader.isInited()) { ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(context) .defaultDisplayImageOptions(new DisplayImageOptions.Builder().build()) // .discCache(new UnlimitedDiscCache(cacheDir))//自定义缓存路径 .build(); imageLoader.init(configuration); } } public static void drowLocationImage(String uri, ImageView image) { displayImage("file://"+uri, image); } public static void drowNetWorkImage(String uri, ImageView image) { displayImage(uri, image); } public static void displayImage(String uri, ImageView imageView) { displayImage(uri, imageView, new SimpleImageLoadingListener()); } public static void displayImage(String uri, ImageView image, DisplayImageOptions options) { ImageLoader imageLoader = ImageLoader.getInstance(); imageLoader.displayImage(uri, image, options); } public static void displayImage(String uri, ImageView imageView, ImageLoadingListener imageLoadingListener) { displayImage(uri, imageView, imageLoadingListener, false); } public static void displayImage(String uri, ImageView imageView, ImageLoadingListener imageLoadingListener, boolean isFadeIn) { ImageLoader imageLoader = ImageLoader.getInstance(); if (!TextUtils.isEmpty(uri) && (uri.startsWith("/mnt/sdcard") || uri.startsWith("/storage"))) { uri = "file://".concat(uri); } imageLoader.displayImage(uri, imageView, imageLoadingListener); } public static void displayImage(String uri, ImageView imageView, boolean isFadeIn) { displayImage(uri, imageView, new SimpleImageLoadingListener() { }, isFadeIn); }好了辅助类也完了。还有个就是我们的属性文件了,下面给出.xml文件
<declare-styleable name="ViewPager"> <attr name="style"> <enum name="standard" value="0" /> <enum name="tablet" value="1" /> <enum name="cubein" value="2" /> <enum name="cubeout" value="3" /> <enum name="flipvertical" value="4" /> <enum name="fliphorizontal" value="5" /> <enum name="stack" value="6" /> <enum name="zoomin" value="7" /> <enum name="zoomout" value="8" /> <enum name="rotateup" value="9" /> <enum name="rotatedown" value="10" /> <enum name="accordion" value="11" /> </attr> <attr name="fadeEnabled" format="boolean" /> <attr name="outlineEnabled" format="boolean" /> <attr name="outlineColor" format="color|reference" /></declare-styleable>说下我们定义属性文件还是规范下呀。虽然attrs在底部是给你包装好了<declare-styleable> 标签,虽然可以不用写这玩意,我们还是要做到规范化,也把属性模块化了,很清楚哪些属性是哪个的,公共的你可以提出来。看也一目了然。不然多了你会昏的.......
好了到此文章就全部结束了。谢谢观读!欢迎指出待优化的部分。谢谢O(∩_∩)O~
本文用到的了nineoldandroids-2.4.0和universal-image-loader-1.9.2两个jar夹包 可以去百度下载或者点击下面链接http://download.csdn.net/detail/u014239140/9639219
- 打造史上最简单的广告轮播图Banner
- 打造一个轻量级,简单,易用的Android Banner框架
- Banner轮播图的简单使用
- 自定义的android 广告banner
- Android 自定义Banner广告轮播图
- BSYBannerScrollview,最简单的Banner轮播图控件
- Android 轮播图Banner的简单实现
- 简单易用的轮播图控件Banner
- 一个简单的banner
- Banner简单的使用
- Banner的简单使用
- Banner的简单实用
- Banner简单的使用
- banner的简单使用
- Banner的简单实现
- Banner的简单使用
- 【FirstKotlinApp】使用Kotlin实现简单的Banner广告条(一)
- 【FirstKotlinApp】使用Kotlin实现简单的Banner广告条(二):Indicator指示器实现
- 各种图片编码格式详解
- hihocode #1385 : A Simple Job
- 周末轻松一刻,欣赏完全由程序自己回忆的视频片段
- python学习之 requests库
- load-on-startup在web.xml中的含义
- 打造史上最简单的广告轮播图Banner
- 光束平差(Bundle Adjustment)算法
- Lowest Common Ancestor of a Binary Tree
- 在Eclipse中显示.project, .classpath, .gitignore文件和.setting文件夹
- 线性表之单链表的c++实现
- ./arch/arm/include/asm/barriers.h:33:24: error: operator '>=' has no left operand
- 0005-每日一记(2016-09-25)
- 科普小知识——音频编码
- html常用标签