本文非技术类文章,博主只是想分享这样的一种实现方法,帮助有需要的开发人员减少工作量。我是学java出身的,做开发2年了,很理解一句话:工欲善其事必先利其器。
继另一篇博文:[Android初级]可自动切换、无限滑动的广告栏的实现 ,我觉得还有更好的方式来展示,这个比较合适更多开发人员。
本次实现的demo,用到了第三方的开源框架:1.JazzyViewPager https://github.com/jfeinstein10/JazzyViewPager(主要用它,效果比较多)
2.universal-image-loader(这个不说了)
下图为demo结构:
先看看是不是你想要的效果:
1.框架代码不多,算的上精简,有兴趣的自行研究。下面是主要的widget:JazzyViewPager.java,请自行下载。
public class JazzyViewPager extends ViewPager { public static final String TAG = "JazzyViewPager"; 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 enum TransitionEffect { Standard, Tablet, CubeIn, CubeOut, FlipVertical, FlipHorizontal, Stack, ZoomIn, ZoomOut, RotateUp, RotateDown, Accordion } public JazzyViewPager(Context context) { this(context, null); } @SuppressWarnings("incomplete-switch") public JazzyViewPager(Context context, AttributeSet attrs) { super(context, attrs); setClipChildren(false); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.JazzyViewPager); int effect = ta.getInt(R.styleable.JazzyViewPager_style, 0); String[] transitions = getResources().getStringArray( R.array.jazzy_effects); setTransitionEffect(TransitionEffect.valueOf(transitions[effect])); setFadeEnabled(ta.getBoolean(R.styleable.JazzyViewPager_fadeEnabled, false)); setOutlineEnabled(ta.getBoolean( R.styleable.JazzyViewPager_outlineEnabled, false)); setOutlineColor(ta.getColor(R.styleable.JazzyViewPager_outlineColor, Color.WHITE)); switch (mEffect) { case Stack: case ZoomOut: setFadeEnabled(true); } ta.recycle(); } 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) { 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) { 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) { 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) { 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) { ViewHelper.setPivotX(left, left.getMeasuredWidth()); ViewHelper.setPivotY(left, 0); ViewHelper.setScaleX(left, 1 - positionOffset); } if (right != null) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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 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) { ((OutlineContainer) left).setOutlineAlpha(1.0f); } if (right != null) { ((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) { 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; } }2.主要的使用和实现,这里的思路就是利用Viewpager来展示imageView,切换效果是做一个延迟的循环调用方法如:handler.sendEmptyMessageDelayed 和handlerMessage方法配合使用。小圆圈的通过viewpager的index来同步自身的设置。是不是很简单,具体看代码“:
主布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <RelativeLayout android:layout_width="fill_parent" android:layout_height="130dp" > <org.jan.adverpaper.widget.JazzyViewPager android:id="@+id/adviewpaper" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <!-- <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/jd_ad_1" /> --> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:gravity="center" android:layout_marginBottom="5dp" android:orientation="horizontal" > <LinearLayout android:id="@+id/symblo_container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > </LinearLayout> </LinearLayout> </RelativeLayout> </LinearLayout>javaCode:MainActivity.java
public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private static int PAGER_START_PLAY = 0x123; //切换间隔时间3秒 private static final int PLAY_TIME = 3 * 1000; //实现viewpager的控件 private JazzyViewPager mViewPaper; //圆形标签的父层 private LinearLayout symbolContainer; private ImageView[] images; private ImageView[] circleSymbols; private ArrayList<String> imageUrlList; //图片框架universalimageloader的图形帮助类 private ImageLoader mImageLoader; private Handler mHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImageLoader = ImageLoader.getInstance(); initMockImages(); setupMyHandler(); initViews(); } private void setupMyHandler() { mHandler = new Handler() { @Override public void handleMessage(Message msg) { if (PAGER_START_PLAY == msg.what) { Log.d(TAG, "----PAGER_START_PLAY-----"); int current = mViewPaper.getCurrentItem(); if (current == images.length - 1) { current = -1; } Log.d(TAG, "play item = " + current); mViewPaper.setCurrentItem(current + 1); mHandler.sendEmptyMessageDelayed(PAGER_START_PLAY, PLAY_TIME); } } }; } private void initViews() { symbolContainer = (LinearLayout) findViewById(R.id.symblo_container); circleSymbols = new ImageView[imageUrlList.size()]; images = new ImageView[imageUrlList.size()]; for (int i = 0; i < imageUrlList.size(); i++) { ImageView imageView = new ImageView(this); ImageView circle = new ImageView(this); imageView.setScaleType(ScaleType.CENTER_CROP); images[i] = imageView; LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); lp.setMargins(3, 0, 3,0); circle.setLayoutParams(lp); circle.setTag(i); circle.setBackgroundDrawable(getResources().getDrawable(R.drawable.circle_normal)); circleSymbols[i] = circle; symbolContainer.addView(circleSymbols[i]); } setViewPager(TransitionEffect.Standard); } private void setViewPager(TransitionEffect effect) { mViewPaper = (JazzyViewPager) findViewById(R.id.adviewpaper); mViewPaper.setTransitionEffect(effect); mViewPaper.setAdapter(new MyPagerAdapter()); mViewPaper.setOnPageChangeListener(new MyPageViewChangeListener()); mViewPaper.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (imageUrlList.size() == 0 || imageUrlList.size() == 1) { return true; } else { return false; } } }); circleSymbols[0].setBackgroundDrawable(getResources().getDrawable(R.drawable.circle_selected)); mViewPaper.setCurrentItem(0); mHandler.sendEmptyMessageDelayed(PAGER_START_PLAY, PLAY_TIME); } /** * 创建本地图片数据 */ private void initMockImages() { imageUrlList = new ArrayList<String>(); imageUrlList.add("drawable://" + R.drawable.jd_ad_0); imageUrlList.add("drawable://" + R.drawable.jd_ad_1); imageUrlList.add("drawable://" + R.drawable.jd_ad_2); imageUrlList.add("drawable://" + R.drawable.jd_ad_3); imageUrlList.add("drawable://" + R.drawable.jd_ad_4); } /** * 设置圆形标签的状态 * @param index 当前标签的位置 */ private void setSymbolImages(int index){ for(ImageView image:circleSymbols){ Integer i = (Integer) image.getTag(); if(i==index){ image.setBackgroundDrawable(getResources().getDrawable(R.drawable.circle_selected)); }else{ image.setBackgroundDrawable(getResources().getDrawable(R.drawable.circle_normal)); } } } @Override protected void onDestroy() { super.onDestroy(); } private class MyPagerAdapter extends PagerAdapter { @Override public int getCount() { return imageUrlList.size(); } @Override public boolean isViewFromObject(View view, Object obj) { if (view instanceof OutlineContainer) { return ((OutlineContainer) view).getChildAt(0) == obj; } else { return view == obj; } } @Override public void destroyItem(ViewGroup container, int position, Object object) { ((ViewPager) container).removeView(mViewPaper .findViewFromObject(position)); } @Override public Object instantiateItem(ViewGroup container, int position) { mImageLoader.displayImage(imageUrlList.get(position), images[position]); container.addView(images[position], LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); final int index = position; images[position].setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Log.e(TAG, "you clicked images position is" + index); Toast.makeText(MainActivity.this, "你点击了第"+(index+1)+"张图", Toast.LENGTH_SHORT).show(); } }); // 注意!不加这个方法要报IllegalStateException mViewPaper.setObjectForPosition(images[position], position); return images[position]; } } private class MyPageViewChangeListener implements OnPageChangeListener { @Override public void onPageScrollStateChanged(int stateCode) { switch (stateCode) { case 0: // 你什么都没动 break; case 1: // 正在滑动哦 break; case 2: // 滑动完了 break; } } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int position) { Log.d(TAG, "onPageSelected-->position:" + position); setSymbolImages(position); } } }
最后附上demo下载去下载!打开如意门!