本文非技术类文章,博主只是想分享这样的一种实现方法,帮助有需要的开发人员减少工作量。我是学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下载去下载!打开如意门!