轮播图 可以实现动图gif 滑动切换动态效果展示, 一个自定义的飘落雪花的功能,(让我用来实现下红包雨的功能了)
废话不多说 直接 上图
image
image.gif
image
image.gif
上面轮播图 可以切换滑动效果, 有很多种滑动,自己去试吧(可能在处理滑动的时候没有考虑动图优化, 有点小卡顿, 如果有兴趣就自己看看源码)
下面是切换滑动特效
private void switchAnimation() {
try {
if (!mPresenter.getTransformerData().isEmpty()) {
if (mPresenter.getTransformerData().size() == index) {
index = 0;
}
mTransforemerName = mPresenter.getTransformerData().get(index);
Class cls = Class.forName("com.ToxicBakery.viewpager.transforms." + mTransforemerName);
mTransforemer = (ABaseTransformer) cls.newInstance();
mBanner.setPageTransformer(mTransforemer);
mBanner.getViewPager().setPageTransformer(true, mTransforemer);
//部分3D特效需要调整滑动速度
if (mTransforemerName.equals("StackTransformer")) {
mBanner.setScrollDuration(1200);
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
image.gif
然后是设置banner数据
@Override
public void refreshData(List<String> data) {
if (!mPresenter.isDataMissing()) return;
switchAnimation();
mBanner.setPages(new CBViewHolderCreator<ViewHolder>() {
@Override
public ViewHolder createHolder() {
return new ViewHolder();
}
}, data).setPageIndicator(new int[]{R.drawable.ic_page_indicator, R.drawable.ic_page_indicator_focused})
.setPageIndicatorAlign(ConvenientBanner.PageIndicatorAlign.ALIGN_PARENT_RIGHT)
.setPageTransformer(mTransforemer)
.startTurning(3000);
}
image.gif
还有个实现类ViewHolder 需要实现Holder
public class ViewHolder implements Holder<String> {
private GifImageView imageView;
@Override
public View createView(Context context) {
imageView = new GifImageView(context);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
return imageView;
}
@Override
public void UpdateUI(Context context, int position, String data) {
if (data.length() > 3) {
if (data.substring(data.length() - 3).equals("gif")) {
try {
byte[] bytes = new GifDataAsyncTask().execute(data).get();
imageView.setBytes(bytes);
imageView.startAnimation();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
Picasso.with(context).load(data).into(imageView);
}
}
}
}
image.gif
以上基本就是轮播图了, 还算是比较简单
下面说一下 下红包雨的功能
两种实现方式, 都是自定义类
一种继承 SurfaceView 实现 SurfaceHolder.Callback 方法
public class Snow extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private SnowFlake[] mFlakes;
private int mViewWidth = 200;
private int mViewHeight = 100;
private int mFlakeCount = 20;
private int mMinSize = 50;
private int mMaxSize = 70;
private int mSpeedX = 10;
private int mSpeedY = 20;
private Bitmap mSnowBitmap = null;
private boolean mStart = false;
public Snow(Context context) {
this(context, null);
}
public Snow(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public Snow(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initHolder();
setZOrderOnTop(true);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.Snow, defStyleAttr, 0);
int cnt = array.getIndexCount();
for (int i = 0; i < cnt; i++) {
int attr = array.getIndex(i);
switch (attr) {
case R.styleable.Snow_flakeCount:
mFlakeCount = array.getInteger(attr, 0);
break;
case R.styleable.Snow_minSize:
mMinSize = array.getInteger(attr, 50);
break;
case R.styleable.Snow_maxSize:
mMaxSize = array.getInteger(attr, 70);
break;
case R.styleable.Snow_flakeSrc:
Integer srcId = array.getResourceId(attr, R.drawable.snow_flake);
mSnowBitmap = BitmapFactory.decodeResource(getResources(), srcId);
break;
case R.styleable.Snow_speedX:
mSpeedX = array.getInteger(attr, 10);
break;
case R.styleable.Snow_speedY:
mSpeedY = array.getInteger(attr, 10);
break;
default:
break;
}
}
if (mMinSize > mMaxSize) {
mMaxSize = mMinSize;
}
array.recycle();
}
private void initHolder() {
mHolder = this.getHolder();
mHolder.setFormat(PixelFormat.TRANSLUCENT);
mHolder.addCallback(this);
}
private void initSnowFlakes() {
mFlakes = new SnowFlake[mFlakeCount];
boolean isRightDir = new Random().nextBoolean();
for (int i = 0; i < mFlakes.length; i++) {
mFlakes[i] = new SnowFlake();
mFlakes[i].setWidth(new Random().nextInt(mMaxSize-mMinSize) + mMinSize);
mFlakes[i].setHeight(mFlakes[i].getWidth());
mFlakes[i].setX(new Random().nextInt(mViewWidth));
mFlakes[i].setY(-(new Random().nextInt(mViewHeight)));
mFlakes[i].setSpeedY(new Random().nextInt(4) + mSpeedY);
if (isRightDir) {
mFlakes[i].setSpeedX(new Random().nextInt(4) + mSpeedX);
}
else {
mFlakes[i].setSpeedX(-(new Random().nextInt(4) + mSpeedX));
}
}
}
private void updatePara() {
int x;
int y;
for (SnowFlake flake : mFlakes) {
if (flake == null) {
break;
}
x = flake.getX() + flake.getSpeedX();
y = flake.getY() + flake.getSpeedY();
if ((x > mViewWidth + 20 || x < 0)
|| (y > mViewHeight + 20)) {
x = new Random().nextInt(mViewWidth);
y = 0;
}
flake.setX(x);
flake.setY(y);
}
}
private void drawView() {
if (mHolder == null) {
return;
}
Canvas canvas = mHolder.lockCanvas();
if (canvas == null) {
return;
}
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
drawSnow(canvas);
mHolder.unlockCanvasAndPost(canvas);
}
private void drawSnow(Canvas canvas) {
Rect rect = new Rect();
Paint paint = new Paint();
for (SnowFlake flake : mFlakes) {
rect.left = flake.getX();
rect.top = flake.getY();
rect.right = rect.left + flake.getWidth();
rect.bottom = rect.top + flake.getHeight();
canvas.drawBitmap(mSnowBitmap, null, rect, paint);
}
}
@Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
mStart = (visibility == VISIBLE);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
initSnowFlakes();
start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//--- measure the view's width
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY) {
mViewWidth = MeasureSpec.getSize(widthMeasureSpec);
} else {
mViewWidth = (getPaddingStart() + mSnowBitmap.getWidth() + getPaddingEnd());
}
//--- measure the view's height
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) {
mViewHeight = MeasureSpec.getSize(heightMeasureSpec);
} else {
mViewHeight = (getPaddingTop() + mSnowBitmap.getHeight() + getPaddingBottom());
}
setMeasuredDimension(mViewWidth, mViewHeight);
}
public void start() {
new Thread(){
@Override
public void run() {
while (true) {
try {
if (mStart) {
updatePara();
drawView();
}
Thread.sleep(20);
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}
}.start();
}
}
image.gif
另一种直接继承View
public class FallingView extends View {
private boolean mStart = false;
private List<FallObject> fallObjects;
private int viewWidth;
private int viewHeight;
private static final int defaultWidth = 600;//默认宽度
private static final int defaultHeight = 1000;//默认高度
private static final int intervalTime = 5;//重绘间隔时间
public FallingView(Context context) {
super(context);
init();
}
public FallingView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
fallObjects = new ArrayList<>();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int height = measureSize(defaultHeight, heightMeasureSpec);
int width = measureSize(defaultWidth, widthMeasureSpec);
setMeasuredDimension(width, height);
viewWidth = width;
viewHeight = height;
}
private int measureSize(int defaultSize, int measureSpec) {
int result = defaultSize;
int specMode = View.MeasureSpec.getMode(measureSpec);
int specSize = View.MeasureSpec.getSize(measureSpec);
if (specMode == View.MeasureSpec.EXACTLY) {
result = specSize;
} else if (specMode == View.MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
return result;
}
@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
mStart = (visibility == VISIBLE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 只有在显示的时候才会去绘制
if (mStart){
if (fallObjects.size() > 0) {
for (int i = 0; i < fallObjects.size(); i++) {
//然后进行绘制
fallObjects.get(i).drawObject(canvas);
}
// 隔一段时间重绘一次, 动画效果
getHandler().postDelayed(runnable, intervalTime);
}
}
}
// 重绘线程
private Runnable runnable = new Runnable() {
@Override
public void run() {
invalidate();
}
};
/**
* 向View添加下落物体对象
*
* @param fallObject 下落物体对象
* @param num
*/
public void addFallObject(final FallObject fallObject, final int num) {
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
getViewTreeObserver().removeOnPreDrawListener(this);
for (int i = 0; i < num; i++) {
FallObject newFallObject = new FallObject(fallObject.builder, viewWidth, viewHeight);
fallObjects.add(newFallObject);
}
invalidate();
return true;
}
});
}
}
image.gif
但这种需要一个容器 来设置一些参数
在调用的时候
private void start(){
//初始化一个雪花样式的fallObject
FallObject.Builder builder = new FallObject.Builder(getResources(), R.drawable.hongbao);
FallObject fallObject = builder
.setSpeed(7,true) // 设置物体的初始下落速度
.setSize(50,50,true) // 设置物体大小
.setWind(5,true,true) // 设置风力等级、方向以及随机因素
.build();
fallingView.addFallObject(fallObject,50);//添加50个下落物体对象
}
两种哪种都可以实现, 具体还是看需求
下载地址:https://github.com/xiaobinAndroid421726260/Android_SnowBanner2019_11_5Demo.git
网友评论